Skip to content

[Yn3-3xh] WEEK 02 solutions #1227

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions 3sum/Yn3-3xh.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
[문제풀이]
- nums 배열 안의 3가지 수를 더했을 때 0이어야 한다.
- 더해진 수들의 index는 모두 달라야 한다.
- DFS (X)
StackOverflowError
- 투 포인터 (O)
time: O(N^2), space: O(N^2)

[회고]
해설을 보고 이해는 했는데 다시 풀 수 있을까?
아직 스킬이 부족한 것 같다..

*/
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Set<List<Integer>> answers = new HashSet<>();
Arrays.sort(nums);

for (int start = 0; start < nums.length; start++) {
int mid = start + 1;
int end = nums.length - 1;

while (mid < end) {
int sum = nums[start] + nums[mid] + nums[end];
if (sum == 0) {
List<Integer> answer = List.of(nums[start], nums[mid], nums[end]);
answers.add(answer);
end--;
} else if (sum < 0) {
mid++;
} else if (sum > 0) {
end--;
}
}
}
return new ArrayList<>(answers);
}
}
47 changes: 47 additions & 0 deletions climbing-stairs/Yn3-3xh.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
[문제풀이]
- 1 또는 2로 n을 만들 수 있는 전체 가지수 구하기
- dfs (X) 시간초과
class Solution {

public int climbStairs(int n) {
return dfs(n);
}

private int dfs(int n) {
if (n == 0) {
return 1;
}
if (n < 0) {
return 0;
}
return dfs(n - 1) + dfs(n - 2);
}
}

- DP (O)
time: O(N), space: O(1)

[회고]
규칙을 찾으려고 했었는데 못찾았다..
피보나치 수열.. 풀었던 문제인데.. 생각하자;
F(N) = F(n-1) + F(n-2)
*/
class Solution {

public int climbStairs(int n) {
if (n <= 3) {
return n;
}

int prev1 = 3;
int prev2 = 2;
int current = 0;
for (int i = 4; i <= n; i++) {
current = prev1 + prev2;
prev2 = prev1;
prev1 = current;
}
return current;
}
}
71 changes: 71 additions & 0 deletions product-of-array-except-self/Yn3-3xh.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
[문제풀이]
- 본인 index를 제외한 모든 index의 수를 곱하자.
- O(N)으로 풀자.
- 나눗셈은 사용하지 말자.

index 0 1 2 3
num 1 2 3 4
prefix 1 1 2 6

index 0 1 2 3
num 1 2 3 4
suffix 24 12 4 1

answer = prefix * suffix
24 12 8 6

- 풀이 1
time: O(N), space: O(N)
class Solution {
public int[] productExceptSelf(int[] nums) {
int len = nums.length;
int[] answer = new int[len];
int[] prefix = new int[len];
int[] suffix = new int[len];

prefix[0] = 1;
suffix[len - 1] = 1;
for (int i = 1; i < len; i++) {
prefix[i] = prefix[i - 1] * nums[i - 1];
}
for (int i = len - 2; i >= 0; i--) {
suffix[i] = suffix[i + 1] * nums[i + 1];
}

for (int i = 0; i < len; i++) {
answer[i] = prefix[i] * suffix[i];
}
return answer;
}
}

- 풀이 2
time: O(N), space: O(1)


[회고]
본인 index가 아닌 "앞의 수들의 곱"과 "뒤의 수들의 곱" 을 어떻게 구할 수 있을까?
의 고민에서 방법을 찾지 못했다.

풀이방법을 보고 변수와 반복문을 더 쓰기 싫어하는 부분에서 아이디어가 닫힌 것 같다..
우선 많이 써보고 줄이는 방법으로 풀어보자.
*/
class Solution {
public int[] productExceptSelf(int[] nums) {
int len = nums.length;

int[] answer = new int[len];
answer[0] = 1;
for (int i = 1; i < len; i++) {
answer[i] = answer[i - 1] * nums[i - 1];
}

int suffixMul = 1;
for (int i = len - 2; i >= 0; i--) {
suffixMul *= nums[i + 1];
answer[i] *= suffixMul;
}
return answer;
}
}
80 changes: 80 additions & 0 deletions valid-anagram/Yn3-3xh.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
[문제풀이]
- char 배열로 맞춰보자 (x)
- s와 t의 길이가 같아야 한다.
- 각 철자의 개수가 s와 t 모두 일치하는지 확인한다. (테스트케이스 하나 실패)

