Skip to content

Commit fe2a645

Browse files
authored
Merge pull request #713 from imsosleepy/main
[ackku] week 2
2 parents 6720ea5 + f38fc83 commit fe2a645

File tree

5 files changed

+194
-0
lines changed

5 files changed

+194
-0
lines changed

3sum/imsosleepy.java

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// 투포인터 방식으로 구현
2+
// 투포인터의 기본 시간복잡도가 O(2^n)이므로 오름차순으로 정렬하는 O(NlogN)은 마음껏 사용해도 된다.
3+
public List<List<Integer>> threeSum(int[] nums) {
4+
List<List<Integer>> result = new ArrayList<>();
5+
Arrays.sort(nums);
6+
for(int i =0; i< nums.length-2;i++) {
7+
if (i > 0 && nums[i] == nums[i - 1]) continue;
8+
int left = i + 1, right = nums.length - 1;
9+
while (left < right) {
10+
int sum = nums[i] + nums[left] + nums[right];
11+
12+
if (sum == 0) {
13+
result.add(Arrays.asList(nums[i], nums[left], nums[right]));
14+
15+
while (left < right && nums[left] == nums[left + 1]) left++;
16+
while (left < right && nums[right] == nums[right - 1]) right--;
17+
18+
left++;
19+
right--;
20+
} else if (sum < 0) {
21+
left++;
22+
} else {
23+
right--;
24+
}
25+
}
26+
}
27+
return result;
28+
}
29+
30+
31+
// dfs 풀이를 생각했으나 dfs 방식은 무조건 O(2^n)의 결과가 나온다.
32+
// 타임 아웃 오답
33+
public class Solution {
34+
public List<List<Integer>> threeSum(int[] nums) {
35+
Set<List<Integer>> answerSet = new HashSet<>();
36+
nums = Arrays.stream(nums).sorted().toArray();
37+
dfs(nums, 0, new ArrayList<>(), answerSet);
38+
return new ArrayList<>(answerSet);
39+
}
40+
41+
public void dfs(int[] nums, int index, List<Integer> temp, Set<List<Integer>> answerSet) {
42+
if (temp.size() == 3) {
43+
int result = 0;
44+
for (int element : temp) result += element;
45+
if (result == 0) answerSet.add(new ArrayList<>(temp));
46+
return;
47+
}
48+
49+
for (int i = index; i < nums.length; i++) {
50+
temp.add(nums[i]);
51+
dfs(nums, i + 1, temp, answerSet);
52+
temp.remove(temp.size() - 1);
53+
}
54+
}
55+
}

