Skip to content

Commit 5087585

Browse files
authored
Merge pull request #1227 from Yn3-3xh/main
[Yn3-3xh] WEEK 02 solutions
2 parents 23a5596 + 132163f commit 5087585

File tree

5 files changed

+288
-0
lines changed

5 files changed

+288
-0
lines changed

3sum/Yn3-3xh.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
[문제풀이]
3+
- nums 배열 안의 3가지 수를 더했을 때 0이어야 한다.
4+
- 더해진 수들의 index는 모두 달라야 한다.
5+
- DFS (X)
6+
StackOverflowError
7+
- 투 포인터 (O)
8+
time: O(N^2), space: O(N^2)
9+
10+
[회고]
11+
해설을 보고 이해는 했는데 다시 풀 수 있을까?
12+
아직 스킬이 부족한 것 같다..
13+
14+
*/
15+
class Solution {
16+
public List<List<Integer>> threeSum(int[] nums) {
17+
Set<List<Integer>> answers = new HashSet<>();
18+
Arrays.sort(nums);
19+
20+
for (int start = 0; start < nums.length; start++) {
21+
int mid = start + 1;
22+
int end = nums.length - 1;
23+
24+
while (mid < end) {
25+
int sum = nums[start] + nums[mid] + nums[end];
26+
if (sum == 0) {
27+
List<Integer> answer = List.of(nums[start], nums[mid], nums[end]);
28+
answers.add(answer);
29+
end--;
30+
} else if (sum < 0) {
31+
mid++;
32+
} else if (sum > 0) {
33+
end--;
34+
}
35+
}
36+
}
37+
return new ArrayList<>(answers);
38+
}
39+
}

