Skip to content
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

[GangBean] Week 2 #707

Merged
merged 5 commits into from
Dec 20, 2024
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
48 changes: 48 additions & 0 deletions 3sum/GangBean.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
/**
1. understanding
- integer array nums, find the whole combination of 3 nums, and the sum of the 3 nums equal to 0. And don't allow reusing same indiced number(but can duplicate in value)
2. solve strategy
- brute force
- in every combination, validate sum of the nums equal to 0
- but it can take O(N^3) times where N is the length of input array, and given that the N can be 3000 at most(3 * 10^3), time can be 27 * 10^9, which takes too long...
- sort and two pointers
- sort nums in ascending order, so move the left pointer to right means the sum of window is getting bigger.
- and mid pointer set to left + 1 index
- if sum of pointers is less than 0, then move mid pointer to right, until the sum is bigger than 0, and while processing them, if the sum of pointers is 0, then add the combination to the return list.
- [-4, -1, -1, 0, 1, 2]:

3. complexity
- time: O(N^2) -> each left pointer, you can search at most N-1, and left pointer's range is [0, N-1), so the max length is N-1 for left index pointer.
- space: O(1) -> no extra space is needed
*/
// 0. assign return variable Set
Set<List<Integer>> answer = new HashSet<>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

중복을 피하려고 Set을 사용한게 인상깊네요..!


// 1. sort the num array in ascending order
Arrays.sort(nums); // O(NlogN)
// Arrays.stream(nums).forEach(System.out::println);

// 3. move the mid pointer from left to right to find the combination of which's sum is 0, and if the sum is over 0, and then move right pointer to the left. else if the sum is under 0, then move left pointer to right direction.
for (int left = 0; left < nums.length - 1; left++) {
int mid = left + 1;
int right = nums.length - 1;
while (mid < right) {
// System.out.println(String.format("%d,%d,%d", nums[left], nums[mid], nums[right]));
int sum = nums[left] + nums[mid] + nums[right];
if (sum > 0) {
right--;
} else if (sum == 0) {
answer.add(List.of(nums[left], nums[mid], nums[right]));
right--;
} else {
mid++;
}
}
}

return new ArrayList<>(answer);
}
}