climbing-stairs/imsosleepy.java

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// dfs를 이용한 풀이
2+
// dp 배열을 이용한 것보다 공간복잡도가 상대적으로 낮게 잡힘 40.4mb -> 40.1mb
3+
// 이유가 뭔지는 조금 더 고민해봐야할 듯
4+
class Solution {
5+
public int climbStairs(int n) {
6+
return dfs(n, new HashMap<>());
7+
}
8+
9+
private int dfs(int n, Map<Integer, Integer> memo) {
10+
if (n == 0) {
11+
return 1;
12+
}
13+
if (n < 0) {
14+
return 0;
15+
}
16+
if (memo.containsKey(n)) {
17+
return memo.get(n);
18+
}
19+
20+
int result = dfs(n - 1, memo) + dfs(n - 2, memo);
21+
memo.put(n, result);
22+
23+
return result;
24+
}
25+
}
26+
27+
// 가장 먼저 생각한 풀이
28+
// 피보나치 수열의 형태의 결과물을 갖는다.
29+
// O(N)의 점화식을 세울 수 있으면 어느 방식으로도 풀림
30+
class Solution {
31+
public int climbStairs(int n) {
32+
if(n == 1) return 1;
33+
if(n == 2) return 2;
34+
35+
int[] dp = new int[n + 1];
36+
dp[1] = 1; // 1
37+
dp[2] = 2; // 1+1, 2
38+
39+
for (int i = 3; i <= n; i++) {
40+
dp[i] = dp[i-1] + dp[i-2];
41+
}
42+
43+
return dp[n];
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// 혼자서 못풀어서 GPT의 도움을 받음
2+
// 왜 두 배열이 필요한가?
3+
// 전위 순회(preorder): 트리의 루트를 가장 먼저 방문합니다. 그 후 왼쪽 서브트리, 오른쪽 서브트리를 방문합니다. 하지만 이 정보만으로는 각 서브트리가 어느 부분인지, 그리고 그 서브트리의 구체적인 구성 요소가 무엇인지를 알 수 없습니다.
4+
//
5+
// 중위 순회(inorder): 트리의 왼쪽 서브트리를 먼저 방문하고, 루트를 방문한 후, 오른쪽 서브트리를 방문합니다. 이 배열을 통해 루트가 트리의 어느 위치에 있는지 확인할 수 있습니다. 루트의 위치를 알면, 그 위치를 기준으로 왼쪽과 오른쪽 서브트리를 나눌 수 있습니다.
6+
7+
// 한 배열로는 트리의 구조를 복원할 수 없는 이유
8+
// 전위 순회만으로는 각 노드의 왼쪽 자식인지 오른쪽 자식인지 알 수 없습니다. 예를 들어, [3, 9, 20, 15, 7]라는 전위 순회 배열만 있다면, '9'가 3의 왼쪽 자식인지 오른쪽 자식인지 알 수 없습니다.
9+
// 중위 순회만으로도 트리의 루트를 알 수 없으므로, 각 서브트리의 구체적인 구조를 알 수 없습니다.
10+
class Solution {
11+
public TreeNode buildTree(int[] preorder, int[] inorder) {
12+
return buildTreeHelper(preorder, inorder, 0, 0, inorder.length - 1);
13+
}
14+
15+
private TreeNode buildTreeHelper(int[] preorder, int[] inorder, int preStart, int inStart, int inEnd) {
16+
if (inStart > inEnd) return null;
17+
18+
int rootVal = preorder[preStart];
19+
TreeNode root = new TreeNode(rootVal);
20+
21+
int rootIndex = -1;
22+
for (int i = inStart; i <= inEnd; i++) {
23+
if (inorder[i] == rootVal) {
24+
rootIndex = i;
25+
break;
26+
}
27+
}
28+
29+
int leftSize = rootIndex - inStart;
30+
root.left = buildTreeHelper(preorder, inorder, preStart + 1, inStart, rootIndex - 1);
31+
root.right = buildTreeHelper(preorder, inorder, preStart + leftSize + 1, rootIndex + 1, inEnd);
32+
33+
return root;
34+
}
35+
36+
}

decode-ways/imsosleepy.java

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// 메인 로직은 맞았는데, 0번째 1번째 때문에 빙빙 돌았던 문제
2+
// dp[0] = 1이 있어야 두자리 수 디코딩의 초기값이 정상적으로 계산된다.
3+
class Solution {
4+
public int numDecodings(String s) {
5+
if (s == null || s.length() == 0) return 0;
6+
7+
int n = s.length();
8+
int[] dp = new int[n + 1];
9+
10+
dp[0] = 1;
11+
dp[1] = s.charAt(0) != '0' ? 1 : 0;
12+
13+
for (int i = 2; i <= n; i++) {
14+
if (s.charAt(i - 1) != '0') {
15+
dp[i] += dp[i - 1];
16+
}
17+
int twoDigit = Integer.parseInt(s.substring(i - 2, i));
18+
if (twoDigit >= 10 && twoDigit <= 26) {
19+
dp[i] += dp[i - 2];
20+
}
21+
}
22+
23+
return dp[n];
24+
}
25+
}

valid-anagram/imsosleepy.java

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// 자바에서는 시간복잡도를 O(N)으로 잡아도 최상위권으로 갈 수 없는 문제
2+
// 유니코드 고려
3+
public boolean isAnagram(String s, String t) {
4+
if (s.length() != t.length()) return false;
5+
6+
Map<Character, Integer> map = new HashMap<>();
7+
for (int i = 0; i < s.length(); i++) {
8+
map.put(s.charAt(i), map.getOrDefault(s.charAt(i), 0) + 1);
9+
map.put(t.charAt(i), map.getOrDefault(t.charAt(i), 0) - 1);
10+
}
11+
for (int value : map.values()) {
12+
if (value != 0) return false;
13+
}
14+
return true;
15+
}
16+
// 알파벳만 고려
17+
public boolean isAnagram(String s, String t) {
18+
int ALPHABET_COUNT = 26;
19+
if(s.length() != t.length()) {
20+
return false;
21+
}
22+
int[] arr = new int[ALPHABET_COUNT]; // 알파벳 갯수
23+
for(int i = 0; i < s.length() ; i ++) {
24+
arr[s.charAt(i) - 97]++;
25+
arr[t.charAt(i) - 97]--;
26+
}
27+
for(int i = 0; i < ALPHABET_COUNT; i ++) {
28+
if(arr[i] != 0) {
29+
return false;
30+
}
31+
}
32+
return true;
33+
}

0 commit comments

Comments
 (0)