diff --git a/coin-change/GangBean.java b/coin-change/GangBean.java new file mode 100644 index 000000000..635f9e8d4 --- /dev/null +++ b/coin-change/GangBean.java @@ -0,0 +1,31 @@ +class Solution { + public int coinChange(int[] coins, int amount) { + /** + 1. understanding + - given coins that can be used, find the minimum count of coins sum up to input amount value. + - [1,2,5]: 11 + - 2 * 5 + 1 * 1: 3 -> use high value coin as much as possible if the remain can be sumed up by remain coins. + 2. strategy + - If you search in greedy way, it will takes over O(min(amount/coin) ^ N), given N is the length of coins. + - Let dp[k] is the number of coins which are sum up to amount k, in a given coin set. + - Then, dp[k] = min(dp[k], dp[k-coin] + 1) + 3. complexity + - time: O(CA), where C is the length of coins, A is amount value + - space: O(A), where A is amount value + */ + + int[] dp = new int[amount + 1]; + for (int i = 1; i <= amount; i++) { + dp[i] = amount + 1; + } + + for (int coin: coins) { // O(C) + for (int k = coin; k <= amount; k++) { // O(A) + dp[k] = Math.min(dp[k], dp[k-coin] + 1); + } + } + + return (dp[amount] >= amount + 1) ? -1 : dp[amount]; + } +} + diff --git a/merge-two-sorted-lists/GangBean.java b/merge-two-sorted-lists/GangBean.java new file mode 100644 index 000000000..60b84752f --- /dev/null +++ b/merge-two-sorted-lists/GangBean.java @@ -0,0 +1,73 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode mergeTwoLists(ListNode list1, ListNode list2) { + /** + 1. understanding + - merge 2 sorted linked list + 2. strategy + - assign return ListNode + - for each node, started in head, compare each node's value, and add smaller value node to return node, and move the node's head to head.next + 3. complexity + - time: O(N + M), N is the length of list1, M is the length of list2 + - space: O(1), exclude the return variable + */ + ListNode curr = null; + ListNode ret = null; + + while (list1 != null && list2 != null) { + if (list1.val < list2.val) { + ListNode node = new ListNode(list1.val); + if (ret == null) { + ret = node; + } else { + curr.next = node; + } + list1 = list1.next; + curr = node; + } else { + ListNode node = new ListNode(list2.val); + if (ret == null) { + ret = node; + } else { + curr.next = node; + } + list2 = list2.next; + curr = node; + } + } + + while (list1 != null) { + ListNode node = new ListNode(list1.val); + if (ret == null) { + ret = node; + } else { + curr.next = node; + } + list1 = list1.next; + curr = node; + } + + while (list2 != null) { + ListNode node = new ListNode(list2.val); + if (ret == null) { + ret = node; + } else { + curr.next = node; + } + list2 = list2.next; + curr = node; + } + + return ret; + } +} + diff --git a/missing-number/GangBean.java b/missing-number/GangBean.java new file mode 100644 index 000000000..bf19c65d8 --- /dev/null +++ b/missing-number/GangBean.java @@ -0,0 +1,19 @@ +class Solution { + public int missingNumber(int[] nums) { + /** + 1. understanding + - array nums, n distinct numbers in range [0, n] + - find missing number + 2. strategy + - you can calculate the sum of range [0, n]: n(n+1)/2 ... (1) + - and the sum of nums ... (2) + - and then extract (2) from (1) = (missing value) what we want. + 3. complexity + - time: O(N), N is the length of nums + - space: O(1) + */ + int N = nums.length; + return N*(N+1)/2 - Arrays.stream(nums).sum(); + } +} + diff --git a/palindromic-substrings/GangBean.java b/palindromic-substrings/GangBean.java index ebb22ac35..d690efd01 100644 --- a/palindromic-substrings/GangBean.java +++ b/palindromic-substrings/GangBean.java @@ -1,8 +1,15 @@ class Solution { public int countSubstrings(String s) { /** - 각 문자를 중간으로 갖는 palindrome 여부 체크 - + 두개의 문자를 중간으로 갖는 palindrome 여부 체크 + 1. understanding + - find the number of palindromic substrings + 2. strategy + - iterate over each character, count below substrings + - First, start with same position, move left and right directions each, until two charactes are not same. + - Second, start with i and i + 1 position, move left and right directions until two chracters are not same. + 3. complexity + - time: O(N^2) + - space: O(1) */ int count = 0; int length = s.length(); @@ -27,3 +34,4 @@ public int countSubstrings(String s) { return count; // O(N^2) } } + diff --git a/word-search/GangBean.java b/word-search/GangBean.java new file mode 100644 index 000000000..5901ea044 --- /dev/null +++ b/word-search/GangBean.java @@ -0,0 +1,48 @@ +class Solution { + int[] dx = {0, 1, 0, -1}; + int[] dy = {1, 0, -1, 0}; + public boolean exist(char[][] board, String word) { + /** + 1. understanding + - check if word can be constructed from board, + - start in any block, moving only 4 direction, up, left, below, right + - can't use same block + 2. strategy + - backtracking and dfs + - iterate over each block, if first character matches, find words in depth first search algorithm + - each dfs, mark current block is visited, and find 4 or less possible directions, when any character matches with next character in word, then call dfs in that block recursively + 3. complexity + - time: O(M * N * L), where L is the length of word + - space: O(M * N) which marks if block of the indices is visited or not + */ + boolean[][] isVisited = new boolean[board.length][board[0].length]; + for (int y = 0; y < board.length; y++) { + for (int x = 0; x < board[0].length; x++) { + if (isWordExists(board, isVisited, word, y, x, 0)) return true; + } + } + return false; + } + + private boolean isWordExists(char[][] board, boolean[][] isVisited, String word, int y, int x, int idx) { + if (board[y][x] != word.charAt(idx)) return false; + if (idx == word.length() - 1) return true; + // boolean isExists = false; + isVisited[y][x] = true; + for (int dir = 0; dir < 4; dir++) { + int ny = y + dy[dir]; + int nx = x + dx[dir]; + if (0 <= ny && ny < board.length + && 0 <= nx && nx < board[0].length + && !isVisited[ny][nx] + && word.charAt(idx + 1) == board[ny][nx]) { + isVisited[ny][nx] = true; + if (isWordExists(board, isVisited, word, ny, nx, idx + 1)) return true; + isVisited[ny][nx] = false; + } + } + isVisited[y][x] = false; + return false; + } +} +