climbing-stairs/Yn3-3xh.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
[문제풀이]
3+
- 1 또는 2로 n을 만들 수 있는 전체 가지수 구하기
4+
- dfs (X) 시간초과
5+
class Solution {
6+
7+
public int climbStairs(int n) {
8+
return dfs(n);
9+
}
10+
11+
private int dfs(int n) {
12+
if (n == 0) {
13+
return 1;
14+
}
15+
if (n < 0) {
16+
return 0;
17+
}
18+
return dfs(n - 1) + dfs(n - 2);
19+
}
20+
}
21+
22+
- DP (O)
23+
time: O(N), space: O(1)
24+
25+
[회고]
26+
규칙을 찾으려고 했었는데 못찾았다..
27+
피보나치 수열.. 풀었던 문제인데.. 생각하자;
28+
F(N) = F(n-1) + F(n-2)
29+
*/
30+
class Solution {
31+
32+
public int climbStairs(int n) {
33+
if (n <= 3) {
34+
return n;
35+
}
36+
37+
int prev1 = 3;
38+
int prev2 = 2;
39+
int current = 0;
40+
for (int i = 4; i <= n; i++) {
41+
current = prev1 + prev2;
42+
prev2 = prev1;
43+
prev1 = current;
44+
}
45+
return current;
46+
}
47+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
[문제풀이]
3+
- 본인 index를 제외한 모든 index의 수를 곱하자.
4+
- O(N)으로 풀자.
5+
- 나눗셈은 사용하지 말자.
6+
7+
index 0 1 2 3
8+
num 1 2 3 4
9+
prefix 1 1 2 6
10+
11+
index 0 1 2 3
12+
num 1 2 3 4
13+
suffix 24 12 4 1
14+
15+
answer = prefix * suffix
16+
24 12 8 6
17+
18+
- 풀이 1
19+
time: O(N), space: O(N)
20+
class Solution {
21+
public int[] productExceptSelf(int[] nums) {
22+
int len = nums.length;
23+
int[] answer = new int[len];
24+
int[] prefix = new int[len];
25+
int[] suffix = new int[len];
26+
27+
prefix[0] = 1;
28+
suffix[len - 1] = 1;
29+
for (int i = 1; i < len; i++) {
30+
prefix[i] = prefix[i - 1] * nums[i - 1];
31+
}
32+
for (int i = len - 2; i >= 0; i--) {
33+
suffix[i] = suffix[i + 1] * nums[i + 1];
34+
}
35+
36+
for (int i = 0; i < len; i++) {
37+
answer[i] = prefix[i] * suffix[i];
38+
}
39+
return answer;
40+
}
41+
}
42+
43+
- 풀이 2
44+
time: O(N), space: O(1)
45+
46+
47+
[회고]
48+
본인 index가 아닌 "앞의 수들의 곱"과 "뒤의 수들의 곱" 을 어떻게 구할 수 있을까?
49+
의 고민에서 방법을 찾지 못했다.
50+
51+
풀이방법을 보고 변수와 반복문을 더 쓰기 싫어하는 부분에서 아이디어가 닫힌 것 같다..
52+
우선 많이 써보고 줄이는 방법으로 풀어보자.
53+
*/
54+
class Solution {
55+
public int[] productExceptSelf(int[] nums) {
56+
int len = nums.length;
57+
58+
int[] answer = new int[len];
59+
answer[0] = 1;
60+
for (int i = 1; i < len; i++) {
61+
answer[i] = answer[i - 1] * nums[i - 1];
62+
}
63+
64+
int suffixMul = 1;
65+
for (int i = len - 2; i >= 0; i--) {
66+
suffixMul *= nums[i + 1];
67+
answer[i] *= suffixMul;
68+
}
69+
return answer;
70+
}
71+
}

valid-anagram/Yn3-3xh.java

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
[문제풀이]
3+
- char 배열로 맞춰보자 (x)
4+
- s와 t의 길이가 같아야 한다.
5+
- 각 철자의 개수가 s와 t 모두 일치하는지 확인한다. (테스트케이스 하나 실패)
6+
7+
- s 철자의 개수를 세어 놓고, t 철자의 개수는 하나씩 빼서 0을 체크해보자. Map (O)
8+
time: O(N), space: O(N)
9+
class Solution {
10+
public boolean isAnagram(String s, String t) {
11+
if (s.length() != t.length()) {
12+
return false;
13+
}
14+
15+
Map<Character, Integer> counting = new HashMap<>();
16+
for (char ch : s.toCharArray()) {
17+
counting.put(ch, counting.getOrDefault(ch, 0) + 1);
18+
}
19+
for (char ch : t.toCharArray()) {
20+
if (!counting.containsKey(ch)) {
21+
return false;
22+
}
23+
counting.put(ch, counting.get(ch) - 1);
24+
}
25+
26+
return counting.values().stream()
27+
.allMatch(count -> count == 0);
28+
}
29+
}
30+
31+
- Arrays로 정렬 및 비교를 해보자. (O)
32+
time: O(NlogN), space: O(N)
33+
class Solution {
34+
public boolean isAnagram(String s, String t) {
35+
if (s.length() != t.length()) {
36+
return false;
37+
}
38+
39+
char[] sToCharArray = s.toCharArray();
40+
char[] tToCharArray = t.toCharArray();
41+
Arrays.sort(sToCharArray);
42+
Arrays.sort(tToCharArray);
43+
44+
return Arrays.equals(sToCharArray, tToCharArray);
45+
}
46+
}
47+
48+
- s 철자의 개수를 세어 놓고, t 철자의 개수는 하나씩 빼서 0을 체크해보자. Array (O)
49+
time: O(N), space: O(1)
50+
51+
[회고]
52+
Arrays처럼 자바에서 제공해주는 util을 잘 활용하지 못한 것 같다.. (띵킹하자!)
53+
54+
처음 성공한 솔루션 접근법은 좋았는데 왜 성능이 안나왔나..
55+
HashMap은 내부적으로 해시 테이블 구조를 사용하므로, 동일한 데이터를 저장하더라도 배열보다 메모리를 더 많이 사용한다.
56+
또한, 키와 값을 객체 타입으로 저장하기 때문에 오토박싱/언박싱 비용이 발생하고, 해시 계산과 충돌 처리 등의 추가 연산이 필요하다.
57+
따라서 배열에 비해 느린 것 같다.
58+
*/
59+
class Solution {
60+
public boolean isAnagram(String s, String t) {
61+
if (s.length() != t.length()) {
62+
return false;
63+
}
64+
65+
int[] counting = new int[26];
66+
for (char ch : s.toCharArray()) {
67+
counting[ch - 'a']++;
68+
}
69+
for (char ch : t.toCharArray()) {
70+
counting[ch - 'a']--;
71+
}
72+
73+
for (int count : counting) {
74+
if (count != 0) {
75+
return false;
76+
}
77+
}
78+
return true;
79+
}
80+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
[문제풀이]
3+
- node의 왼쪽은 작아야 한다.
4+
- node의 오른쪽은 커야 한다.
5+
- 2^31 - 1 까지면 int
6+
- 범위는 long
7+
8+
- dfs로 풀자 (O)
9+
time: O(N), space: O(N)
10+
11+
[회고]
12+
!!! int 범위이지만 비교를 위해서는 더 큰 단위가 필요하므로 Long을 사용해야 한다 !!!
13+
14+
leftMaxVal, rightMinVal 네이밍은
15+
왼쪽 노드는 root가 커야 해서 leftMaxVal,
16+
오른쪽 노드는 root가 작아야 해서 rightMinVal로
17+
조금 더 직관적으로 지어봤다. (조건문도 마찬가지)
18+
*/
19+
20+
/**
21+
* Definition for a binary tree node.
22+
* public class TreeNode {
23+
* int val;
24+
* TreeNode left;
25+
* TreeNode right;
26+
* TreeNode() {}
27+
* TreeNode(int val) { this.val = val; }
28+
* TreeNode(int val, TreeNode left, TreeNode right) {
29+
* this.val = val;
30+
* this.left = left;
31+
* this.right = right;
32+
* }
33+
* }
34+
*/
35+
class Solution {
36+
public boolean isValidBST(TreeNode root) {
37+
return dfs(root, Long.MAX_VALUE, Long.MIN_VALUE);
38+
}
39+
40+
private boolean dfs(TreeNode node, long leftMaxVal, long rightMinVal) {
41+
if (node == null) {
42+
return true;
43+
}
44+
45+
if (!(node.val < leftMaxVal) || !(node.val > rightMinVal)) {
46+
return false;
47+
}
48+
49+
return dfs(node.left, node.val, rightMinVal) && dfs(node.right, leftMaxVal, node.val);
50+
}
51+
}

0 commit comments

Comments
 (0)