diff --git a/Week 02/id_576/LeetCode_144_576.java b/Week 02/id_576/LeetCode_144_576.java new file mode 100644 index 000000000..d7b68b4dc --- /dev/null +++ b/Week 02/id_576/LeetCode_144_576.java @@ -0,0 +1,40 @@ +package id_576; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class LeetCode_144_576 { + + // Approach 1: recursion, O(n) + public List preorderTraversal1(TreeNode root) { + List res = new ArrayList<>(); + helper(root, res); + return res; + } + + private void helper(TreeNode root, List res) { + if (root == null) return; + res.add(root.val); + helper(root.left, res); + helper(root.right, res); + } + + // Approach 2: stack with manual, O(n) + public List preorderTraversal2(TreeNode root) { + List res = new ArrayList<>(); + if (root == null) return res; + Stack stack = new Stack<>(); + TreeNode node = root; + while (node != null || !stack.isEmpty()) { + while (node != null) { + res.add(node.val); + stack.push(node); + node = node.left; + } + node = stack.pop().right; + } + return res; + } + +} diff --git a/Week 02/id_576/LeetCode_145_576.java b/Week 02/id_576/LeetCode_145_576.java new file mode 100644 index 000000000..1b9e07759 --- /dev/null +++ b/Week 02/id_576/LeetCode_145_576.java @@ -0,0 +1,46 @@ +package id_576; + +import javax.naming.InsufficientResourcesException; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Stack; + +public class LeetCode_145_576 { + + // Approach 1: recursion, O(n) + public List postorderTraversal1(TreeNode root) { + List res = new ArrayList<>(); + helper(root, res); + return res; + } + + private void helper(TreeNode root, List res) { + if (root == null) return; + helper(root.left, res); + helper(root.right, res); + res.add(root.val); + } + + // Approach 2: stack with manual, O(n) + /** + * 更为简洁的写法。这种解法的思想是先序遍历的变形, + * 先序遍历是“根->左->右”,后序遍历是“左->右->根”, + * 那么把先序遍历改成“根->右->左”,再逆序一下就是后序遍历。 + * 没太明白意思?再多练习几遍 + * 画一遍图有些理解了,等于是逆序,从后往前存值。 + */ + public List postorderTraversal2(TreeNode root) { + List res = new LinkedList<>(); + if (root == null) return res; + Stack stack = new Stack<>(); + stack.push(root); + while (!stack.isEmpty()) { + TreeNode node = stack.pop(); + res.add(0, node.val); + if (node.left != null) stack.push(node.left); + if (node.right != null) stack.push(node.right); + } + return res; + } +} diff --git a/Week 02/id_576/LeetCode_1_576.java b/Week 02/id_576/LeetCode_1_576.java new file mode 100644 index 000000000..aa47b742e --- /dev/null +++ b/Week 02/id_576/LeetCode_1_576.java @@ -0,0 +1,37 @@ +package id_576; + +import java.util.HashMap; +import java.util.Map; + +public class LeetCode_1_576 { + + // Approach 1: hash table + public int[] twoSum1(int[] nums, int target) { + int[] res = new int[2]; + Map map = new HashMap<>(); + for (int i = 0; i < nums.length; ++i) { + if (map.containsKey(target - nums[i])) { + res[1] = i; + res[0] = map.get(target - nums[i]); + return res; + } + map.put(nums[i], i); + } + return res; + } + + // Approach 2: brute force, O(n^2) + public int[] twoSum2(int[] nums, int target) { + int[] res = new int[2]; + for (int i = 0; i < nums.length - 1; i++) { + for (int j = i + 1; j < nums.length; j++) { + if (nums[i] + nums[j] == target) { + res[0] = i; + res[1] = j; + return res; + } + } + } + return new int[0]; + } +} diff --git a/Week 02/id_576/LeetCode_242_576.java b/Week 02/id_576/LeetCode_242_576.java new file mode 100644 index 000000000..e89bc708c --- /dev/null +++ b/Week 02/id_576/LeetCode_242_576.java @@ -0,0 +1,33 @@ +package id_576; + +import java.util.Arrays; + +public class LeetCode_242_576 { + + + public boolean isAnagram1(String s, String t) { + if (s.length() != t.length()) { + return false; + } + + char[] str1 = s.toCharArray(); + char[] str2 = t.toCharArray(); + Arrays.sort(str1); + Arrays.sort(str2); + return Arrays.equals(str1, str2); + } + + // Approach 2: hash、map,统计每个字符的频次 + public boolean isAnagram2(String s, String t) { + if (s.length() != t.length()) { + return false; + } + int[] counter = new int[26]; + for (int i = 0; i < s.length(); i++) { + counter[s.charAt(i) - 'a']++; + counter[t.charAt(i) - 'a']--; + } + for (int count:counter) if (count != 0) return false; + return true; + } +} diff --git a/Week 02/id_576/LeetCode_49_576.java b/Week 02/id_576/LeetCode_49_576.java new file mode 100644 index 000000000..640522915 --- /dev/null +++ b/Week 02/id_576/LeetCode_49_576.java @@ -0,0 +1,41 @@ +package id_576; + +import java.util.*; + +public class LeetCode_49_576 { + + // Approach 1: sort, O(k * n * logN) + public List> groupAnagrams1(String[] strs) { + if (strs.length == 0) return new ArrayList<>(); + Map> ans = new HashMap<>(); + for (String s : strs) { + char[] ca = s.toCharArray(); + Arrays.sort(ca); + String key = String.valueOf(ca); + if (!ans.containsKey(key)) ans.put(key, new ArrayList<>()); + ans.get(key).add(s); + } + return new ArrayList<>(ans.values()); + } + + // Approach 2: counter, O(k * n * logN) + public List> groupAnagrams2(String[] strs) { + if (strs.length == 0) return new ArrayList<>(); + Map> ans = new HashMap<>(); + int[] count = new int[26]; + for (String s: strs) { + Arrays.fill(count, 0); + for (char c : s.toCharArray()) count[c - 'a']++; + + StringBuilder sb = new StringBuilder(""); + for (int i = 0; i < 26; i++) { + sb.append('#'); + sb.append(count[i]); + } + String key = sb.toString(); + if (!ans.containsKey(key)) ans.put(key, new ArrayList<>()); + ans.get(key).add(s); + } + return new ArrayList<>(ans.values()); + } +} diff --git a/Week 02/id_576/LeetCode_590_576.java b/Week 02/id_576/LeetCode_590_576.java new file mode 100644 index 000000000..e89bc708c --- /dev/null +++ b/Week 02/id_576/LeetCode_590_576.java @@ -0,0 +1,33 @@ +package id_576; + +import java.util.Arrays; + +public class LeetCode_242_576 { + + + public boolean isAnagram1(String s, String t) { + if (s.length() != t.length()) { + return false; + } + + char[] str1 = s.toCharArray(); + char[] str2 = t.toCharArray(); + Arrays.sort(str1); + Arrays.sort(str2); + return Arrays.equals(str1, str2); + } + + // Approach 2: hash、map,统计每个字符的频次 + public boolean isAnagram2(String s, String t) { + if (s.length() != t.length()) { + return false; + } + int[] counter = new int[26]; + for (int i = 0; i < s.length(); i++) { + counter[s.charAt(i) - 'a']++; + counter[t.charAt(i) - 'a']--; + } + for (int count:counter) if (count != 0) return false; + return true; + } +} diff --git a/Week 02/id_576/LeetCode_94_576.java b/Week 02/id_576/LeetCode_94_576.java new file mode 100644 index 000000000..38dc54b9c --- /dev/null +++ b/Week 02/id_576/LeetCode_94_576.java @@ -0,0 +1,43 @@ +package id_576; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class LeetCode_94_576 { + + + // Approach 1: recursion, O(n) + public List inorderTraversal1(TreeNode root) { + List res = new ArrayList<>(); + helper(root, res); + return res; + } + + private void helper(TreeNode root, List res) { + if (root != null) { + if (root.left != null) helper(root.left, res); + res.add(root.val); + if (root.right != null) helper(root.right, res); + } + } + + // Approach 2: create a stack with manual, O(n) + public List inorderTraversal2(TreeNode root) { + List res = new ArrayList<>(); + Stack stack = new Stack<>(); + TreeNode node = root; + while (node != null || !stack.isEmpty()) { + while (node != null) { + stack.push(node); + node = node.left; + } + node = stack.pop(); + res.add(node.val); + node = node.right; + } + return res; + } + + +} diff --git a/Week 03/id_576/LeetCode_102_576.java b/Week 03/id_576/LeetCode_102_576.java new file mode 100644 index 000000000..e31eef81c --- /dev/null +++ b/Week 03/id_576/LeetCode_102_576.java @@ -0,0 +1,48 @@ +package id_576; + +import jdk.nashorn.api.tree.Tree; + +import java.time.temporal.Temporal; +import java.util.ArrayList; +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; + +public class LeetCode_102_576 { + + //Approach 1: BFS, O(n) + public List> levelOrder1(TreeNode root) { + List> res = new ArrayList<>(); + if (root == null) return res; + Deque queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + List tmp = new ArrayList<>(); + int cnt = queue.size(); + for (int i = 0; i < cnt; i++) {//为什么直接写queue.size()会报错? + // 因为queue.size()在循环体里值不会改变,需要借助变量cnt改变 + TreeNode node = queue.poll(); + tmp.add(node.val); + if (node.left != null) queue.add(node.left); + if (node.right != null) queue.add(node.right); + } + res.add(tmp); + } + return res; + } + + //Approach 2: DFS, O(n) + public List> levelOrder2(TreeNode root) { + List> res = new ArrayList<>(); + helper(res, root, 0); + return res; + } + + private void helper(List> res, TreeNode root, int level) { + if (root == null) return; + if (res.size() == level) res.add(new LinkedList<>()); + res.get(level).add(root.val); + helper(res, root.left, level + 1); + helper(res, root.right, level + 1); + } +} diff --git a/Week 03/id_576/LeetCode_200_576.java b/Week 03/id_576/LeetCode_200_576.java new file mode 100644 index 000000000..a060300f4 --- /dev/null +++ b/Week 03/id_576/LeetCode_200_576.java @@ -0,0 +1,24 @@ +package id_576; + +public class LeetCode_200_576 { + + //Approach 1: floodfill, O(M * N) + char[][] g; + public int numIslands(char[][] grid) { + int islands = 0; + g = grid; + for (int i=0; i findWords(char[][] board, String[] words) { + //构建字典树 + wordTrie myTrie=new wordTrie(); + trieNode root=myTrie.root; + for(String s:words) + myTrie.insert(s); + + //使用set防止重复 + Set result =new HashSet<>(); + int m=board.length; + int n=board[0].length; + boolean [][]visited=new boolean[m][n]; + //遍历整个二维数组 + for(int i=0;i(result); + } + private void find(char [] [] board, boolean [][]visited,int i,int j,int m,int n,Set result,trieNode cur){ + //边界以及是否已经访问判断 + if(i<0||i>=m||j<0||j>=n||visited[i][j]) + return; + cur=cur.child[board[i][j]-'a']; + visited[i][j]=true; + if(cur==null) + { + //如果单词不匹配,回退 + visited[i][j]=false; + return; + } + //找到单词加入 + if(cur.isLeaf) + { + result.add(cur.val); + //找到单词后不能回退,因为可能是“ad” “addd”这样的单词得继续回溯 +// visited[i][j]=false; +// return; + } + find(board,visited,i+1,j,m,n,result,cur); + find(board,visited,i,j+1,m,n,result,cur); + find(board,visited,i,j-1,m,n,result,cur); + find(board,visited,i-1,j,m,n,result,cur); + //最后要回退,因为下一个起点可能会用到上一个起点的字符 + visited[i][j]=false; + } + + +} + +//字典树 +class wordTrie{ + public trieNode root=new trieNode(); + public void insert(String s){ + trieNode cur=root; + for(char c:s.toCharArray()){ + if(cur.child[c-'a']==null){ + cur.child [c-'a'] = new trieNode(); + cur=cur.child[c-'a']; + }else + cur=cur.child [c-'a']; + } + cur.isLeaf=true; + cur.val=s; + } +} +//字典树结点 +class trieNode{ + public String val; + public trieNode[] child=new trieNode[26]; + public boolean isLeaf=false; + + trieNode(){ + + } +} diff --git a/Week 06/id_576/LeetCode_547_576.java b/Week 06/id_576/LeetCode_547_576.java index e69de29bb..d6e3fe1b2 100644 --- a/Week 06/id_576/LeetCode_547_576.java +++ b/Week 06/id_576/LeetCode_547_576.java @@ -0,0 +1,53 @@ +package id_576; + +public class LeetCode_547_576 { + + class UnionFind { + private int count = 0; + private int[] parent, rank; + public UnionFind(int n) { + count = n; + parent = new int[n]; + rank = new int[n]; + for (int i = 0; i < n; i++) { + parent[i] = i; + } + } + + public int find(int p) { + while (p != parent[p]) { + parent[p] = parent[parent[p]]; + p = parent[p]; + } + return p; + } + public void union(int p, int q) { + int rootP = find(p); + int rootQ = find(q); + if (rootP == rootQ) return; + if (rank[rootQ] > rank[rootP]) { + parent[rootP] = rootQ; + } else { + parent[rootQ] = rootP; + if (rank[rootP] == rank[rootQ]) { + rank[rootP]++; + } + } + count--; + } + public int count() { + return count; + } + + } + public int findCircleNum(int[][] M) { + int n = M.length; + UnionFind uf = new UnionFind(n); + for (int i = 0; i < n - 1 ; i++) { + for (int j = i + 1; j < n; j++) { + if (M[i][j] == 1) uf.union(i, j); + } + } + return uf.count(); + } +} diff --git a/Week 08/id_576/LeetCode_1143_576.java b/Week 08/id_576/LeetCode_1143_576.java new file mode 100644 index 000000000..f4f3842ae --- /dev/null +++ b/Week 08/id_576/LeetCode_1143_576.java @@ -0,0 +1,28 @@ +package id_576; + +public class LeetCode_1143_576 { + + public int longestCommonSubsequence(String text1, String text2) { + int m = text1.length(); + int n = text2.length(); + int[][] dp = new int[m + 1][n + 1]; + for (int i = 1; i < m + 1; i++) { + for (int j = 1; j < n + 1; j++) { + if (text1.charAt(i) == text2.charAt(j)) { + //需要注意数组越界的问题 + dp[i][j] = dp[i - 1][j - 1] + 1; + } + dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); + } + } + return dp[m][n]; + } + + /** + * 如果是最长公共子串,dp方程将改为 + * dp[i][j] = dp[i-1][j-1] + 1(if s1[i-1] == s2[j-1]) + * else dp[i][j] = 0 + * + * return Max(dp[i][j]) + */ +} diff --git a/Week 08/id_576/LeetCode_14_576.java b/Week 08/id_576/LeetCode_14_576.java new file mode 100644 index 000000000..05938dd50 --- /dev/null +++ b/Week 08/id_576/LeetCode_14_576.java @@ -0,0 +1,33 @@ +package id_576; + +public class LeetCode_14_576 { + + /** + * 1.brute + * 2. approach 1 + * 3. Trie + * @param strs + * @return + */ + public String longestCommonPrefix1(String[] strs) { + if (strs == null || strs.length == 0) return ""; + for (int i = 0; i < strs[0].length(); i++) { + char c = strs[0].charAt(i); + for (int j = 1; j < strs.length ; j++) { + if (i == strs[j].length() || strs[j].charAt(i) != c) + return strs[0].substring(0, i); + } + } + return strs[0]; + } + + public String longestCommonPrefix2(String[] strs) { + + return null; + } + + public String longestCommonPrefix3(String[] strs) { + + return null; + } +} diff --git a/Week 08/id_576/LeetCode_387_576.java b/Week 08/id_576/LeetCode_387_576.java new file mode 100644 index 000000000..afbf5433e --- /dev/null +++ b/Week 08/id_576/LeetCode_387_576.java @@ -0,0 +1,35 @@ +package id_576; + +import java.util.HashMap; +import java.util.Map; + + +public class LeetCode_387_576 { + + // Approach 1: Map(hashmap(O(1)), treemap(O(logN))) and for loop, O(n)/O(nlogn) + public int firstUniqChar1(String s) { + Map res = new HashMap(); + for (int i = 0; i < s.length(); i++) { + res.put(s.charAt(i), res.getOrDefault(s.charAt(i), 0) + 1); + } + + for (int i = 0; i < s.length(); i++) { + if (res.get(s.charAt(i)) == 1) { + return i; + } + } + return -1; + } + + // Approach 2: brute-force, O(n^2),i 枚举所有字符,j枚举i后面的所有字符 + public int firstUniqChar2(String s) { + + return 0; + } + + // Approach 3: hash table + public int firstUniqChar3(String s) { + + return 0; + } +} diff --git a/Week 08/id_576/LeetCode_5_576.java b/Week 08/id_576/LeetCode_5_576.java new file mode 100644 index 000000000..a8cc69d1f --- /dev/null +++ b/Week 08/id_576/LeetCode_5_576.java @@ -0,0 +1,56 @@ +package id_576; + +public class LeetCode_5_576 { + + /** + * 1. brute 嵌套循环,枚举 i, j(起点和终点),判断子串是否是回文串, O(n^3) + * 2. 枚举中心,向两边扩张O(n^2) + * 3. DP + * @param s + * @return + */ + public String longestPalindrome1(String s) { + int n = s.length(); + String res = ""; + boolean[][] dp = new boolean[n][n]; + for (int i = n - 1; i >= 0; i--) { + for (int j = i; j < n; j++) { + dp[i][j] = s.charAt(i) == s.charAt(j) && + (j - i < 2 || dp[i + 1][j - 1]); + + if (dp[i][j] && j - i + 1 > res.length()) { + res = s.substring(i, j + 1); + } + } + } + return res; + } + + private int lo, maxlen; + public String longestPalindrome2(String s) { + int len = s.length(); + if (len < 2) { + return s; + } + + for (int i = 0; i < len - 1; i++) { + extendPalindrome(s, i, i); // odd length + extendPalindrome(s, i, i + 1); // even length + } + + return s.substring(lo, lo + maxlen); + } + + private void extendPalindrome(String s, int j, int k) { + while (j >= 0 && k < s.length() && s.charAt(j) == s.charAt(k)) { + j--; k++; + } + + if (maxlen < k - j - 1) { + lo = j + 1; + maxlen = k - j - 1; + } + } + + +} diff --git a/Week 08/id_576/LeetCode_72_576.java b/Week 08/id_576/LeetCode_72_576.java new file mode 100644 index 000000000..8669660e6 --- /dev/null +++ b/Week 08/id_576/LeetCode_72_576.java @@ -0,0 +1,36 @@ +package id_576; + +public class LeetCode_72_576 { + + // Approach1: BFS, twe-ended BFS + public int minDistance1(String word1, String word2) { + + return 0; + } + + // Approach2: DP + /** + * dp[i] 如何定义? + * dp[i][j] // word1.substr(0,i) 与 + * word2.substr(0,j) 之间的编辑距离 + * 感觉跟uniquepath那道题差不多 + */ + + public int minDistance2(String word1, String word2) { + int n1 = word1.length(); + int n2 = word2.length(); + int[][] dp = new int[n1 + 1][n2 + 1]; + // first row + for (int j = 1; j <= n2 ; j++) dp[0][j] = dp[0][j - 1] + 1; + // first col + for (int i = 1; i <= n1 ; i++) dp[i][0] = dp[i - 1][0] + 1; + + for (int i = 1; i <= n1 ; i++) { + for (int j = 1; j <= n2 ; j++) { + if (word1.charAt(i - 1) == word2.charAt(j - 1)) dp[i][j] = dp[i - 1][j - 1]; + else dp[i][j] = Math.min(Math.min(dp[i - 1][j - 1], dp[i - 1][j]), dp[i][j - 1]) + 1; + } + } + return dp[n1][n2]; + } +}