35 changes: 35 additions & 0 deletions climbing-stairs/GangBean.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
class Solution {
public int climbStairs(int n) {
/**
1. Understanding
- return the count of ways to climb up to top
- way means the sequence of step count
- each state, there can be 2 ways. first climb 1 step, second climb 2 step
2. solve strategy
- assume the count of ways to climb up to K th stairs is C[K].
- then, C[0] = 1, C[1] = 1, C[2] = 2(because, you can up to 2nd stair from 0th stair and also from 1st stair.)
- and C[3] = C[2] + C[1], C[4] = C[3] + C[2], ... etc...
- so we can fomulate C[k] = C[k-1] + C[k-2]
- iterate over 0 to n, you can caculate C[k].
- and finally return C[n] is the answer.

3. complexity
- I answer to this part, along with coding upon each line description.
*/

// 1. create array to demonstrate each stairs way count to reach that position.
// the maximun step count is 45, so maybe there is over 2^32(approximately 2 billion; so i worry about the overflow), I assign long type array. Oh.. but i catch that return type of this method is integer, so i can assume that maximum value is under integer range. So, assign as integer.
int[] c = new int[n + 1]; // the extra plus 1 means 0th stair state
// space complexity: O(n)
for (int stair = 0; stair <= n; stair++) { // time complexity O(n)
if (stair <= 1) {
c[stair] = 1; // O(1)
continue;
}
c[stair] = c[stair-1] + c[stair-2]; // O(1)
}

return c[n];
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* 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 TreeNode buildTree(int[] preorder, int[] inorder) {
/**
1. understanding
- preorder: mid -> left -> right
- inorder: left -> mid -> right
- so, first element of the preorder array is always mid node.
- if the idx of inorder's 1st depth mid node is k, then inorder[0:k-1] is the left tree part array. And also, preorder[k:] is the right tree part.
2. strategy
- find the inorder's mid node idx, and then split left tree part and right part, buildTree with each preorder and inorder part.

3. complexity
- time: O(N^2)
- space: O(N^2)
*/
if (preorder.length == 0) return null;
if (preorder.length == 1) return new TreeNode(preorder[0]);
int i = 0;
List<Integer> leftPreorder = new ArrayList<>(); // O(N)
List<Integer> leftInorder = new ArrayList<>(); // O(N)
List<Integer> rightPreorder = new ArrayList<>(); // O(N)
List<Integer> rightInorder = new ArrayList<>(); // O(N)
for (; i < inorder.length; i++) { // O(N)
if (inorder[i] == preorder[0]) break;
leftPreorder.add(preorder[i+1]);
leftInorder.add(inorder[i]);
}
for (int idx = i+1; idx < inorder.length; idx++) { // O(N)
rightPreorder.add(preorder[idx]);
rightInorder.add(inorder[idx]);
}

return new TreeNode(preorder[0], buildTree(leftPreorder.stream().mapToInt(Integer::intValue).toArray(), leftInorder.stream().mapToInt(Integer::intValue).toArray()), buildTree(rightPreorder.stream().mapToInt(Integer::intValue).toArray(), rightInorder.stream().mapToInt(Integer::intValue).toArray()));
Comment on lines +31 to +48
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

와; 이렇게 푸시는건 상상을 못했네요. dfs로 풀어보시는 것도 좋을것 같습니다!

}
}

45 changes: 45 additions & 0 deletions decode-ways/GangBean.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
class Solution {
public int numDecodings(String s) {
/**
1. understanding
- number to upper case alphabet mapping code: 1 -> A, ... 26 -> Z
- many ways to decode each input string
- also there can be no way to decode input string.
- answer fits in 32-bit integer.

2. example
- 12: (1, 2), (12)
- 226: (2, 2, 6), (2, 26), (22, 6)
- 06: (0, x)

3. strategy
- iterate in reverse order,
- at index k, dp[k] means the count of decode ways till that index.
- dp[k-1] = 0 if num[k] == 0
- dp[k-1] = dp[k] + dp[k+1] if 1<= nums[k-1:k] < 27
- dp[k-1] = dp[k]
- dp[n] = 1 -> assume that first empty input can be decoded in 1 way.

4. complexity
- time: O(N)
- space: O(1)
*/
int prev = 1;
int current = 1;
for (int i = s.length()-1; i >= 0; i--) { // O(1)
if (s.charAt(i) == '0') {
int tmp = current;
current = 0;
prev = tmp;
} else if ( (i+1) < s.length() && Integer.parseInt(s.substring(i, i+2)) < 27) {
int tmp = current;
current = prev + current;
prev = tmp;
} else {
prev = current;
}
}
return current;
}
}

31 changes: 31 additions & 0 deletions valid-anagram/GangBean.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
class Solution {
public boolean isAnagram(String s, String t) {
/**
1. 문제 이해.
- 아나그램: 문자의 순서만 바뀌었을 때 동일한 글자
- 구성 문자와 숫자만 동일하면 아나그램
2. 풀이 방식
- comapre s.length() with t.length()
- loop over s and t, count each word's character and it's count, and then save it as map(key-value pair structure)
- compare map of s and t
3. Complexity
- time complexity: O(N)
- space complexity: O(N)
*/

if (s.length() != s.length()) return false;

Map<Character, Integer> sMap = new HashMap<>();
Map<Character, Integer> tMap = new HashMap<>();

for (char c: s.toCharArray()) {
sMap.put(c, sMap.getOrDefault(c, 0) + 1);
}
for (char c: t.toCharArray()) {
tMap.put(c, tMap.getOrDefault(c, 0) + 1);
}

return Objects.equals(sMap, tMap);
Comment on lines +18 to +28
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

전 s와 t를 .toCharArray()로 바꾼 후 Arrays.sort -> Arrays.equals() 로 비교했는데 Objects.equals로 HashMap 자체를 비교하는 방법도 있군요. 배워갑니다!

}
}

Loading