diff --git a/coin-change/forest000014.java b/coin-change/forest000014.java new file mode 100644 index 000000000..45d4cff91 --- /dev/null +++ b/coin-change/forest000014.java @@ -0,0 +1,28 @@ +/* +Time Complexity: O(coins.length * amount) +Space Complexity: O(amount) + +1 ~ i-1원까지의 최적해를 알고 있다면, i원의 최적해를 구할 때 coins 배열 iteration으로 구할 수 있음 +*/ +class Solution { + public int coinChange(int[] coins, int amount) { + int c = coins.length; + + int[] dp = new int[amount + 1]; + Arrays.fill(dp, 99999); + dp[0] = 0; + + for (int i = 1; i <= amount; i++) { + for (int j = 0; j < c; j++) { + if (i - coins[j] < 0) { + continue; + } + if (dp[i - coins[j]] >= 0 && dp[i - coins[j]] + 1 < dp[i]) { + dp[i] = dp[i - coins[j]] + 1; + } + } + } + + return dp[amount] == 99999 ? -1 : dp[amount]; + } +} diff --git a/merge-two-sorted-lists/forest000014.java b/merge-two-sorted-lists/forest000014.java new file mode 100644 index 000000000..4a31f1313 --- /dev/null +++ b/merge-two-sorted-lists/forest000014.java @@ -0,0 +1,35 @@ +/** + + (n = list1.length + list2.length) + 시간 복잡도: O(n) + - 최악의 경우 전체 노드 순회 + 공간 복잡도: O(n) + - 최악의 경우 전체 노드만큼 새 노드 생성 + + */ +class Solution { + public ListNode mergeTwoLists(ListNode list1, ListNode list2) { + ListNode head = new ListNode(); + ListNode curr = head; + + while (list1 != null && list2 != null) { + if (list1.val <= list2.val) { + curr.next = new ListNode(list1.val); + curr = curr.next; + list1 = list1.next; + } else { + curr.next = new ListNode(list2.val); + curr = curr.next; + list2 = list2.next; + } + } + + if (list1 == null) { + curr.next = list2; + } else if (list2 == null) { + curr.next = list1; + } + + return head.next; + } +} diff --git a/missing-number/forest000014.java b/missing-number/forest000014.java new file mode 100644 index 000000000..ddac2e98f --- /dev/null +++ b/missing-number/forest000014.java @@ -0,0 +1,16 @@ +/* +시간 복잡도: O(n) +공간 복잡도: O(1) + +1 ~ n의 합이 n * (n + 1) / 2 라는 점을 활용 +*/ +class Solution { + public int missingNumber(int[] nums) { + int n = nums.length; + int ans = n * (n + 1) / 2; + for (int i = 0; i < n; i++) { + ans -= nums[i]; + } + return ans; + } +} diff --git a/palindromic-substrings/forest000014.java b/palindromic-substrings/forest000014.java new file mode 100644 index 000000000..42e69387d --- /dev/null +++ b/palindromic-substrings/forest000014.java @@ -0,0 +1,38 @@ +/* +time complexity: O(n^2) +space complexity: O(1) + +모든 가능한 조합(O(n^2))에 대해 palindrome 여부를 검사(O(n))하는 brute force는 O(n^3). +i번째 문자에서 시작하여, 앞/뒤로 한 글자씩 늘려가면서 탐색하되, 한번이라도 앞/뒤 글자가 서로 다르다면 그 이후는 탐색하지 않을 수 있음. 이 경우는 O(n^2). +*/ +class Solution { + public int countSubstrings(String s) { + int ans = 0; + for (int i = 0; i < s.length(); i++) { + int head = i, tail = i; + while (head >= 0 && tail < s.length()) { + if (s.charAt(head) == s.charAt(tail)) { + ans++; + } else { + break; + } + head--; + tail++; + } + + head = i; + tail = i + 1; + while (head >= 0 && tail < s.length()) { + if (s.charAt(head) == s.charAt(tail)) { + ans++; + } else { + break; + } + head--; + tail++; + } + } + + return ans; + } +} diff --git a/word-search/forest000014.java b/word-search/forest000014.java new file mode 100644 index 000000000..f151e9fe8 --- /dev/null +++ b/word-search/forest000014.java @@ -0,0 +1,84 @@ +/* +Time Complexity: O(m * n * 4^(word.length)) +Space Complexity: O(m * n) +*/ + +class Solution { + boolean[][] visited; + int m, n; + int len; + int[] dr = {-1, 0, 1, 0}; // clockwise traversal + int[] dc = {0, 1, 0, -1}; + char board2[][]; + String word2; + + public boolean exist(char[][] board, String word) { + int[] cnt = new int[52]; + board2 = board; + word2 = word; + m = board.length; + n = board[0].length; + visited = new boolean[m][n]; + len = word.length(); + + // 1. for pruning, count characters in board and word respectively + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + cnt[charToInt(board[i][j])]++; + } + } + for (int i = 0; i < len; i++) { + int idx = charToInt(word.charAt(i)); + if (--cnt[idx] < 0) { + return false; + } + } + + // 2. DFS + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (board2[i][j] != word.charAt(0)) { + continue; + } + if (dfs(i, j, 1)) { + return true; + } + } + } + return false; + } + + private boolean dfs(int row, int col, int idx) { + if (idx == len) { // end of word + return true; + } + visited[row][col] = true; + + for (int i = 0; i < 4; i++) { + int nr = row + dr[i]; + int nc = col + dc[i]; + if (nr < 0 || nr >= m || nc < 0 || nc >= n) { // check boundary of the board + continue; + } + if (visited[nr][nc]) { // check visited + continue; + } + if (board2[nr][nc] == word2.charAt(idx)) { + if (dfs(nr, nc, idx + 1)) { + return true; + } + } + } + + visited[row][col] = false; + return false; + } + + private int charToInt(char ch) { + if (ch <= 'Z') { + return ch - 'A'; + } else { + return ch - 'a' + 26; + } + } +}