- s 철자의 개수를 세어 놓고, t 철자의 개수는 하나씩 빼서 0을 체크해보자. Map (O)
time: O(N), space: O(N)
class Solution {
public boolean isAnagram(String s, String t) {
if (s.length() != t.length()) {
return false;
}

Map<Character, Integer> counting = new HashMap<>();
for (char ch : s.toCharArray()) {
counting.put(ch, counting.getOrDefault(ch, 0) + 1);
}
for (char ch : t.toCharArray()) {
if (!counting.containsKey(ch)) {
return false;
}
counting.put(ch, counting.get(ch) - 1);
}

return counting.values().stream()
.allMatch(count -> count == 0);
}
}

- Arrays로 정렬 및 비교를 해보자. (O)
time: O(NlogN), space: O(N)
class Solution {
public boolean isAnagram(String s, String t) {
if (s.length() != t.length()) {
return false;
}

char[] sToCharArray = s.toCharArray();
char[] tToCharArray = t.toCharArray();
Arrays.sort(sToCharArray);
Arrays.sort(tToCharArray);

return Arrays.equals(sToCharArray, tToCharArray);
}
}

- s 철자의 개수를 세어 놓고, t 철자의 개수는 하나씩 빼서 0을 체크해보자. Array (O)
time: O(N), space: O(1)

[회고]
Arrays처럼 자바에서 제공해주는 util을 잘 활용하지 못한 것 같다.. (띵킹하자!)

처음 성공한 솔루션 접근법은 좋았는데 왜 성능이 안나왔나..
HashMap은 내부적으로 해시 테이블 구조를 사용하므로, 동일한 데이터를 저장하더라도 배열보다 메모리를 더 많이 사용한다.
또한, 키와 값을 객체 타입으로 저장하기 때문에 오토박싱/언박싱 비용이 발생하고, 해시 계산과 충돌 처리 등의 추가 연산이 필요하다.
따라서 배열에 비해 느린 것 같다.
*/
class Solution {
public boolean isAnagram(String s, String t) {
if (s.length() != t.length()) {
return false;
}

int[] counting = new int[26];
for (char ch : s.toCharArray()) {
counting[ch - 'a']++;
}
for (char ch : t.toCharArray()) {
counting[ch - 'a']--;
}

for (int count : counting) {
if (count != 0) {
return false;
}
}
return true;
}
}
51 changes: 51 additions & 0 deletions validate-binary-search-tree/Yn3-3xh.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
[문제풀이]
- node의 왼쪽은 작아야 한다.
- node의 오른쪽은 커야 한다.
- 2^31 - 1 까지면 int
- 범위는 long

- dfs로 풀자 (O)
time: O(N), space: O(N)

[회고]
!!! int 범위이지만 비교를 위해서는 더 큰 단위가 필요하므로 Long을 사용해야 한다 !!!

leftMaxVal, rightMinVal 네이밍은
왼쪽 노드는 root가 커야 해서 leftMaxVal,
오른쪽 노드는 root가 작아야 해서 rightMinVal로
조금 더 직관적으로 지어봤다. (조건문도 마찬가지)
*/

/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean isValidBST(TreeNode root) {
return dfs(root, Long.MAX_VALUE, Long.MIN_VALUE);
}

private boolean dfs(TreeNode node, long leftMaxVal, long rightMinVal) {
if (node == null) {
return true;
}

if (!(node.val < leftMaxVal) || !(node.val > rightMinVal)) {
return false;
}

return dfs(node.left, node.val, rightMinVal) && dfs(node.right, leftMaxVal, node.val);
}
}