diff --git a/Week_01/.idea/Week_01.iml b/Week_01/.idea/Week_01.iml new file mode 100644 index 00000000..d6ebd480 --- /dev/null +++ b/Week_01/.idea/Week_01.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Week_01/.idea/encodings.xml b/Week_01/.idea/encodings.xml new file mode 100644 index 00000000..15a15b21 --- /dev/null +++ b/Week_01/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Week_01/.idea/misc.xml b/Week_01/.idea/misc.xml new file mode 100644 index 00000000..28a804d8 --- /dev/null +++ b/Week_01/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/Week_01/.idea/modules.xml b/Week_01/.idea/modules.xml new file mode 100644 index 00000000..c779e0d2 --- /dev/null +++ b/Week_01/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Week_01/.idea/vcs.xml b/Week_01/.idea/vcs.xml new file mode 100644 index 00000000..6c0b8635 --- /dev/null +++ b/Week_01/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Week_01/.idea/workspace.xml b/Week_01/.idea/workspace.xml new file mode 100644 index 00000000..ea700bc2 --- /dev/null +++ b/Week_01/.idea/workspace.xml @@ -0,0 +1,186 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1560681524748 + + + 1560682106400 + + + 1560682222777 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 12 + + + + + + + + \ No newline at end of file diff --git a/Week_02/id_1/LeetCode_101_1.java b/Week_02/id_1/LeetCode_101_1.java new file mode 100644 index 00000000..1981a324 --- /dev/null +++ b/Week_02/id_1/LeetCode_101_1.java @@ -0,0 +1,84 @@ +package week02; + +import java.util.LinkedList; +import java.util.Queue; + +/** + * @创建人 luoxiang + * @创建时间 2019/6/14 15:06 + * @描述 LeetCode : 101. 对称二叉树 https://leetcode-cn.com/problems/symmetric-tree/ + */ +public class SymmetricTree101 { + public static void main(String[] args) { + TreeNode node = new TreeNode(3); + node.left = new TreeNode(2); + node.right = new TreeNode(2); + node.left.left = new TreeNode(3); + node.left.right = new TreeNode(4); + node.right.left = new TreeNode(4); + node.right.right = new TreeNode(3); + System.out.println(new SymmetricTree101().isSymmetric(node)); + } + + /** + * Method 1 : BFS ,使用队列 + * 添加顺序: + * 1、左子树的左 + * 2、右子树的右 + * 3、左子树的右 + * 4、右子树的左 + * 时间复杂度 : O(N) ; + * 空间复杂度 : O(N) ; + */ + public boolean isSymmetric(TreeNode root) { + if (root == null || (root.left==null && root.right==null)) return true; + Queue queue = new LinkedList<>(); + queue.offer(root.left); + queue.offer(root.right); + while (!queue.isEmpty()) { + TreeNode node = queue.poll(); + TreeNode node2 = queue.poll(); + if (node == null && node2 == null) continue; + if (node == null || node2 == null) return false; + if (node.val != node2.val) return false; + queue.offer(node.left); + queue.offer(node2.right); + queue.offer(node.right); + queue.offer(node2.left); + } + return true; + } + + /** + * Method 2 : DFS + * 时间复杂度 : O(N) + * 空间复杂度 : O(N) + */ + public boolean isSymmetric2(TreeNode root) { + return isMirrer(root, root); + } + + private boolean isMirrer(TreeNode root, TreeNode root1) { + if (root == null && root1 == null) return true; + if (root == null || root1 == null) return false; + if (root.val != root1.val) return false; + return isMirrer(root.left, root1.right) && isMirrer(root.right, root1.left); + } + + /** + * Method 2 : DFS 优化版 + * 时间复杂度 : O(N) + * 空间复杂度 : O(N) + */ + public boolean isSymmetric3(TreeNode root) { + if (root == null) return true; + return isMirrer3(root.left, root.right); + } + + private boolean isMirrer3(TreeNode left, TreeNode right) { + if (left == null && right == null) return true; + if (left == null || right == null) return false; + return (left.val == right.val) && isMirrer3(left.left, right.right) && isMirrer3(left.right, right.left); + } + +} diff --git a/Week_02/id_1/LeetCode_102_1.java b/Week_02/id_1/LeetCode_102_1.java new file mode 100644 index 00000000..5a4d4da1 --- /dev/null +++ b/Week_02/id_1/LeetCode_102_1.java @@ -0,0 +1,57 @@ +package week02; + +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +/** + * @创建人 luoxiang + * @创建时间 2019/6/14 16:24 + * @描述 LeetCode : 102. 二叉树的层次遍历 https://leetcode-cn.com/problems/binary-tree-level-order-traversal/ + */ +public class BinaryTreeLevelorderTraversal102 { + public static void main(String[] args) { + TreeNode node = new TreeNode(3); + node.left = new TreeNode(5); + node.right = new TreeNode(1); + node.left.left = new TreeNode(6); + node.left.right = new TreeNode(2); + node.left.right.left = new TreeNode(7); + node.left.right.right = new TreeNode(4); + + node.right.left = new TreeNode(0); + node.right.right = new TreeNode(8); + final List> list = new BinaryTreeLevelorderTraversal102().levelOrder(node); + for (List integers : list) { + for (Integer integer : integers) { + System.out.print(integer + ","); + } + System.out.println(); + } + } + + /** + * Method 1 : BFS ,队列存储每一层的值, 用 currentSize 记录当前层的数量,currentSize 为0时,当前层遍历完毕 + * 时间复杂度 : O(N) 树的遍历 ; 空间复杂度 : O(N) ; 额外的空间 队列 + */ + public List> levelOrder(TreeNode root) { + List> list = new LinkedList<>(); + if (root == null) return list; + Queue queue = new LinkedList<>(); + queue.offer(root); + int currentSize = 1; + List currentList = new LinkedList<>(); + while (!queue.isEmpty()) { + TreeNode node = queue.poll(); + currentList.add(node.val); + if (node.left != null) queue.offer(node.left); + if (node.right != null) queue.offer(node.right); + if (--currentSize == 0) { + currentSize = queue.size(); + list.add(currentList); + currentList = new LinkedList<>(); + } + } + return list; + } +} diff --git a/Week_02/id_1/LeetCode_103_1.java b/Week_02/id_1/LeetCode_103_1.java new file mode 100644 index 00000000..caa8a0e8 --- /dev/null +++ b/Week_02/id_1/LeetCode_103_1.java @@ -0,0 +1,87 @@ +package week02; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +/** + * @创建人 luoxiang + * @创建时间 2019/6/14 16:41 + * @描述 LeetCode : 103. 二叉树的锯齿形层次遍历 https://leetcode-cn.com/problems/binary-tree-zigzag-level-order-traversal/ + */ +public class BinaryTreeZigzagLevelOrderTraversal103 { + public static void main(String[] args) { + TreeNode node = new TreeNode(3); + node.left = new TreeNode(5); + node.right = new TreeNode(1); + node.left.left = new TreeNode(6); + node.left.right = new TreeNode(2); + node.left.right.left = new TreeNode(7); + node.left.right.right = new TreeNode(4); + + node.right.left = new TreeNode(0); + node.right.right = new TreeNode(8); + final List> list = new BinaryTreeZigzagLevelOrderTraversal103().zigzagLevelOrder(node); + for (List integers : list) { + for (Integer integer : integers) { + System.out.print(integer + ","); + } + System.out.println(); + } + } + + /** + * Method 1 : 对 准备新插入 List 进行处理,用一个奇偶数 或 布尔值 来记录是否需要反转 + * 时间复杂度 : O(N) 树的遍历 + * 空间复杂度 : O(N) 额外空间 队列 + * + */ + public List> zigzagLevelOrder(TreeNode root) { + List> list = new LinkedList<>(); + if (root == null) return list; + Queue queue = new LinkedList<>(); + queue.offer(root); + int currentSize = 1; + int depth =0; + List currentList = new LinkedList<>(); + while (!queue.isEmpty()) { + TreeNode node = queue.poll(); + currentList.add(node.val); + if (node.left != null) queue.offer(node.left); + if (node.right != null) queue.offer(node.right); + if (--currentSize == 0) { + currentSize = queue.size(); + if(depth%2!=0) Collections.reverse(currentList); + list.add(currentList); + currentList = new LinkedList<>(); + depth++; + } + } + return list; + } + + public List> zigzagLevelOrder2(TreeNode root) { + List> list = new LinkedList<>(); + if (root == null) return list; + Queue queue = new LinkedList<>(); + queue.offer(root); + int currentSize = 1; + boolean depth =false; + List currentList = new LinkedList<>(); + while (!queue.isEmpty()) { + TreeNode node = queue.poll(); + currentList.add(node.val); + if (node.left != null) queue.offer(node.left); + if (node.right != null) queue.offer(node.right); + if (--currentSize == 0) { + currentSize = queue.size(); + if(depth) Collections.reverse(currentList); + list.add(currentList); + currentList = new LinkedList<>(); + depth=!depth; + } + } + return list; + } +} diff --git a/Week_02/id_1/LeetCode_111_1.java b/Week_02/id_1/LeetCode_111_1.java new file mode 100644 index 00000000..9d1100ae --- /dev/null +++ b/Week_02/id_1/LeetCode_111_1.java @@ -0,0 +1,67 @@ +package week02; + +import java.util.LinkedList; +import java.util.Queue; + +/** + * @创建人 luoxiang + * @创建时间 2019/6/13 12:27 + * @描述 LeetCode : 111. 二叉树的最小深度 https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/ + * 五毒神掌 : 隔一周练习一次 + */ +public class MinimunDepthBinaryTree111 { + public static void main(String[] args) { + TreeNode node = new TreeNode(5); + node.left = new TreeNode(1); + node.right = new TreeNode(4); + node.left.left = new TreeNode(3); + node.left.right = new TreeNode(6); + System.out.println(new MinimunDepthBinaryTree111().minDepth3(node)); + } + + /** + * Method 1 : DFS 递归解决 + * 时间复杂度 : O(N) ; + * 空间复杂度 : O(N) ; + */ + public int minDepth(TreeNode root) { + if (root == null) return 0; + int left = minDepth(root.left); + int right = minDepth(root.right); + return (left == 0 || right == 0) ? right + left + 1 : Math.min(left, right) + 1; + } + + /** + * Method 2 : 方法一 DFS 精简版 + * 时间复杂度 : O(N) ; + * 空间复杂度 : O(1); 没有额外的空间开销 + */ + public int minDepth2(TreeNode root) { + if (root == null) return 0; + return (root.left == null || root.right == null) ? minDepth(root.right) + minDepth(root.left) + 1 : Math.min(minDepth(root.left), minDepth(root.right)) + 1; + } + + /** + * Method 3 : BFS 迭代 ; 使用队列 ; depth 记录深度;currentSize 记录当前层的数量; 只有数量为0时,当前层才算是深度加1; + * 时间复杂度 : O(N) ; + * * 空间复杂度 : O(N) ; + */ + public int minDepth3(TreeNode root) { + if (root == null) return 0; + Queue queue = new LinkedList<>(); + queue.offer(root); + int depth = 1,currentSize = 1; + while (!queue.isEmpty()) { + TreeNode node = queue.poll(); + if (node.left != null) queue.offer(node.left); + if (node.right != null) queue.offer(node.right); + if (node.left == null && node.right == null) return depth; + if (--currentSize == 0) { + depth++; + currentSize = queue.size(); + } + } + return depth; + } + +} diff --git a/Week_02/id_1/LeetCode_1_1.java b/Week_02/id_1/LeetCode_1_1.java new file mode 100644 index 00000000..1ef2fb2b --- /dev/null +++ b/Week_02/id_1/LeetCode_1_1.java @@ -0,0 +1,51 @@ +package week02; + +import java.util.HashMap; +import java.util.Map; + +/** + * @创建人 luoxiang + * @创建时间 2019/6/11 11:50 + * @描述 LeetCode : 1. 两数之和 https://leetcode-cn.com/problems/two-sum/ + */ +public class TwoSum1 { + + public static void main(String[] args) { + final TwoSum1 twoSum1 = new TwoSum1(); + int[] i = twoSum1.twoSum(new int[]{2, 7, 11, 15}, 9); + for (int i1 : i) { + System.out.println(i1); + } + } + + /** + * Method 1 : 暴力法 ,两层循环 + * 时间复杂度 : O(N*N) ; 空间复杂度 : O(1) ; + */ + public int[] twoSum(int[] nums, int target) { + for (int i = 0; i < nums.length - 1; i++) { + for (int j = i + 1; j < nums.length; j++) { + if (target - nums[i] == nums[j]) { + return new int[]{i, j}; + } + } + } + throw new IllegalArgumentException("No result"); + } + + /** + * Method 2 : 利用 Map 记忆储存法 ,把循环中没有匹配的值存储进 map当中,后面循环时进行判断,map 匹配成功 即返回 + * 时间复杂度 : O(N) + * 空间复杂度 : O(N) + */ + public int[] twoSum2(int[] nums, int target) { + final Map map = new HashMap<>(); + for (int i = 0; i < nums.length; i++) { + final int temp = target - nums[i]; + if (map.containsKey(temp)) return new int[]{map.get(temp), i}; + map.put(nums[i], i); + } + throw new IllegalArgumentException("No result"); + } + +} diff --git a/Week_02/id_1/LeetCode_235_1.java b/Week_02/id_1/LeetCode_235_1.java new file mode 100644 index 00000000..deeb7b8a --- /dev/null +++ b/Week_02/id_1/LeetCode_235_1.java @@ -0,0 +1,70 @@ +package week02; + +/** + * @创建人 luoxiang + * @创建时间 2019/6/11 12:56 + * @描述 LeetCode : 235. 二叉搜索树的最近公共祖先 https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree/ + */ +public class LowestCommonAncestorBinarySearchTree235 { + public static void main(String[] args) { + TreeNode node = new TreeNode(6); + node.left = new TreeNode(2); + node.right = new TreeNode(8); + node.left.left = new TreeNode(0); + node.left.right = new TreeNode(4); + node.left.right.left = new TreeNode(3); + node.left.right.right = new TreeNode(5); + + node.right.left = new TreeNode(7); + node.right.right = new TreeNode(9); + System.out.println(new LowestCommonAncestorBinarySearchTree235().lowestCommonAncestor3(node, node.left, node.right).toString()); + } + + /** + * Method 1 : 利用二叉搜索树 的特性;父节点的右节点 大于 父节点。左节点 小于 父节点 ,以此类推。 + * 当两个传入的两个节点的 最小值 都要比父节点 大 的话,只需要从 右节点 中查找即可 + * 当两个传入的两个节点的 最大值 都要比父节点 小 的话,只需要从 左节点 中查找即可 + * 时间复杂度 : O(logN) ; + * 空间复杂度 : O(1) 没有额外的空间开销; + */ + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + if (root == null || root == p || root == q) return root; + if (Math.min(p.val, q.val) > root.val) return lowestCommonAncestor(root.right, p, q); + if (Math.max(p.val, q.val) < root.val) return lowestCommonAncestor(root.left, p, q); + return root; + } + + /** + * Method 2: 也可以不利用二叉搜索树的特性, 从左、右子树中都找一遍,比较费时 + * 也就是二叉树 的 最近公共祖先 + * 时间复杂度 : O(N) ; + * 空间复杂度 : O(2N) ; + */ + public TreeNode lowestCommonAncestor2(TreeNode root, TreeNode p, TreeNode q) { + if (root == null || root == p || root == q) return root; + final TreeNode left = lowestCommonAncestor2(root.left, p, q); + final TreeNode right = lowestCommonAncestor2(root.right, p, q); + if (left != null && right != null) return root; + return left != null ? left : right; + } + + /** + * Method 3 : 利用二叉树的特性 ; 不使用 递归 实现 ; + * 还是分两边的情况处理 : 同时在 左边 或者 同时在右边 , + * 同时在左边 : root.val - p.val > 0 ; root.val - q.val > 0 ; root=root.left + * 同时在右边 : root.val - p.val < 0 ; root.val - q.val < 0 ; root=root.right + * 它们 结果的乘积 一定是 大于 0 + * 不然的话直接返回当前的root了 + * 时间复杂度 : O(logN) 每次都是进行二分 ; + * 空间复杂度 : O(1) ; 没有额外的空间开销 + */ + public TreeNode lowestCommonAncestor3(TreeNode root, TreeNode p, TreeNode q) { + while((root.val-p.val) * (root.val- q.val)>0){ + root=root.val>q.val ? root.left : root.right; + } + return root; + } + + + + } diff --git a/Week_02/id_1/LeetCode_236_1.java b/Week_02/id_1/LeetCode_236_1.java new file mode 100644 index 00000000..219e8b99 --- /dev/null +++ b/Week_02/id_1/LeetCode_236_1.java @@ -0,0 +1,35 @@ +package week02; + +/** + * @创建人 luoxiang + * @创建时间 2019/6/14 14:49 + * @描述 LeetCode : 236. 二叉树的最近公共祖先 https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/ + */ +public class LowestCommonAncestorBinaryTree236 { + public static void main(String[] args) { + TreeNode node = new TreeNode(3); + node.left = new TreeNode(5); + node.right = new TreeNode(1); + node.left.left = new TreeNode(6); + node.left.right = new TreeNode(2); + node.left.right.left = new TreeNode(7); + node.left.right.right = new TreeNode(4); + + node.right.left = new TreeNode(0); + node.right.right = new TreeNode(8); + System.out.println(new LowestCommonAncestorBinaryTree236().lowestCommonAncestor(node, node.right, node.left).toString()); + } + + /** + * Method 1 : 递归 ,从左右子树中分别查找 + * 时间复杂度 : O(N) + * 空间复杂度 : O(N) + */ + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + if (root == null || root == p || root == q) return root; + TreeNode left = lowestCommonAncestor(root.left, p, q); + TreeNode right = lowestCommonAncestor(root.right, p, q); + if (left != null && right != null) return root; + return left != null ? left : right; + } +} diff --git a/Week_02/id_1/LeetCode_242_1.java b/Week_02/id_1/LeetCode_242_1.java new file mode 100644 index 00000000..747547eb --- /dev/null +++ b/Week_02/id_1/LeetCode_242_1.java @@ -0,0 +1,53 @@ +package week02; + +import java.util.Arrays; + +/** + * @创建人 luoxiang + * @创建时间 2019/6/11 12:37 + * @描述 LeetCode : 242. 有效的字母异位词 https://leetcode-cn.com/problems/valid-anagram/ + */ +public class ValidAnagram242 { + public static void main(String[] args) { + System.out.println(new ValidAnagram242().isAnagram("anagram", "nagaram")); + System.out.println(new ValidAnagram242().isAnagram("rat", "car")); + } + + /** + * Method 1 : 把两个字符串 转化成 char 数组,在排序比较两者是否一致 + * 字符串 转化成 数组 ,额外开销空间 两个数组 + * 数组内 排序 采用 快速排序,时间复杂度 NlogN + * 时间复杂度 : O(2NlogN) ; + * 空间复杂度 : O(N) ; N 为 字符串的长度 + */ + public boolean isAnagram(String s, String t) { + if (s.length() != t.length()) return false; + final char[] charsOne = s.toCharArray(); + final char[] charsTwo = t.toCharArray(); + Arrays.sort(charsOne); + Arrays.sort(charsTwo); + return String.valueOf(charsOne).equals(String.valueOf(charsTwo)); + } + + /** + * Method 2 : 用一个 26 位 长度的数组来保存字符串内的字符数量。 无需排序 + * 第一个字符串中的字符 数组中的数量 ++ + * 第二个字符串中的字符 数组中的数量 -- + * 时间复杂度 : O(N) ; + * 空间复杂度 : O(2N) ; N 为 字符串的长度 + */ + public boolean isAnagram2(String s, String t) { + if (s.length() != t.length()) return false; + final int[] array = new int[26]; + final char[] charsOne = s.toCharArray(); + final char[] charsTwo = t.toCharArray(); + for (int i = 0; i < s.length(); i++) { + array[charsOne[i] - 'a']++; + array[charsTwo[i] - 'a']--; + } + for (int i : array) { + if (i != 0) return false; + } + return true; + } +} diff --git a/Week_02/id_1/LeetCode_3_1.java b/Week_02/id_1/LeetCode_3_1.java new file mode 100644 index 00000000..73e107ef --- /dev/null +++ b/Week_02/id_1/LeetCode_3_1.java @@ -0,0 +1,136 @@ +package week02; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * @创建人 luoxiang + * @创建时间 2019/6/11 14:40 + * @描述 LeetCode : 3. 无重复字符的最长子串 https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/ + */ +public class LongestSubstringWithoutRepeatingCharacters3 { + public static void main(String[] args) { + System.out.println(new LongestSubstringWithoutRepeatingCharacters3().lengthOfLongestSubstring4("abcabcbb")); + System.out.println(new LongestSubstringWithoutRepeatingCharacters3().lengthOfLongestSubstring4("bbbbb")); + System.out.println(new LongestSubstringWithoutRepeatingCharacters3().lengthOfLongestSubstring4("pwwkew")); + System.out.println(new LongestSubstringWithoutRepeatingCharacters3().lengthOfLongestSubstring4(" ")); + System.out.println(new LongestSubstringWithoutRepeatingCharacters3().lengthOfLongestSubstring4("")); + System.out.println(new LongestSubstringWithoutRepeatingCharacters3().lengthOfLongestSubstring4("c")); + System.out.println(new LongestSubstringWithoutRepeatingCharacters3().lengthOfLongestSubstring4("abc")); + System.out.println(new LongestSubstringWithoutRepeatingCharacters3().lengthOfLongestSubstring4("abba")); + } + + /** + * Method 1 : 暴力法 + */ + public int lengthOfLongestSubstring1(String s) { + int max=0; + for(int i=0;i set = new HashSet<>(); + for(int i=start;i set = new HashSet<>(); + while (i map = new HashMap<>(); + int max=0; + int count=0; + for(int j=0;j list = new TopKFrequentWords692().topKFrequent(strs, 2); + final List list2 = new TopKFrequentWords692().topKFrequent(strs2, 4); + for (String s : list) { + System.out.print(s + ","); + } + System.out.println(); + for (String s : list2) { + System.out.print(s + ","); + } + + } + + /** + * Method 1 : 使用优先队列, 需要重写 优先队列的比较方式 + * 时间复杂度 : O(N) ; + */ + public List topKFrequent(String[] words, int k) { + Map map = new HashMap<>(); + for (String word : words) map.put(word, map.getOrDefault(word, 0) + 1); + PriorityQueue pq = new PriorityQueue(new Comparator() { + @Override + public int compare(String o1, String o2) { + return map.get(o1) == map.get(o2) ? o1.compareTo(o2) : map.get(o2) - map.get(o1); + } + } + ); + List list = new LinkedList<>(); + for (String entry : map.keySet()) pq.offer(entry); + for (int i = 0; i < k; i++) list.add(pq.poll()); + return list; + } + + public List topKFrequent2(String[] words, int k) { + Map map = new HashMap<>(); + for (String word : words) { + map.put(word, map.getOrDefault(word, 0) + 1); + } + PriorityQueue> pq = new PriorityQueue<>( + (a, b) -> a.getValue() == b.getValue() ? a.getKey().compareTo(b.getKey()) : b.getValue() - a.getValue() + ); + for (Map.Entry entry : map.entrySet()) { + pq.offer(entry); + } + List list = new LinkedList<>(); + for (int i = 0; i < k; i++) { + list.add(pq.poll().getKey()); + } + return list; + } + + +} diff --git a/Week_02/id_1/LeetCode_726_1.java b/Week_02/id_1/LeetCode_726_1.java new file mode 100644 index 00000000..e5416035 --- /dev/null +++ b/Week_02/id_1/LeetCode_726_1.java @@ -0,0 +1,69 @@ +package week02; + +import java.util.Map; +import java.util.Stack; +import java.util.TreeMap; + +/** + * @创建人 luoxiang + * @创建时间 2019/6/12 16:04 + * @描述 LeetCode : 726. 原子的数量 https://leetcode-cn.com/problems/number-of-atoms/ + */ +public class NumberOfAtoms726 { + public static void main(String[] args) { + String str = "Mg(OH)2"; + String str2 = "K4(ON(SO3)2)2"; + new NumberOfAtoms726().countOfAtoms(str); + new NumberOfAtoms726().countOfAtoms(str2); + } + + /** + * 思考方式简单,实现比较麻烦 + * Method 1 : 使用 堆栈 + map 解决 + * 拆解为三种情况: + * 1、 ( 左括号,压栈 + * 2、 ) 右括号,出栈 + * 3、 字符串 + * 判断是否为 小写 + * 判断是否为 数字 + * 时间复杂度 : O(N) ; + * 空间复杂度 : O(N) ; + */ + public String countOfAtoms(String formula) { + int n = formula.length(); + Stack> stack = new Stack<>(); + stack.push(new TreeMap<>()); + + for (int i = 0; i < n; ) { + if (formula.charAt(i) == '(') { + stack.push(new TreeMap<>()); + i++; + } else if (formula.charAt(i) == ')') { + Map top = stack.pop(); + int start = ++i; + while (i < n && Character.isDigit(formula.charAt(i))) i++; + int multi = (i == start ? 1 : Integer.parseInt(formula.substring(start, i))); + for (String s : top.keySet()) { + Integer sum = top.get(s); + stack.peek().put(s, stack.peek().getOrDefault(s, 0) + sum * multi); + } + } else { + int start = i++; + while (i < n && Character.isLowerCase(formula.charAt(i))) i++; + String key = formula.substring(start, i); + start = i; + while (i < n && Character.isDigit(formula.charAt(i))) i++; + int multi = (i == start ? 1 : Integer.parseInt(formula.substring(start, i))); + // 当前 括号 内可能有重复的元素 + stack.peek().put(key, stack.peek().getOrDefault(key, 0) + multi); + } + } + StringBuilder sb = new StringBuilder(); + for (String s : stack.peek().keySet()) { + Integer num = stack.peek().get(s); + sb.append(s); + if (num > 1) sb.append(num); + } + return sb.toString(); + } +} diff --git a/Week_02/id_1/LeetCode_783_1.java b/Week_02/id_1/LeetCode_783_1.java new file mode 100644 index 00000000..ad19086d --- /dev/null +++ b/Week_02/id_1/LeetCode_783_1.java @@ -0,0 +1,65 @@ +package week02; + +import java.util.LinkedList; +import java.util.List; + +/** + * @创建人 luoxiang + * @创建时间 2019/6/13 14:32 + * @描述 LeetCode : 783. 二叉搜索树结点最小距离 https://leetcode-cn.com/problems/minimum-distance-between-bst-nodes/ + * 五毒神掌 : 练习上一周的习题 + */ +public class MinimumDistanceBetweenBstNodes783 { + public static void main(String[] args) { + TreeNode node = new TreeNode(4); + node.left = new TreeNode(2); + node.right = new TreeNode(6); + node.left.left = new TreeNode(1); + node.left.right = new TreeNode(3); + System.out.println(new MinimumDistanceBetweenBstNodes783().minDiffInBST(node)); + } + + /** + * Method 1 : 中序遍历, 然后两两相减取最小值 + * 时间复杂度 : O(2*N) ; 中序遍历 + 循环 + * 空间复杂度 : O(N) ; list 集合 + */ + public int minDiffInBST(TreeNode root) { + List list = new LinkedList<>(); + inOrder(root, list); + int min = Integer.MAX_VALUE; + for (int i = 1; i < list.size(); i++) { + min = Math.min(min, list.get(i) - list.get(i - 1)); + } + return min; + } + + private void inOrder(TreeNode root, List list) { + if (root == null) return; + inOrder(root.left, list); + list.add(root.val); + inOrder(root.right, list); + } + + /** + * Method 2 : 递归的方法 , 用全局变量记忆存储上一个节点 + * 时间复杂度 : O(N) + * 空间复杂度 : O(1) + */ + int min = Integer.MAX_VALUE; + TreeNode pre = null; + + public int minDiffInBST2(TreeNode root) { + dfs(root); + return min; + } + + private void dfs(TreeNode root) { + if (root == null) return; + dfs(root.left); + if (pre != null) min = Math.min(min, root.val - pre.val); + pre = root; + dfs(root.right); + } + +} diff --git a/Week_02/id_1/LeetCode_938_1.java b/Week_02/id_1/LeetCode_938_1.java new file mode 100644 index 00000000..7559ada6 --- /dev/null +++ b/Week_02/id_1/LeetCode_938_1.java @@ -0,0 +1,61 @@ +package week02; + +import java.util.ArrayList; +import java.util.List; + +/** + * @创建人 luoxiang + * @创建时间 2019/6/14 17:54 + * @描述 LeetCode : 938. 二叉搜索树的范围和 https://leetcode-cn.com/problems/range-sum-of-bst/ + */ +public class RangeSumBst938 { + public static void main(String[] args) { + TreeNode node = new TreeNode(10); + node.left = new TreeNode(5); + node.right = new TreeNode(15); + node.left.left = new TreeNode(3); + node.left.right = new TreeNode(7); + node.right.right = new TreeNode(18); + System.out.println(new RangeSumBst938().rangeSumBST2(node, 7, 15)); + } + + /** + * Method 1 : 中序遍历 , 然后在 有序集合中 计算和 ;当前 值 大于 R ,直接break,避免无效的循环; + * 时间复杂度 : O(N) ; 中序遍历 + 循环 + * 空间复杂度 : O(N) ; list 集合 + */ + public int rangeSumBST(TreeNode root, int L, int R) { + List list = new ArrayList<>(); + inOrder(root, list); + int sum = 0; + for (int i = 0; i < list.size(); i++) { + if (L <= list.get(i) && list.get(i) <= R) + sum += list.get(i); + if (list.get(i) > R) break; + } + return sum; + } + + private void inOrder(TreeNode root, List list) { + if (root == null) return; + inOrder(root.left, list); + list.add(root.val); + inOrder(root.right, list); + } + + /** + * Method 2 : DFS 使用 二叉搜索树的特性, 在递归中操作; + * L 的值大于当前根节点的值时,从根的右子树中找 + * R 的值小于当前根节点的值时,从根的左子树中找 + * 不然都要找 + * 时间复杂度 : O(N) ; + * 空间复杂度 : O(N) ; + */ + public int rangeSumBST2(TreeNode root, int L, int R) { + if(root==null) return 0; + if(root.valR) return rangeSumBST2(root.left,L,R); + return root.val+rangeSumBST2(root.right,L,R)+rangeSumBST2(root.left,L,R); + } + +} diff --git a/Week_02/id_1/LeetCode_98_1.java b/Week_02/id_1/LeetCode_98_1.java new file mode 100644 index 00000000..86e39da9 --- /dev/null +++ b/Week_02/id_1/LeetCode_98_1.java @@ -0,0 +1,84 @@ +package week02; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Stack; + +/** + * @创建人 luoxiang + * @创建时间 2019/6/12 17:45 + * @描述 LeetCode : 98. 验证二叉搜索树 https://leetcode-cn.com/problems/validate-binary-search-tree/ + */ +public class ValidateBinarySearchTree98 { + public static void main(String[] args) { +// TreeNode node = new TreeNode(5); +// node.left = new TreeNode(1); +// node.right = new TreeNode(4); +// node.right.left = new TreeNode(3); +// node.right.right = new TreeNode(6); + + TreeNode node = new TreeNode(10); + node.left = new TreeNode(5); + node.right = new TreeNode(15); + node.left.left = new TreeNode(3); + node.left.right = new TreeNode(6); + node.right.left = new TreeNode(11); + node.right.right = new TreeNode(20); + +// TreeNode node = new TreeNode(0); +// node.left = new TreeNode(-1); + +// TreeNode node = new TreeNode(6); +// node.left = new TreeNode(2); +// node.right = new TreeNode(8); +// node.left.left = new TreeNode(0); +// node.left.right = new TreeNode(4); +// node.left.right.left = new TreeNode(3); +// node.left.right.right = new TreeNode(5); +// node.right.left = new TreeNode(7); +// node.right.right = new TreeNode(9); + System.out.println(new ValidateBinarySearchTree98().inorderTraversal(node)); + } + + + public List inorderTraversal(TreeNode root) { + List list = new ArrayList<>(); + if(root == null) return list; + Stack stack = new Stack<>(); + while(root != null || !stack.empty()){ + while(root != null){ + stack.push(root); + root = root.left; + } + root = stack.pop(); + list.add(root.val); + root = root.right; + + } + return list; + } + /** + * Method 1 : 中序遍历 为 升序 ; 不满足条件 即返回 false + * 时间复杂度 : O(N) + * 空间复杂度 : O(N) + **/ + public boolean isValidBST(TreeNode root) { + if(root==null) return true; + List list = new LinkedList(); + inOrder(root,list); + for(int i=1;i lastlen+1 { + cursublen = lastlen + 1 + } + if maxsublen < cursublen { + maxsublen = cursublen + } + lastlen = cursublen + alphaposrel[b] = i + } + return maxsublen +} \ No newline at end of file diff --git a/Week_02/id_10/Leecode-692-10.go b/Week_02/id_10/Leecode-692-10.go new file mode 100644 index 00000000..336a5ba7 --- /dev/null +++ b/Week_02/id_10/Leecode-692-10.go @@ -0,0 +1,44 @@ +import "sort" + +type WNode struct { + Val string + Frequent int +} + +type WNodes []*WNode + +func (s WNodes) Len() int { return len(s) } +func (s WNodes) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s WNodes) Less(i, j int) bool { + if s[i].Frequent > s[j].Frequent { + return true + } else if s[i].Frequent == s[j].Frequent { + return s[i].Val < s[j].Val + } + return false +} + +func topKFrequent(words []string, k int) []string { + if k <= 0 { + return []string{} + } + frequenthash := make(map[string]*WNode) + frequentarr := make([]*WNode, 0, len(words)) + for i := 0; i < len(words); i++ { + w := words[i] + if node, ok := frequenthash[w]; ok { + node.Frequent++ + } else { + node = &WNode{w, 1} + frequenthash[w] = node + frequentarr = append(frequentarr, node) + } + } + sort.Sort(WNodes(frequentarr)) + retarr := make([]string, k) + for i := 0; i < k; i++ { + retarr[i] = frequentarr[i].Val + } + return retarr + +} diff --git a/Week_02/id_10/Leecode-726-10.go b/Week_02/id_10/Leecode-726-10.go new file mode 100644 index 00000000..aeae82bc --- /dev/null +++ b/Week_02/id_10/Leecode-726-10.go @@ -0,0 +1,76 @@ +import "strconv" +import "strings" +import "sort" + +func countOfAtoms(formula string) string { + s := []byte(formula) + resultmap, _ := helper(s, 0) + resultstrs := make([]string, len(resultmap)) + for k, v := range resultmap { + vstr := strconv.Itoa(v) + if vstr == "1" { + vstr = "" + } + resultstrs = append(resultstrs, k+vstr) + } + sort.Strings(resultstrs) + return strings.Join(resultstrs, "") + +} + +func helper(s []byte, start int) (map[string]int, int) { + elmentmap := make(map[string]int) + i := start + curel := "" + for i < len(s) { + if curel != "" && (s[i] < '0' || s[i] > '9') { + elmentmap[curel] += 1 + curel = "" + } + if s[i] >= 'A' && s[i] <= 'Z' { + elbytes := make([]byte, 0) + elbytes = append(elbytes, s[i]) + for i+1 < len(s) && s[i+1] >= 'a' && s[i+1] <= 'z' { + i++ + elbytes = append(elbytes, s[i]) + } + curel = string(elbytes) + } + if s[i] >= '0' && s[i] <= '9' { + nbyte := make([]byte, 0) + nbyte = append(nbyte, s[i]) + for i+1 < len(s) && s[i+1] >= '0' && s[i+1] <= '9' { + i++ + nbyte = append(nbyte, s[i]) + } + numbyte, _ := strconv.Atoi(string(nbyte)) + elmentmap[curel] += numbyte + curel = "" + } else if s[i] == '(' { + subelmap, pos := helper(s, i+1) + for k, v := range subelmap { + elmentmap[k] += v + } + i = pos + } else if s[i] == ')' { + nbyte := make([]byte, 0) + for i+1 < len(s) && s[i+1] >= '0' && s[i+1] <= '9' { + i++ + nbyte = append(nbyte, s[i]) + } + if len(nbyte) > 0 { + numbyte, _ := strconv.Atoi(string(nbyte)) + for k, v := range elmentmap { + elmentmap[k] = v * numbyte + } + } + return elmentmap, i + } + i++ + } + if curel != "" { + elmentmap[curel] += 1 + curel = "" + } + return elmentmap, i +} \ No newline at end of file diff --git a/Week_02/id_10/Leecode-783-10.go b/Week_02/id_10/Leecode-783-10.go new file mode 100644 index 00000000..1217ee40 --- /dev/null +++ b/Week_02/id_10/Leecode-783-10.go @@ -0,0 +1,32 @@ +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +//二叉树 中序遍历 递增 +const int_min = ^int(^uint(0) >> 1) + +var pre int +var min_diff int + +func minDiffInBST(root *TreeNode) int { + pre = int_min + min_diff = int(^uint(0) >> 1) + _dfs(root) + return min_diff +} + +func _dfs(root *TreeNode) { + if root == nil { + return + } + _dfs(root.Left) + if pre != int_min && root.Val-pre < min_diff { + min_diff = root.Val - pre + } + pre = root.Val + _dfs(root.Right) +} \ No newline at end of file diff --git a/Week_02/id_10/Leecode-938-10.go b/Week_02/id_10/Leecode-938-10.go new file mode 100644 index 00000000..fd13a4a8 --- /dev/null +++ b/Week_02/id_10/Leecode-938-10.go @@ -0,0 +1,24 @@ +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func rangeSumBST(root *TreeNode, L int, R int) int { + if root == nil { + return 0 + } + result := 0 + if root.Val < L { + result += rangeSumBST(root.Right, L, R) + } else if root.Val > R { + result += rangeSumBST(root.Left, L, R) + } else { + result += root.Val + result += rangeSumBST(root.Left, L, R) + result += rangeSumBST(root.Right, L, R) + } + return result +} \ No newline at end of file diff --git a/Week_02/id_10/Leecode-98-10.go b/Week_02/id_10/Leecode-98-10.go new file mode 100644 index 00000000..8388e80b --- /dev/null +++ b/Week_02/id_10/Leecode-98-10.go @@ -0,0 +1,37 @@ +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +var pre int + +func isValidBST(root *TreeNode) bool { + if root == nil { + return true + } + // int类型的最小值 + pre = ^int(^uint(0) >> 1) + return _dfs(root) +} + +//二叉搜索树 中序遍历 递增序列 +func _dfs(root *TreeNode) bool { + if root == nil { + return true + } + if !_dfs(root.Left) { + return false + } + curVal := root.Val + if curVal <= pre { + return false + } + pre = curVal + if !_dfs(root.Right) { + return false + } + return true +} \ No newline at end of file diff --git a/Week_02/id_11/LeetCode_111_11.js b/Week_02/id_11/LeetCode_111_11.js new file mode 100644 index 00000000..6f858300 --- /dev/null +++ b/Week_02/id_11/LeetCode_111_11.js @@ -0,0 +1,23 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ +var minDepth = function(root) { + if(root == null) return 0 + + let left = minDepth(root.left) + let right = minDepth(root.right) + if(left == 0 || right == 0){ + return Math.max(left, right) + 1 + } + else{ + return Math.min(left, right) + 1 + } +}; \ No newline at end of file diff --git a/Week_02/id_11/LeetCode_1_11.js b/Week_02/id_11/LeetCode_1_11.js new file mode 100644 index 00000000..eb06a231 --- /dev/null +++ b/Week_02/id_11/LeetCode_1_11.js @@ -0,0 +1,19 @@ +/** + * @param {number[]} nums + * @param {number} target + * @return {number[]} + */ +var twoSum = function(nums, target) { + + let map = {} + for(let i = nums.length - 1; i>=0; i--){ + let value = target - nums[i] + if(map[value] != null){ + return [i, map[value]] + } + map[nums[i]] = i + } + + return [] +}; + diff --git a/Week_02/id_11/LeetCode_783_11.js b/Week_02/id_11/LeetCode_783_11.js new file mode 100644 index 00000000..917d64f3 --- /dev/null +++ b/Week_02/id_11/LeetCode_783_11.js @@ -0,0 +1,27 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ + +var minDiffInBST = function(root) { + let pre + let min = 100 + + var inOrder = root => { + if (root.left != null) inOrder(root.left); + if (pre != null) min = Math.min(min, root.val - pre); + pre = root.val; + if (root.right != null) inOrder(root.right); + return min; + } + + return inOrder(root) +}; + diff --git a/Week_02/id_12/LeetCode_1_012.java b/Week_02/id_12/LeetCode_1_012.java new file mode 100644 index 00000000..feda1977 --- /dev/null +++ b/Week_02/id_12/LeetCode_1_012.java @@ -0,0 +1,19 @@ +class Solution { + public int[] twoSum(int[] nums, int target) { + Map map = new HashMap<>(); + int[] result = new int[2]; + int temp; + for (int i = 0; i < nums.length; i++) { + temp = nums[i]; + if (map.containsKey(temp)) { + if (map.get(temp) != i) { + result[0] = i; + result[1] = map.get(temp); + } + } else { + map.put(target - temp, i); + } + } + return result; + } +} diff --git a/Week_02/id_12/LeetCode_242_012.java b/Week_02/id_12/LeetCode_242_012.java new file mode 100644 index 00000000..69be2e9c --- /dev/null +++ b/Week_02/id_12/LeetCode_242_012.java @@ -0,0 +1,9 @@ +class Solution { + public boolean isAnagram(String s, String t) { + int[] alphabet = new int[26]; + for(char c : s.toCharArray()) alphabet[c - 'a']++; + for(char c : t.toCharArray()) alphabet[c - 'a']--; + for (int a : alphabet) if(a != 0) return false; + return true; + } +} \ No newline at end of file diff --git a/Week_02/id_12/LeetCode_3_012.java b/Week_02/id_12/LeetCode_3_012.java new file mode 100644 index 00000000..c973cdb3 --- /dev/null +++ b/Week_02/id_12/LeetCode_3_012.java @@ -0,0 +1,22 @@ +class Solution { + public int lengthOfLongestSubstring(String s) { + Deque characterDeque = new LinkedList<>(); + int result = 0; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (characterDeque.contains(c)) { + int len = characterDeque.size(); + if (len > result) { + result = len; + } + while (c != characterDeque.peek()) { + characterDeque.poll(); + } + characterDeque.poll(); + } + characterDeque.add(c); + } + int size = characterDeque.size(); + return size > result ? size : result; + } +} \ No newline at end of file diff --git a/Week_02/id_12/NOTE.md b/Week_02/id_12/NOTE.md deleted file mode 100644 index 107ea7d6..00000000 --- a/Week_02/id_12/NOTE.md +++ /dev/null @@ -1 +0,0 @@ -# 学习笔记 diff --git "a/Week_02/id_12/\345\255\246\344\271\240\346\200\273\347\273\223.md" "b/Week_02/id_12/\345\255\246\344\271\240\346\200\273\347\273\223.md" new file mode 100644 index 00000000..0e7305b9 --- /dev/null +++ "b/Week_02/id_12/\345\255\246\344\271\240\346\200\273\347\273\223.md" @@ -0,0 +1,6 @@ +# 学习笔记 +这周由于比较忙我只做了3题,但是3题我都认真做了,总结了一下经验: +1.第1题,刚开始确实想不出来这里面存在一个映射关系,可以利用到hashmap,学到了,以后碰到类似的题目,一定到先考虑有没有一对一映射的可能性。 +2.第3题,刚开始我就想到了这里可以利用一个双端队列来实现,因为从头到尾遍历的过程中,头和尾都会出队列,之后我又对我的代码优化了几次,感觉受益匪浅,起码在双端队列这一块学到了很多。 +3.第242题,这一题我刚开始的想法是可以排序后比较,直到我看到了leetcode英文版上面的讨论区学到了这个方法,利用26个长度的数组来判断,真的比较巧妙,从这里我学到了,以后一定要注意题目当中的关键字,比如只包含小写字母,这就是一个很明显的暗示,可以立马联想到这个题目。 +算法训练是一个长期的过程,这周我只完成了3道题目,感觉很惭愧,下周我会挤出更多的时间来完成算法训练。 \ No newline at end of file diff --git a/Week_02/id_13/LeetCode_101_013.js b/Week_02/id_13/LeetCode_101_013.js new file mode 100644 index 00000000..4d10d13c --- /dev/null +++ b/Week_02/id_13/LeetCode_101_013.js @@ -0,0 +1,28 @@ +//https://leetcode.com/problems/symmetric-tree/ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {boolean} + */ +var isSymmetric = function(root) { + if(root==undefined) return root; + let isMorror =(left,right)=>{ + if(left==undefined && right==undefined) return true; + if(left==undefined || right == undefined) return false; + return((left.val==right.val) + && isMorror(left.left,right.right) + && isMorror(left.right,right.left) + ) + + } + return isMorror(root.left,root.right); + +}; + + \ No newline at end of file diff --git a/Week_02/id_13/LeetCode_102_013.js b/Week_02/id_13/LeetCode_102_013.js new file mode 100644 index 00000000..2b3fb8d1 --- /dev/null +++ b/Week_02/id_13/LeetCode_102_013.js @@ -0,0 +1,35 @@ +//https://leetcode.com/problems/binary-tree-level-order-traversal/ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number[][]} + */ +var levelOrder = function(root) { + if(!root || root.length==0) return []; + let result = new Array(); + let queue = new Array(); + queue.push(root); + while (queue.length>0) { + let row = new Array(); + let len = queue.length; + for (let i = 0; i < len; i++) { + /* let node = queue.shift(); + row.push(node.val); + if(node.left){queue.push(node.left);} + if(node.right){queue.push(node.right);} + */ + row.push(queue[i].val); + if(queue[i].left){queue.push(queue[i].left);} + if(queue[i].right){queue.push(queue[i].right);} + } + queue= queue.slice(len); + result.push(row); + } + return result; +}; \ No newline at end of file diff --git a/Week_02/id_13/LeetCode_103_013.js b/Week_02/id_13/LeetCode_103_013.js new file mode 100644 index 00000000..35840887 --- /dev/null +++ b/Week_02/id_13/LeetCode_103_013.js @@ -0,0 +1,44 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number[][]} + */ +var zigzagLevelOrder = function(root) { + if(!root || root.length==0) return [] ; + let queue= new Array(); + let result =new Array(); + queue.push(root); + let zigzag=true; + while(queue.length) + { + let row= new Array(); + let len=queue.length; + for (let i = 0; i < len; i++) + { + let node=null; + if(zigzag) + { + node = queue.shift(); + if(node.left) queue.push(node.left); + if(node.right) queue.push(node.right); + } + else + { + node = queue.pop(); + if(node.right) queue.unshift(node.right); + if(node.left) queue.unshift(node.left); + } + row.push(node.val); + } + result.push(row); + zigzag=!zigzag; + } + return result; + +}; \ No newline at end of file diff --git a/Week_02/id_13/LeetCode_111_013.js b/Week_02/id_13/LeetCode_111_013.js new file mode 100644 index 00000000..41c64c1d --- /dev/null +++ b/Week_02/id_13/LeetCode_111_013.js @@ -0,0 +1,42 @@ +//https://leetcode.com/problems/minimum-depth-of-binary-tree/ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ +var minDepth = function(root) { + + let depth= 0; + let mindepth= Infinity; + if(!root) return 0; + function _postorder(root) + { + if(!root) return; + if(root.left ==undefined && root.right== undefined ) + { + mindepth= Math.min(depth,mindepth); + } + if( root.left != undefined ) + { + depth++; + _postorder(root.left); + depth --; + } + if( root.right != undefined ) + { + depth++; + _postorder(root.right); + depth --; + } + + + } + _postorder(root); + return mindepth+1; +}; \ No newline at end of file diff --git a/Week_02/id_13/LeetCode_236_013.js b/Week_02/id_13/LeetCode_236_013.js new file mode 100644 index 00000000..0d045c00 --- /dev/null +++ b/Week_02/id_13/LeetCode_236_013.js @@ -0,0 +1,24 @@ +//https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @param {TreeNode} p + * @param {TreeNode} q + * @return {TreeNode} + */ +var lowestCommonAncestor= l= function(root, p, q) { + if(!root || root ==p || root == q) return root; + let left = l(root.left,p,q); + let right= l(root.right,p,q); + if(!left) return right; + if(!right) return left; + return root; +}; + + \ No newline at end of file diff --git a/Week_02/id_13/LeetCode_297_013.js b/Week_02/id_13/LeetCode_297_013.js new file mode 100644 index 00000000..19da93fe --- /dev/null +++ b/Week_02/id_13/LeetCode_297_013.js @@ -0,0 +1,92 @@ +//https://leetcode.com/problems/serialize-and-deserialize-binary-tree/ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ + +/** + * Encodes a tree to a single string. + * + * @param {TreeNode} root + * @return {string} + */ +var serialize = function(root) { + let result = new Array(); + if(!root) return result; + let queue = new Array(); + queue.push(root); + let node = null; + while(queue.length>0) + { + node = queue.shift(); + if(node) + { + result.push(node.val); + queue.push(node.left||null); + queue.push(node.right||null); + } + else + { + result.push(null); + } + + } + while(result[result.length-1]==null){result.pop()} + return JSON.stringify(result); +}; + +/** + * Decodes your encoded data to tree. + * + * @param {string} data + * @return {TreeNode} + */ +var deserialize = function(data) { + if(data.length==0) return null; + let input =JSON.parse(data); + let root = new TreeNode(input.shift()); + let currentNode =null; + let levelNodes = new Array(); + levelNodes.push(root); + while(input.length) + { + let nextLevelNodes= new Array(); + while(levelNodes.length>0) + { + currentNode = levelNodes.shift(); + let leftNode = new TreeNode(input.shift()); + let rightNode = new TreeNode(input.shift()); + if(leftNode && leftNode.val != null) + { + currentNode.left=leftNode; + nextLevelNodes.push(leftNode); + } + if(rightNode && rightNode.val != null) + { + currentNode.right=rightNode; + nextLevelNodes.push(rightNode); + } + } + levelNodes = nextLevelNodes; + } + return root; + +}; +function TreeNode(val) { + this.val = val; + this.left = this.right = null; + } +/** + * Your functions will be called as such: + * deserialize(serialize(root)); + */ + + let input= "[1,0,1]"; + let root = deserialize(input); + let output = serialize(root); + console.log(output); + + \ No newline at end of file diff --git a/Week_02/id_13/LeetCode_3_013.js b/Week_02/id_13/LeetCode_3_013.js new file mode 100644 index 00000000..0236478c --- /dev/null +++ b/Week_02/id_13/LeetCode_3_013.js @@ -0,0 +1,40 @@ +//https://leetcode.com/problems/longest-substring-without-repeating-characters/ + +/** + * @param {string} s + * @return {number} + */ +var lengthOfLongestSubstring = function(s) { + if(!s) return 0; + if(s.length==1 || s.length==0) return s.length; + let hash = new Map(); + let max= 0; + for (let index = 0; index < s.length; index++) { + let start = index; + let length = 0; + while(start < s.length) + { + if(!hash.get(s.charAt(start))) + { + hash.set(s.charAt(start),1); + length ++; + max = Math.max(max,length); + start++; + } + else + { + max = Math.max(max,length); + hash.clear(); + break; + } + + } + + } + + return max; + +}; + +let input = "au"; +console.log(lengthOfLongestSubstring(input)); diff --git a/Week_02/id_13/LeetCode_692_013.js b/Week_02/id_13/LeetCode_692_013.js new file mode 100644 index 00000000..425fcaae --- /dev/null +++ b/Week_02/id_13/LeetCode_692_013.js @@ -0,0 +1,60 @@ +//https://leetcode.com/problems/top-k-frequent-words/ +/** + * @param {string[]} words + * @param {number} k + * @return {string[]} + */ +var topKFrequent = function(words, k) { + let hash = new Map(); + words.forEach(word => { + if(hash.get(word)) + { + hash.set(word,hash.get(word)+1); + } + else + { + hash.set(word,1); + } + }); + let array= new Array(); + hash.forEach( + function(value, key, map) + { + let node= new CustomerNode(key,value); + array.push(node); + } + ) + array.sort(function(a,b){ + if(a.count==b.count) + { + if(a.val < b.val) + { + return -1; + } + else + return 1; + } + return b.count- a.count ; + } + ) + + let result = new Array(); + let index=0; + while(k>0) + { + result.push(array[index].val); + index++; + k--; + } + return result; +}; + +function CustomerNode(val,count) { + this.val = val; + this.count = count +} +let words = ["glarko","zlfiwwb","nsfspyox","pwqvwmlgri","qggx","qrkgmliewc","zskaqzwo","zskaqzwo","ijy","htpvnmozay","jqrlad","ccjel","qrkgmliewc","qkjzgws","fqizrrnmif","jqrlad","nbuorw","qrkgmliewc","htpvnmozay","nftk","glarko","hdemkfr","axyak","hdemkfr","nsfspyox","nsfspyox","qrkgmliewc","nftk","nftk","ccjel","qrkgmliewc","ocgjsu","ijy","glarko","nbuorw","nsfspyox","qkjzgws","qkjzgws","fqizrrnmif","pwqvwmlgri","nftk","qrkgmliewc","jqrlad","nftk","zskaqzwo","glarko","nsfspyox","zlfiwwb","hwlvqgkdbo","htpvnmozay","nsfspyox","zskaqzwo","htpvnmozay","zskaqzwo","nbuorw","qkjzgws","zlfiwwb","pwqvwmlgri","zskaqzwo","qengse","glarko","qkjzgws","pwqvwmlgri","fqizrrnmif","nbuorw","nftk","ijy","hdemkfr","nftk","qkjzgws","jqrlad","nftk","ccjel","qggx","ijy","qengse","nftk","htpvnmozay","qengse","eonrg","qengse","fqizrrnmif","hwlvqgkdbo","qengse","qengse","qggx","qkjzgws","qggx","pwqvwmlgri","htpvnmozay","qrkgmliewc","qengse","fqizrrnmif","qkjzgws","qengse","nftk","htpvnmozay","qggx","zlfiwwb","bwp","ocgjsu","qrkgmliewc","ccjel","hdemkfr","nsfspyox","hdemkfr","qggx","zlfiwwb","nsfspyox","ijy","qkjzgws","fqizrrnmif","qkjzgws","qrkgmliewc","glarko","hdemkfr","pwqvwmlgri"]; + +let k = 14 + +console.log(topKFrequent(words,k)); diff --git a/Week_02/id_13/LeetCode_726_013.js b/Week_02/id_13/LeetCode_726_013.js new file mode 100644 index 00000000..f9ad5385 --- /dev/null +++ b/Week_02/id_13/LeetCode_726_013.js @@ -0,0 +1,13 @@ +//https://leetcode.com/problems/number-of-atoms/ +/** + * @param {string} formula + * @return {string} + */ +var countOfAtoms = function(formula) { + + + +}; + +let formula="K4(ON(SO3)2)2"; +console.log(countOfAtoms(formula)); diff --git a/Week_02/id_13/LeetCode_938_013.js b/Week_02/id_13/LeetCode_938_013.js new file mode 100644 index 00000000..40d39fe0 --- /dev/null +++ b/Week_02/id_13/LeetCode_938_013.js @@ -0,0 +1,30 @@ +//https://leetcode.com/problems/range-sum-of-bst/ + +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @param {number} L + * @param {number} R + * @return {number} + */ +var rangeSumBST = function(root, L, R) { + if(!root) return 0; + let sum = 0; + let mid_s= function (root){ + if(!root) return; + mid_s(root.left); + if(root.val>=L && root.val <=R) + { + sum = sum+root.val; + } + mid_s(root.right); + } + mid_s(root); + return sum ; +}; \ No newline at end of file diff --git a/Week_02/id_13/LeetCode_98_013.js b/Week_02/id_13/LeetCode_98_013.js new file mode 100644 index 00000000..ab4842cc --- /dev/null +++ b/Week_02/id_13/LeetCode_98_013.js @@ -0,0 +1,28 @@ + +https://leetcode.com/problems/validate-binary-search-tree/ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {boolean} + */ +var isValidBST = function(root) { + const isValid = (root, low, high) => { + if (!root) {return true} + if (root.val <= low || root.val >= high) { return false } + if (root.left && root.val <= root.left.val ) { return false } + if (root.right && root.val >= root.right.val ) { return false } + + return isValid(root.left, Math.min(root.val, low), Math.min(root.val, high)) + && isValid(root.right, Math.max(root.val, low), Math.max(root.val, high)) + } + return isValid(root, -Infinity, Infinity) +}; + + + \ No newline at end of file diff --git a/Week_02/id_14/LeetCode_111_14.py.txt b/Week_02/id_14/LeetCode_111_14.py.txt new file mode 100644 index 00000000..8509d3f2 --- /dev/null +++ b/Week_02/id_14/LeetCode_111_14.py.txt @@ -0,0 +1,19 @@ +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class Solution(object): + def minDepth(self, root): + """ + :type root: TreeNode + :rtype: int + """ + if root == None: + return 0 + if root.left==None or root.right==None: + return self.minDepth(root.left)+self.minDepth(root.right)+1 + return min(self.minDepth(root.right),self.minDepth(root.left))+1 + \ No newline at end of file diff --git a/Week_02/id_14/LeetCode_1_14.py.txt b/Week_02/id_14/LeetCode_1_14.py.txt new file mode 100644 index 00000000..c460a8d6 --- /dev/null +++ b/Week_02/id_14/LeetCode_1_14.py.txt @@ -0,0 +1,14 @@ +class Solution(object): + def twoSum(self, nums, target): + """ + :type nums: List[int] + :type target: int + :rtype: List[int] + """ + obj = {} + for i in range(len(nums)): + num = nums[i] + if target - num in obj: + return obj[target-num], i + if num not in obj: + obj[num] = i \ No newline at end of file diff --git a/Week_02/id_14/LeetCode_242_14.py.txt b/Week_02/id_14/LeetCode_242_14.py.txt new file mode 100644 index 00000000..469e1cdc --- /dev/null +++ b/Week_02/id_14/LeetCode_242_14.py.txt @@ -0,0 +1,8 @@ +class Solution(object): + def isAnagram(self, s, t): + """ + :type s: str + :type t: str + :rtype: bool + """ + return sorted(s) == sorted(t) \ No newline at end of file diff --git a/Week_02/id_14/LeetCode_3_14.py.txt b/Week_02/id_14/LeetCode_3_14.py.txt new file mode 100644 index 00000000..d0e1d71d --- /dev/null +++ b/Week_02/id_14/LeetCode_3_14.py.txt @@ -0,0 +1,14 @@ +class Solution: + def lengthOfLongestSubstring(self, s): + """ + :type s: str + :rtype: int + """ + st = {} + i, ans = 0, 0 + for j in range(len(s)): + if s[j] in st: + i = max(st[s[j]], i) + ans = max(ans, j - i + 1) + st[s[j]] = j + 1 + return ans \ No newline at end of file diff --git a/Week_02/id_14/LeetCode_692_14.py.txt b/Week_02/id_14/LeetCode_692_14.py.txt new file mode 100644 index 00000000..fa7618af --- /dev/null +++ b/Week_02/id_14/LeetCode_692_14.py.txt @@ -0,0 +1,7 @@ +class Solution(object): + def topKFrequent(self, words, k): + obj = {} + for word in words: + obj[word] = obj.get(word, 0) + 1 + ret = sorted(obj, key=lambda word: (-obj[word], word)) + return ret[:k] \ No newline at end of file diff --git a/Week_02/id_15/LeetCode_1_015.py b/Week_02/id_15/LeetCode_1_015.py new file mode 100644 index 00000000..ee5d6dd2 --- /dev/null +++ b/Week_02/id_15/LeetCode_1_015.py @@ -0,0 +1,7 @@ +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + d={} + for i,num in enumerate(nums): + if target-num in d: + return d[target-num], i + d[num]=i diff --git a/Week_02/id_15/LeetCode_242_015.py b/Week_02/id_15/LeetCode_242_015.py new file mode 100644 index 00000000..b89088ca --- /dev/null +++ b/Week_02/id_15/LeetCode_242_015.py @@ -0,0 +1,14 @@ +class Solution: + def isAnagram(self, s: str, t: str) -> bool: + if s =="" and t == "": + return True + + if len(s) != len(t) or len(set(s)) != len(set(t)): + return False + + for char in set(s): + s_count = s.count(char) + t_count = t.count(char) + if s_count != t_count: + return False + return True diff --git a/Week_02/id_15/LeetCode_3_015.py b/Week_02/id_15/LeetCode_3_015.py new file mode 100644 index 00000000..84c04c27 --- /dev/null +++ b/Week_02/id_15/LeetCode_3_015.py @@ -0,0 +1,12 @@ +class Solution: + def lengthOfLongestSubstring(self, s: str) -> int: + substring, length, max_len = "", 0, 0 + for c in s: + if c in substring: + index = substring.find(c) + substring = substring[(index + 1)::] + substring += c + length = len(substring) + if length > max_len: + max_len = length + return max_len diff --git a/Week_02/id_15/NOTE.md b/Week_02/id_15/NOTE.md index 107ea7d6..820d3a2c 100644 --- a/Week_02/id_15/NOTE.md +++ b/Week_02/id_15/NOTE.md @@ -1 +1,11 @@ # 学习笔记 +## 日常计划 + - 完成相对应的算法习题 + +## 算法相关书籍 + - 任务:完成数据结构与算法Python语言描述阅读 + - 心得:这本书完全第一遍刷下来以后发现不是非常入门的深度,比上本图解的书难很多。不少地方都需要听下来思考,收获是更加深入的了解了Python这个语言背后的一些数据结构与算法的实现原理。比如内置函数Sort()背后的算法是依据Tim算法来实现的,再比如如果要调用Python实现堆栈,可以考虑用deque这个数据结构。 + +## 下周计划 + - 复刷之前做过的算法题和尚未完成的新题 + - 完成新一周的算法作业 diff --git a/Week_02/id_16/Map b/Week_02/id_16/Map new file mode 100644 index 00000000..9be128fe --- /dev/null +++ b/Week_02/id_16/Map @@ -0,0 +1,62 @@ +//692 前K个高频词 +import java.awt.List; +import java.util.*; +import java.util.ArrayList; + +public class Main { + + public ArrayList topKFrequent(String[] words, int k) { + HashMap map = new HashMap<>(); + + for (String word : words) { + map.put(word, map.getOrDefault(word, 0) + 1); + } + + PriorityQueue queue = new PriorityQueue<>(k, new Comparator() { + @Override + public int compare(String s1, String s2) { + if (map.get(s1).equals(map.get(s2))) { + return s2.compareTo(s1); + } + return map.get(s1).compareTo(map.get(s2)); + + } + }); + + for (String key : map.keySet()) { + if (queue.size() < k) { + queue.add(key); + } else if (queue.comparator().compare(key, queue.peek()) > 0) { + queue.poll(); + queue.add(key); + } + } + + String[] res = new String[k]; + + for (int i = k - 1; i >= 0; i--) { + res[i] = queue.poll(); + } + + return (ArrayList) Arrays.asList(res); + + } + + + + + + public static void main(String[] args) + { + String s="abc"; + String c="vrd"; + Main v=new Main(); + //System.out.println(v.sea(s,c)); + String q="abc"; + String n="ccccccccc"; + System.out.println(v.lengthOfLongestSubstring(q)); + System.out.println(v.lengthOfLongestSubstring(n)); + + } + +} diff --git a/Week_02/id_16/Map1 b/Week_02/id_16/Map1 new file mode 100644 index 00000000..84e464a6 --- /dev/null +++ b/Week_02/id_16/Map1 @@ -0,0 +1,15 @@ + //242 有效的字母异位 + 字符串数组是否元素相同 + + public boolean sea(String s,String t) + { + char []schars=s.toCharArray(); + char []tchars=t.toCharArray(); + Arrays.sort(schars); + Arrays.sort(tchars); + if(schars==tchars) + return true; + else + return false; + + } \ No newline at end of file diff --git a/Week_02/id_16/Map2 b/Week_02/id_16/Map2 new file mode 100644 index 00000000..02925a13 --- /dev/null +++ b/Week_02/id_16/Map2 @@ -0,0 +1,14 @@ + //3 + public int lengthOfLongestSubstring(String s) { + int n=s.length(); + if(n<=1) return n; + int max=1; + for(int i=0;i set=new HashSet<>(); + for(int j=i;j y { + return x + } + return y +} diff --git a/Week_02/id_17/LeetCoe_236_17.go b/Week_02/id_17/LeetCoe_236_17.go new file mode 100644 index 00000000..da14379b --- /dev/null +++ b/Week_02/id_17/LeetCoe_236_17.go @@ -0,0 +1,32 @@ +/* + * @lc app=leetcode id=236 lang=golang + * + * [236] Lowest Common Ancestor of a Binary Tree + */ +/** + * Definition for TreeNode. + * type TreeNode struct { + * Val int + * Left *ListNode + * Right *ListNode + * } + */ +func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode { + if root == nil { + return nil + } + if root == p || root == q { + return root + } + left := lowestCommonAncestor(root.Left, p, q) + right := lowestCommonAncestor(root.Right, p, q) + if left != nil && right != nil { + return root + } + if left == nil { + return right + } else { + return left + } +} + diff --git a/Week_02/id_18/LeetCode_111_18.java b/Week_02/id_18/LeetCode_111_18.java new file mode 100644 index 00000000..fdb37518 --- /dev/null +++ b/Week_02/id_18/LeetCode_111_18.java @@ -0,0 +1,35 @@ +package Week_02.id_18; + +/** + * @author LiveForExperience + * @date 2019/6/12 21:50 + */ +public class LeetCode_111_18 { + public int minDepth(TreeNode root) { + if (root == null) { + return 0; + } + + if (root.left == null && root.right == null) { + return 1; + } + + int depth = Integer.MAX_VALUE; + if (root.left != null) { + depth = Math.min(minDepth(root.left), depth); + } + + if (root.right != null) { + depth = Math.min(minDepth(root.right), depth); + } + + return depth + 1; + } + + private class TreeNode { + int val; + TreeNode left; + TreeNode right; + TreeNode(int x) { val = x; } + } +} diff --git a/Week_02/id_18/LeetCode_1_18.java b/Week_02/id_18/LeetCode_1_18.java new file mode 100644 index 00000000..9ab67a4c --- /dev/null +++ b/Week_02/id_18/LeetCode_1_18.java @@ -0,0 +1,63 @@ +package Week_02.id_18; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author LiveForExperience + * @date 2019/6/11 13:33 + */ +public class LeetCode_1_18 { + public int[] twoSum(int[] nums, int target) { + if (nums == null || nums.length < 2) { + return 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) { + return new int[]{i,j}; + } + } + } + + return new int[2]; + } + + public int[] twoSum1(int[] nums, int target) { + if (nums == null || nums.length < 2) { + return new int[2]; + } + + Map map = new HashMap<>(); + for (int i = 0; i < nums.length; i++) { + map.put(nums[i], i); + } + + for (int i = 0; i < nums.length; i++) { + int j = target - nums[i]; + if (map.containsKey(j) && i != map.get(j)) { + return new int[]{i, map.get(j)}; + } + } + + return new int[2]; + } + + public int[] twoSum2(int[] nums, int target) { + if (nums == null || nums.length < 2) { + return new int[2]; + } + + Map map = new HashMap<>(); + for (int i = 0; i < nums.length; i++) { + int j = target - nums[i]; + if (map.containsKey(j)) { + return new int[]{i, map.get(j)}; + } + map.put(nums[i], i); + } + + return new int[2]; + } +} diff --git a/Week_02/id_18/LeetCode_235_18.java b/Week_02/id_18/LeetCode_235_18.java new file mode 100644 index 00000000..3384764c --- /dev/null +++ b/Week_02/id_18/LeetCode_235_18.java @@ -0,0 +1,83 @@ +package Week_02.id_18; + +import java.util.Stack; + +/** + * @author LiveForExperience + * @date 2019/6/14 18:30 + */ +public class LeetCode_235_18 { + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + if (found(root, p, q)) { + return root; + } + + Stack stack = new Stack<>(); + stack.push(root); + + while (!stack.isEmpty()) { + TreeNode node = stack.pop(); + + if (node != null) { + if (found(node, p, q)) { + return node; + } + + stack.push(node.left); + stack.push(node.right); + } + } + + return null; + } + + private boolean found(TreeNode node, TreeNode p, TreeNode q) { + return p.val <= node.val && q.val >= node.val || + p.val >= node.val && q.val <= node.val; + } + + public TreeNode lowestCommonAncestor1(TreeNode root, TreeNode p, TreeNode q) { + int parentVal = root.val; + int pVal = p.val; + int qVal = q.val; + + if (pVal < parentVal && qVal < parentVal) { + return lowestCommonAncestor1(root.left, p, q); + } else if (pVal > parentVal && qVal > parentVal) { + return lowestCommonAncestor1(root.right, p, q); + } else { + return root; + } + } + + public TreeNode lowestCommonAncestor2(TreeNode root, TreeNode p, TreeNode q) { + Stack stack = new Stack<>(); + stack.push(root); + + while (!stack.isEmpty()) { + TreeNode node = stack.pop(); + + if (node != null) { + if (p.val < node.val && q.val < node.val) { + stack.push(node.left); + } else if (p.val > node.val && q.val > node.val){ + stack.push(node.right); + } else { + return node; + } + } + } + + return null; + } + + private class TreeNode { + int val; + TreeNode left; + TreeNode right; + + TreeNode(int x) { + val = x; + } + } +} diff --git a/Week_02/id_18/LeetCode_236_18.java b/Week_02/id_18/LeetCode_236_18.java new file mode 100644 index 00000000..41dbfe8b --- /dev/null +++ b/Week_02/id_18/LeetCode_236_18.java @@ -0,0 +1,122 @@ +package Week_02.id_18; + +import java.util.*; + +/** + * @author LiveForExperience + * @date 2019/6/12 12:49 + */ +public class LeetCode_236_18 { + private TreeNode result; + + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + doRecurse(root, p, q); + return result; + } + + private boolean doRecurse(TreeNode current, TreeNode p, TreeNode q) { + if (current == null) { + return false; + } + + int left = doRecurse(current.left, p, q) ? 1 : 0; + int right = doRecurse(current.right, p, q) ? 1 : 0; + int mid = current.val == p.val || current.val == q.val ? 1 : 0; + + if (mid + left + right >= 2) { + result = current; + } + + return mid + left + right > 0; + } + + public TreeNode lowestCommonAncestor1(TreeNode root, TreeNode p, TreeNode q) { + Deque stack = new ArrayDeque<>(); + Map parents = new HashMap<>(); + + stack.push(root); + parents.put(root, null); + + while (!parents.containsKey(p) || !parents.containsKey(q)) { + TreeNode current = stack.pop(); + + if (current.left != null) { + stack.push(current.left); + parents.put(current.left, current); + } + + if (current.right != null) { + stack.push(current.right); + parents.put(current.right, current); + } + } + + Set pAncestors = new HashSet<>(); + while (p != null) { + pAncestors.add(p); + p = parents.get(p); + } + + while (!pAncestors.contains(q)) { + q = parents.get(q); + } + + return q; + } + + public TreeNode lowestCommonAncestor2(TreeNode root, TreeNode p, TreeNode q) { + TreeNode lca = null; + + boolean oneFound = false; + + Stack stack = new Stack<>(); + + stack.push(new Object[]{root, 2}); + + TreeNode childNode = null; + + while (!stack.isEmpty()) { + Object[] parentArr = stack.peek(); + if (parentArr[0] == null) {return p;} + TreeNode parentNode = (TreeNode) parentArr[0]; + int parentState = (int) parentArr[1]; + if (parentState != 0) { + if (parentState == 2) { + if (parentNode == p || parentNode == q) { + if (oneFound) { + return lca; + } else { + lca = (TreeNode)stack.peek()[0]; + oneFound = true; + } + } + childNode = parentNode.left; + } else { + childNode = parentNode.right; + } + + stack.pop(); + stack.push(new Object[]{parentNode, parentState - 1}); + + if (childNode != null) { + stack.push(new Object[]{childNode, 2}); + } + } else { + if (stack.pop()[0] == lca && oneFound) { + lca = (TreeNode) stack.peek()[0]; + } + } + } + return lca; + } + + private class TreeNode { + int val; + TreeNode left; + TreeNode right; + + TreeNode(int x) { + val = x; + } + } +} diff --git a/Week_02/id_18/LeetCode_242_18.java b/Week_02/id_18/LeetCode_242_18.java new file mode 100644 index 00000000..76e5b135 --- /dev/null +++ b/Week_02/id_18/LeetCode_242_18.java @@ -0,0 +1,149 @@ +package Week_02.id_18; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @author LiveForExperience + * @date 2019/6/4 13:09 + */ +public class LeetCode_242_18 { + public boolean isAnagram1(String s, String t) { + if (s.length() != t.length()) { + return false; + } + + char[] tc = t.toCharArray(); + for (char sc : s.toCharArray()) { + for (int i = 0; i < tc.length; i++) { + if (sc == tc[i]) { + tc[i] = '#'; + break; + } + } + } + + for (char c : tc) { + if (c != '#') { + return false; + } + } + + return true; + } + + public boolean isAnagram2(String s, String t) { + if (s.length() != t.length()) { + return false; + } + + Map map = Arrays.stream(s.split("")).collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + for (String ts : t.split("")) { + if (map.containsKey(ts)) { + map.put(ts, map.get(ts) - 1); + continue; + } + return false; + } + + for (Long value : map.values()) { + if (value != 0) { + return false; + } + } + + return true; + } + + public boolean isAnagram3(String s, String t) { + if (s.length() != t.length()) { + return false; + } + + Map map = s.chars().boxed().collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + for (char c : t.toCharArray()) { + int ci = (int) c; + if (map.containsKey(ci)) { + map.put(ci, map.get(ci) - 1); + continue; + } + return false; + } + + for (Long value : map.values()) { + if (value != 0) { + return false; + } + } + return true; + } + + public boolean isAnagram4(String s, String t) { + if (s.length() != t.length()) { + return false; + } + char[] cs = s.toCharArray(); + char[] ct = t.toCharArray(); + Arrays.sort(cs); + Arrays.sort(ct); + return Arrays.equals(cs, ct); + } + + public boolean isAnagram5(String s, String t) { + if (s.length() != t.length()) { + return false; + } + char[] cs = s.toCharArray(); + char[] ct = t.toCharArray(); + int[] countArr = new int[26]; + + for (int i = 0; i < cs.length; i++) { + countArr[cs[i] - 'a']++; + countArr[ct[i] - 'a']--; + } + + for (int i : countArr) { + if (i != 0) { + return false; + } + } + + return true; + } + + public boolean isAnagram6(String s, String t) { + if (s == null || t == null || s.length() != t.length()) { + return false; + } + int[] prime = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, + 73, 79, 83, 89, 97, 101}; + BigDecimal productS = BigDecimal.valueOf(1); + BigDecimal productT = BigDecimal.valueOf(1); + for (int i = 0; i < s.length(); i++) { + productS = productS.multiply(BigDecimal.valueOf(prime[s.charAt(i) - 'a'])); + } + for (int i = 0; i < t.length(); i++) { + productT = productT.multiply(BigDecimal.valueOf(prime[t.charAt(i) - 'a'])); + } + return productS.compareTo(productT) == 0; + } + + public boolean isAnagram7(String s, String t) { + int[] alphabet = new int[26]; + for (char c : s.toCharArray()) { + alphabet[c - 'a']++; + } + for (char c : t.toCharArray()) { + alphabet[c - 'a']--; + } + for (int a : alphabet) { + if (a != 0) { + return false; + } + } + return true; + } +} diff --git a/Week_02/id_18/LeetCode_3_18.java b/Week_02/id_18/LeetCode_3_18.java new file mode 100644 index 00000000..76f798b2 --- /dev/null +++ b/Week_02/id_18/LeetCode_3_18.java @@ -0,0 +1,86 @@ +package Week_02.id_18; + +import java.util.Deque; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Set; + +/** + * @author LiveForExperience + * @date 2019/6/15 22:04 + */ +public class LeetCode_3_18 { + public int lengthOfLongestSubstring(String s) { + if (s == null || "".equals(s)) { + return 0; + } + + if (s.length() == 1) { + return 1; + } + + return doCheck(s); + } + + private int doCheck(String s) { + Set set = new HashSet<>(); + char[] cs = s.toCharArray(); + for (char c : cs) { + if (set.contains(c)) { + return Math.max(set.size(), doCheck(s.substring(s.indexOf(c) + 1))); + } + set.add(c); + } + + return set.size(); + } + + + public int lengthOfLongestSubstring1(String s) { + Deque characterDeque = new LinkedList<>(); + int result = 0; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (characterDeque.contains(c)) { + int len = characterDeque.size(); + if (len > result) { + result = len; + } + while (c != characterDeque.peek()) { + characterDeque.poll(); + } + characterDeque.poll(); + } + characterDeque.add(c); + } + int size = characterDeque.size(); + return size > result ? size : result; + } + + public int lengthOfLongestSubstring2(String s) { + if (s == null || "".equals(s)) { + return 0; + } + + if (s.length() == 1) { + return 1; + } + + Set set = new HashSet<>(); + return doCheck(s, set); + } + + private int doCheck(String s, Set set) { + char[] cs = s.toCharArray(); + for (char c : cs) { + if (set.contains(c)) { + int len = set.size(); + set.clear(); + return Math.max(len, doCheck(s.substring(s.indexOf(c) + 1), set)); + } + set.add(c); + } + + return set.size(); + } +} diff --git a/Week_02/id_18/LeetCode_783_18.java b/Week_02/id_18/LeetCode_783_18.java new file mode 100644 index 00000000..8c19dfaf --- /dev/null +++ b/Week_02/id_18/LeetCode_783_18.java @@ -0,0 +1,36 @@ +package Week_02.id_18; + +/** + * @author LiveForExperience + * @date 2019/6/14 13:27 + */ +public class LeetCode_783_18 { + public int minDiffInBST(TreeNode root) { + return doSearch(root, null, null, Integer.MAX_VALUE); + } + + private int doSearch(TreeNode root, TreeNode leftNode, TreeNode rightNode, int min) { + if (root == null) { + return min; + } + + int left = leftNode == null ? Integer.MAX_VALUE : leftNode.val - root.val; + int right = rightNode == null ? Integer.MAX_VALUE : root.val - rightNode.val; + + min = Math.min(Math.min(left, right), min); + + int leftChild = doSearch(root.left, root, rightNode, min); + int rightChild = doSearch(root.right, leftNode, root, min); + return Math.min(leftChild, rightChild); + } + + private class TreeNode { + int val; + TreeNode left; + TreeNode right; + + TreeNode(int x) { + val = x; + } + } +} diff --git a/Week_02/id_18/NOTE.md b/Week_02/id_18/NOTE.md index 107ea7d6..88f61cfa 100644 --- a/Week_02/id_18/NOTE.md +++ b/Week_02/id_18/NOTE.md @@ -1 +1,666 @@ # 学习笔记 +## LeetCode_1 +### 题目 +给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 + +你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 + +示例: +``` +给定 nums = [2, 7, 11, 15], target = 9 + +因为 nums[0] + nums[1] = 2 + 7 = 9 +所以返回 [0, 1] +``` +### 解法一 +#### 思路 +1. 2个for循环嵌套,暴力 +2. 时间复杂度O(n^2) +3. 空间复杂度O(1) +#### 代码 +```java +class Solution { + public int[] twoSum(int[] nums, int target) { + if (nums == null || nums.length < 2) { + return 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) { + return new int[]{i,j}; + } + } + } + + return new int[2]; + } +} +``` +### 解法二 +#### 思路 +1. 先遍历数组,把元素作为key,下标作为value,放入hash表,这样也做到了去重 +2. 再遍历一遍数组,先计算target和当前元素的差,在hash表中查找这个差对应的下标,且不是当前元素的下标 +3. 这样时间复杂度就是O(n) +4. 空间复杂度因为多了个map,所以是O(n) +#### 代码 +```java +class Solution { + public int[] twoSum(int[] nums, int target) { + if (nums == null || nums.length < 2) { + return new int[2]; + } + + Map map = new HashMap<>(); + for (int i = 0; i < nums.length; i++) { + map.put(nums[i], i); + } + + for (int i = 0; i < nums.length; i++) { + int j = target - nums[i]; + if (map.containsKey(j) && i != map.get(j)) { + return new int[]{i, map.get(j)}; + } + } + + return new int[2]; + } +} +``` +### 解法三 +#### 思路 +1. 基于解法二,其实不需要先遍历一边数组,全部放到map里,可以边遍历变放 +2. 这样也就不用判断是否重复使用当前元素 +3. 最坏情况会遍历整个数组,所以时间复杂度是O(n) +4. 同样的空间复杂度和解法三类似,最坏情况下空间复杂度是O(n) +#### 代码 +```java +class Solution { + public int[] twoSum(int[] nums, int target) { + if (nums == null || nums.length < 2) { + return new int[2]; + } + + Map map = new HashMap<>(); + for (int i = 0; i < nums.length; i++) { + int j = target - nums[i]; + if (map.containsKey(j)) { + return new int[]{i, map.get(j)}; + } + map.put(nums[i], i); + } + + return new int[2]; + } +} +``` +### 收获 +算法可以不断地迭代改进,像生物进化一样,非常有趣。 +## LeetCode_236 +### 题目 +Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. + +> According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).” + +Example 1: +``` +Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 +Output: 3 +Explanation: The LCA of nodes 5 and 1 is 3. +``` +Example 2: +``` +Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 +Output: 5 +Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition. +``` +### 解法一 +#### 思路 +dfs路径上最早重叠的那个节点,就是它们的最早祖先节点。 +1. 不断地向左右子节点搜索,如果找到返回true,否则false +2. 判断当前节点是不是p或q的一个 +3. 如果以上三种情况有2种是true +4. 那么说明当前节点就是最早祖先节点 +#### 代码 +```java +class Solution { + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + doRecurse(root, p, q); + return result; + } + + private boolean doRecurse(TreeNode current, TreeNode p, TreeNode q) { + if (current == null) { + return false; + } + + int left = doRecurse(current.left, p, q) ? 1 : 0; + int right = doRecurse(current.right, p, q) ? 1 : 0; + int mid = current.val == p.val || current.val == q.val ? 1 : 0; + + if (mid + left + right >= 2) { + result = current; + } + + return mid + left + right > 0; + } +} +``` +### 解法二 +#### 思路 +使用bfs查找两个节点,同时记录查找过程中的路过的父节点 +1. 使用bfs标配的队列 +2. 使用map记录路过的父节点,这样查询父节点的时间复杂度就是O(1) +3. 查找两个节点,当全部查到时开始生成查找p节点的父节点路径的集合 +4. 再用这个集合去让q节点的父节点来匹配,第一个匹配上的就是最早祖先 +#### 代码 +```java +class Solution { + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + Deque stack = new ArrayDeque<>(); + Map parents = new HashMap<>(); + + stack.push(root); + parents.put(root, null); + + while (!parents.containsKey(p) || !parents.containsKey(q)) { + TreeNode current = stack.pop(); + + if (current.left != null) { + stack.push(current.left); + parents.put(current.left, current); + } + + if (current.right != null) { + stack.push(current.right); + parents.put(current.right, current); + } + } + + Set pAncestors = new HashSet<>(); + while (p != null) { + pAncestors.add(p); + p = parents.get(p); + } + + while (!pAncestors.contains(q)) { + q = parents.get(q); + } + + return q; + } +} +``` +### 解法三 +#### 思路 +使用dfs非递归的方法(stack): +1. 从左子树开始向下查找,同时更新当前节点的状态 + - 左右都查过 + - 左边查好了 + - 还没查好 +2. 通过栈不断地向下查,如果发现了和p或q相同的节点,就把它作为LCA,同时记录已经找到一个节点 +3. 如果左边检查完,那么开始检查右边 +4. 如果两边检查完,都没有找到全部两个目标节点,就把这个节点弹出,把这个弹出节点的父节点标记为LCA +5. 循环往复,直到找到两个节点为止 +#### 代码 +```java +class Solution { + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + TreeNode lca = null; + + boolean oneFound = false; + + Stack stack = new Stack<>(); + + stack.push(new Object[]{root, 2}); + + TreeNode childNode; + + while (!stack.isEmpty()) { + Object[] parentArr = stack.peek(); + if (parentArr[0] == null) {return p;} + TreeNode parentNode = (TreeNode) parentArr[0]; + int parentState = (int) parentArr[1]; + if (parentState != 0) { + if (parentState == 2) { + if (parentNode == p || parentNode == q) { + if (oneFound) { + return lca; + } else { + lca = (TreeNode)stack.peek()[0]; + oneFound = true; + } + } + childNode = parentNode.left; + } else { + childNode = parentNode.right; + } + + stack.pop(); + stack.push(new Object[]{parentNode, parentState - 1}); + + if (childNode != null) { + stack.push(new Object[]{childNode, 2}); + } + } else { + if (stack.pop()[0] == lca && oneFound) { + lca = (TreeNode) stack.peek()[0]; + } + } + } + return lca; + } +} +``` +### 收获 +熟悉了BFS和DFS的搜索方式,对递归有了进一步的理解。 +## LeetCode_111 +### 题目 +给定一个二叉树,找出其最小深度。 + +最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 + +说明: 叶子节点是指没有子节点的节点。 + +示例: +``` +给定二叉树 [3,9,20,null,null,15,7], + + 3 + / \ + 9 20 + / \ + 15 7 +返回它的最小深度  2. +``` +### 解法一 +#### 思路 +使用dfs的递归方式 +1. 一开始没有审清除题目,对于从根节点到最近叶子节点的最短路径上的节点数量没有理解 +2. 叶子节点应该是没有左右子树的节点 +3. 所以如果只有一个节点,那么只递归下钻有节点地一边,另一边就不管了 +4. 然后只有当左右都为null的时候才开始计数 +5. 然后开始返回,同时还要有一个变量存储左右节点的最小的那个值,初始的时候用int的最大值 +6. 然后每一层返回的时候都需要+1,代表层数的累加。 +#### 代码 +```java +class Solution { + public int minDepth(TreeNode root) { + if (root == null) { + return 0; + } + + if (root.left == null && root.right == null) { + return 1; + } + + int depth = Integer.MAX_VALUE; + if (root.left != null) { + depth = Math.min(minDepth(root.left), depth); + } + + if (root.right != null) { + depth = Math.min(minDepth(root.right), depth); + } + + return depth + 1; + } +} +``` +### 收获 +审清题目很重要,就像理解需求一样,如果没搞清楚,搞半天也是瞎弄。 +## LeetCode_783 +### 题目 +给定一个二叉搜索树的根结点 root, 返回树中任意两节点的差的最小值。 + +示例: +``` +输入: root = [4,2,6,1,3,null,null] +输出: 1 +解释: +注意,root是树结点对象(TreeNode object),而不是数组。 +``` +给定的树 [4,2,6,1,3,null,null] 可表示为下图: +``` + 4 + / \ + 2 6 + / \ + 1 3 + +最小的差值是 1, 它是节点1和节点2的差值, 也是节点3和节点2的差值。 +``` +注意: +``` +二叉树的大小范围在 2 到 100。 +二叉树总是有效的,每个节点的值都是整数,且不重复。 +``` +### 解法一 +#### 思路 +二叉搜索树的两个定义,老师需要我们O(1)的时间复杂度来反应: +1. 所有的左子树都小于根节点,所有的右子树都大于根节点,循环往复 +2. 中序搜索的路径是升序的 +所以直接就反应了使用dfs递归搜索的方式,但是没办法确定具体的逻辑,于是参考了国际站的方法: +1. 左边子树的差值就是上一个节点减去当前节点 +2. 右边子树的差值就是当前节点减去上一个节点 +3. 然后加上要记录的最小值 +4. 于是涉及到的所有参数就是4个 + - 当前节点 + - 上一个节点(用左和右两个参数表示,因为不同的运算方式) + - 最小值 +5. 然后就是递归运算,求左右子树返回的差值中的最小值 +#### 代码 +```java +class Solution { + public int minDiffInBST(TreeNode root) { + return doSearch(root, null, null, Integer.MAX_VALUE); + } + + private int doSearch(TreeNode root, TreeNode leftNode, TreeNode rightNode, int min) { + if (root == null) { + return min; + } + + int left = leftNode == null ? Integer.MAX_VALUE : leftNode.val - root.val; + int right = rightNode == null ? Integer.MAX_VALUE : root.val - rightNode.val; + + min = Math.min(Math.min(left, right), min); + + int leftChild = doSearch(root.left, root, rightNode, min); + int rightChild = doSearch(root.right, leftNode, root, min); + return Math.min(leftChild, rightChild); + } +} +``` +### 收获 + +## LeetCode_235 +### 题目 +给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 + +百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。” + +例如,给定如下二叉搜索树:  root = [6,2,8,0,4,7,9,null,null,3,5] + +示例 1: +``` +输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 +输出: 6 +解释: 节点 2 和节点 8 的最近公共祖先是 6。 +``` +示例 2: +``` +输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 +输出: 2 +解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。 +```  +说明: +``` +所有节点的值都是唯一的。 +p、q 为不同节点且均存在于给定的二叉搜索树中。 +``` +### 解法一 +#### 思路 +二叉搜索树的中序搜索是升序的,所以最早祖先就是 +1. node >= q && node <= p +2. node <= q && node >= p +这样直接dfs就能查到这个节点 +#### 代码 +```java +class Solution { + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + if (found(root, p, q)) { + return root; + } + + Stack stack = new Stack<>(); + stack.push(root); + + while (!stack.isEmpty()) { + TreeNode node = stack.pop(); + + if (node != null) { + if (found(node, p, q)) { + return node; + } + + stack.push(node.left); + stack.push(node.right); + } + } + + return null; + } + + private boolean found(TreeNode node, TreeNode p, TreeNode q) { + return p.val <= node.val && q.val >= node.val || + p.val >= node.val && q.val <= node.val; + } +} +``` +### 解法二 +#### 思路 +借鉴国际站的dfs递归解法,同时对解法一的代码进行了优化,速度快了很多,应该算是进行了剪枝。 +1. 如果q和p的值都小于root,就搜索左子树 +2. 如果都大于root就搜索右子树 +3. 否则就说明当前节点一定是如下三种情况,且无论哪种情况,当前节点都是lca + - p是当前节点,且q也在这个路径上 + - 如上,只是p和q换一下 + - p和q分别在当前节点的左右子树的路径上 +#### 代码 +```java +class Solution { + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + int parentVal = root.val; + int pVal = p.val; + int qVal = q.val; + + if (pVal < parentVal && qVal < parentVal) { + return lowestCommonAncestor(root.left, p, q); + } else if (pVal > parentVal && qVal > parentVal) { + return lowestCommonAncestor(root.right, p, q); + } else { + return root; + } + } +} +``` +如下是对解法一的优化代码: +```java +class Solution { + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + Stack stack = new Stack<>(); + stack.push(root); + + while (!stack.isEmpty()) { + TreeNode node = stack.pop(); + + if (node != null) { + if (p.val < node.val && q.val < node.val) { + stack.push(node.left); + } else if (p.val > node.val && q.val > node.val){ + stack.push(node.right); + } else { + return node; + } + } + } + + return null; + } +} +``` +### 收获 +用到了剪枝,优化的效果非常明显,也进一步熟悉了dfs的递归和非递归的用法 +## LeetCode_3 +### 题目 +给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。 + +示例 1: +``` +输入: "abcabcbb" +输出: 3 +解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 +``` +示例 2: +``` +输入: "bbbbb" +输出: 1 +解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。 +示例 3: +``` +``` +输入: "pwwkew" +输出: 3 +解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 +  请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。 +``` +### 解法一 +#### 思路 +首先吸取之前叶子节点审题不清的教训,分清除了子序列和子串之间的区别。这题是要计算最长的字串。所以不是简单的去重计算字符个数。 +1. 使用hash表去重 +2. 因为每次重复的时候,意味着从重复的那个字符的后一位开始重新计算长度,所以需要递归的重复计算subString那个字符后的新字符串 +3. 然后递归返回的时候比一下这一层和返回的那层的长度最大值 +#### 代码 +```java +class Solution { + public int lengthOfLongestSubstring(String s) { + if (s == null || "".equals(s)) { + return 0; + } + + if (s.length() == 1) { + return 1; + } + + return doCheck(s); + } + + private int doCheck(String s) { + Set set = new HashSet<>(); + char[] cs = s.toCharArray(); + for (char c : cs) { + if (set.contains(c)) { + return Math.max(set.size(), doCheck(s.substring(s.indexOf(c) + 1))); + } + set.add(c); + } + + return set.size(); + } +} +``` +### 解法二 +#### 思路 +使用队列存储字符,利用先进先出的特性,加上字符串中的字符下标,实现解法一的递归subString的逻辑 +1. 遍历字符数组; +2. 把不重复的字符直接放入队列; +3. 如果队列中有重复的字符,说明到了计算长度的时候了,算一下暂存长度的变量和队列的长度谁长,并暂存那个长的; +4. 把队列中与当前字符重复的字符及之前的其他字符全部出队; +5. 然后循环往复,并最后返回队列及暂存变量中长的那个作为结果。 +#### 代码 +```java +class Solution { + public int lengthOfLongestSubstring(String s) { + Deque characterDeque = new LinkedList<>(); + int result = 0; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (characterDeque.contains(c)) { + int len = characterDeque.size(); + if (len > result) { + result = len; + } + while (c != characterDeque.peek()) { + characterDeque.poll(); + } + characterDeque.poll(); + } + characterDeque.add(c); + } + int size = characterDeque.size(); + return size > result ? size : result; + } +} +``` +### 解法三 +#### 思路 +在解法一中,每一层的下钻都会new出一个set对象,这样大大浪费了空间,于是只使用一个set贯穿始终。这样大大减少了空间占用的情况。 +#### 代码 +```java +public class Solution { + public int lengthOfLongestSubstring(String s) { + if (s == null || "".equals(s)) { + return 0; + } + + if (s.length() == 1) { + return 1; + } + + Set set = new HashSet<>(); + return doCheck(s, set); + } + + private int doCheck(String s, Set set) { + char[] cs = s.toCharArray(); + for (char c : cs) { + if (set.contains(c)) { + int len = set.size(); + set.clear(); + return Math.max(len, doCheck(s.substring(s.indexOf(c) + 1), set)); + } + set.add(c); + } + + return set.size(); + } +} +``` +### 收获 +肯定可以优化呀,pr以后继续优化一下。在解法三种对解法一的空间复杂度情况进行了优化。 +## LeetCode_242 +### 题目 +给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 + +示例 1: +``` +输入: s = "anagram", t = "nagaram" +输出: true +``` +示例 2: +``` +输入: s = "rat", t = "car" +输出: false +说明: +你可以假设字符串只包含小写字母。 +``` +### 解法一 +#### 思路 +使用长度为26的int数组代表字符串中可能出现的字符 +1. 两个字符数组分别遍历 +2. 一个遍历的时候使用**字符 - 'a'**的方式对应到长度26的数组下标上++ +3. 另一个就-- +4. 最后再遍历字符数组,只要哪个元素不是0,就说明两个不是异位词 +#### 代码 +```java +public class Solution { + public boolean isAnagram7(String s, String t) { + int[] alphabet = new int[26]; + for (char c : s.toCharArray()) { + alphabet[c - 'a']++; + } + for (char c : t.toCharArray()) { + alphabet[c - 'a']--; + } + for (int a : alphabet) { + if (a != 0) { + return false; + } + } + return true; + } +} +``` +### 收获 +242题之前做过很多种解,这次是从一个同学的代码中review到的,和我之前的某一个解法类似,但思路更清晰,代码更简单,学习了。 \ No newline at end of file diff --git a/Week_02/id_2/LeetCode_101_2.java b/Week_02/id_2/LeetCode_101_2.java new file mode 100644 index 00000000..83f01162 --- /dev/null +++ b/Week_02/id_2/LeetCode_101_2.java @@ -0,0 +1,106 @@ +//Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). +// +// For example, this binary tree [1,2,2,3,4,4,3] is symmetric: +// +// +// 1 +// / \ +// 2 2 +// / \ / \ +//3 4 4 3 +// +// +// +// +// But the following [1,2,2,null,3,null,3] is not: +// +// +// 1 +// / \ +// 2 2 +// \ \ +// 3 3 +// +// +// +// +// Note: +//Bonus points if you could solve it both recursively and iteratively. +// + +package com.llz.algorithm.algorithm2019.secondweek; + +import com.llz.algorithm.algorithm2019.firstweek.TreeNode; +import java.util.Deque; +import java.util.LinkedList; + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ + +public class LeetCode_101_2 { + + /** + * Time and space complexity is O(n), n is the number of nodes in the tree. + * @param root + * @return + */ + public boolean isSymmetricByTraverse(TreeNode root) { + return traverse(root, root); + } + + public boolean traverse(TreeNode cur, TreeNode mirr) { + if (cur == null && mirr == null) + return true; + if (cur == null || mirr == null) { + return false; + } + if (cur.val != mirr.val) + return false; + return traverse(cur.left, mirr.right) && traverse(cur.right, mirr.left); + + } + + /** + * Time and space complexity is O(n), n is the number of nodes in the tree. + * However, traverse method is faster than the iteration method. I think it owns to + * the cost of creation and the operation of the deque. + * @param root + * @return + */ + public boolean isSymmetricByIteration(TreeNode root) { + Deque deque = new LinkedList<>(); + deque.add(root); + deque.add(root); + TreeNode cur, mirr; + while (!deque.isEmpty()) { + cur = deque.poll(); + mirr = deque.poll(); + if (cur == null && mirr == null) continue; + if (cur == null || mirr == null) return false; + if (cur.val != mirr.val) return false; + deque.add(cur.left); + deque.add(mirr.right); + deque.add(cur.right); + deque.add(mirr.left); + } + return true; + } + + public static void main(String[] args) { + TreeNode root = new TreeNode(1); + root.left = new TreeNode(3); + root.right = new TreeNode(3); + root.left.left = new TreeNode(4); + root.left.right = new TreeNode(5); + root.right.left = new TreeNode(5); + LeetCode_101_2 s = new LeetCode_101_2(); + System.out.println(new LeetCode_101_2().isSymmetricByTraverse(root)); + } +} diff --git a/Week_02/id_2/LeetCode_102_2.java b/Week_02/id_2/LeetCode_102_2.java new file mode 100644 index 00000000..1afc43b6 --- /dev/null +++ b/Week_02/id_2/LeetCode_102_2.java @@ -0,0 +1,92 @@ +//Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level). +// +// +//For example: +//Given binary tree [3,9,20,null,null,15,7], +// +// 3 +// / \ +// 9 20 +// / \ +// 15 7 +// +// +// +//return its level order traversal as: +// +//[ +// [3], +// [9,20], +// [15,7] +//] +// +// + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ + +package com.llz.algorithm.algorithm2019.secondweek; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; + +import com.llz.algorithm.algorithm2019.firstweek.TreeNode; + +public class LeetCode_102_2 { + + /** + * Time complexity is O(n) and space complexity is O(n) as well. + * + * @param root + * @return + */ + public List> levelOrder(TreeNode root) { + List> res = new ArrayList<>(); + if (root == null) return res; + Queue queue = new ArrayDeque<>(); + queue.add(root); + while (!queue.isEmpty()) { + int size = queue.size(); + List list = new ArrayList<>(); + for (int i = 0; i < size; i++) { + TreeNode temp = queue.remove(); + list.add(temp.val); + if (temp.left != null) + queue.add(temp.left); + if (temp.right != null) + queue.add(temp.right); + } + res.add(list); + } + return res; + } + + /** + * Time complexity is O(n) and space complexity is O(n) as well. + * Another dfs solution referenced from discussion. + * @param root + * @return + */ + public List> levelOrderByDfs(TreeNode root) { + List> res = new ArrayList<>(); + dfs(res, root, 0); + return res; + } + + public void dfs(List> res, TreeNode root, int height) { + if (root == null) return; + if (height == res.size()) res.add(new ArrayList<>()); + res.get(height).add(root.val); + dfs(res, root.left, height + 1); + dfs(res, root.right, height + 1); + } +} diff --git a/Week_02/id_2/LeetCode_103_2.java b/Week_02/id_2/LeetCode_103_2.java new file mode 100644 index 00000000..f4a8a13d --- /dev/null +++ b/Week_02/id_2/LeetCode_103_2.java @@ -0,0 +1,152 @@ +//Given a binary tree, return the zigzag level order traversal of its nodes' values. +// (ie, from left to right, then right to left for the next level and alternate between). +// +// +//For example: +//Given binary tree [3,9,20,null,null,15,7], +// +// 3 +// / \ +// 9 20 +// / \ +// 15 7 +// +// +// +//return its zigzag level order traversal as: +// +//[ +// [3], +// [20,9], +// [15,7] +//] +// +// + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ + +package com.llz.algorithm.algorithm2019.secondweek; + +import java.util.*; + +import com.llz.algorithm.algorithm2019.firstweek.TreeNode; + +public class LeetCode_103_2 { + + /** + * Original version + * Time complexity is O(n), space complexity is O(n) + * + * @param root + * @return + */ + public List> zigzagLevelOrder(TreeNode root) { + List> list = new ArrayList<>(); + if (root == null) return list; + + Deque queue = new ArrayDeque<>(); + Deque innerQueue = new ArrayDeque<>(); + queue.add(root); + List innerList = new ArrayList<>(); + innerList.add(root.val); + list.add(innerList); + + int size = 0; + boolean leftToRight = false; + TreeNode temp = null; + while (!queue.isEmpty()) { + size = queue.size(); + innerList = new ArrayList<>(); + for (int i = 0; i < size; i++) { + temp = queue.removeLast(); + if (leftToRight) { + if (temp.left != null) { + innerQueue.add(temp.left); + innerList.add(temp.left.val); + } + if (temp.right != null) { + innerQueue.add(temp.right); + innerList.add(temp.right.val); + } + } else { + if (temp.right != null) { + innerQueue.add(temp.right); + innerList.add(temp.right.val); + } + if (temp.left != null) { + innerQueue.add(temp.left); + innerList.add(temp.left.val); + } + } + } + if (innerList.size() != 0) + list.add(innerList); + queue = innerQueue; + innerQueue = new ArrayDeque<>(); + leftToRight = leftToRight == true ? false : true; + } + return list; + } + + + /** + * A more cleaner and easier code referenced from discussion + * with only one queue compared with two queues that used by my original version. + * Remember better utilize JDK API, think about using list.add(index, val) instead of construct an stack. + * Time complexity is O(n) and space complexity is O(n) as well. + * + * @param root + * @return + */ + public List> zigzagLevelOrder2(TreeNode root) { + List> res = new ArrayList<>(); + if (root == null) return res; + boolean leftToRight = false; + Queue queue = new ArrayDeque<>(); + List list = new ArrayList<>(); + queue.add(root); + while (!queue.isEmpty()) { + int size = queue.size(); + for (int i = 0; i < size; i++) { + TreeNode temp = queue.remove(); + if (leftToRight) + list.add(0, temp.val); + else + list.add(temp.val); + if (temp.left != null) + queue.add(temp.left); + if (temp.right != null) + queue.add(temp.right); + } + leftToRight = !leftToRight; + res.add(list); + list = new ArrayList<>(); + } + return res; + } + + public static void main(String[] args) { + TreeNode root = new TreeNode(1); + root.left = new TreeNode(2); + root.right = new TreeNode(3); + root.left.left = new TreeNode(4); + root.left.right = new TreeNode(5); + root.right.left = new TreeNode(6); + root.right.right = new TreeNode(7); + root.left.left.left = new TreeNode(8); + root.left.right.left = new TreeNode(9); + root.right.right.left = new TreeNode(10); + + LeetCode_103_2 lc = new LeetCode_103_2(); + List> list = lc.zigzagLevelOrder2(root); + System.out.println(list); + } +} diff --git a/Week_02/id_2/LeetCode_111_2.java b/Week_02/id_2/LeetCode_111_2.java new file mode 100644 index 00000000..3edfa5f2 --- /dev/null +++ b/Week_02/id_2/LeetCode_111_2.java @@ -0,0 +1,153 @@ +//Given a binary tree, find its minimum depth. +// +// The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node. +// +// Note: A leaf is a node with no children. +// +// Example: +// +// Given binary tree [3,9,20,null,null,15,7], +// +// +// 3 +// / \ +// 9 20 +// / \ +// 15 7 +// +// return its minimum depth = 2. +// + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ + +package com.llz.algorithm.algorithm2019.secondweek; + +import com.llz.algorithm.algorithm2019.firstweek.TreeNode; + +import java.util.ArrayDeque; +import java.util.Deque; + +public class LeetCode_111_2 { + + /** + * A clean version referenced from discussion + * + * @param root + * @return + */ + public int minDepthByTraverseRefact2(TreeNode root) { + if (root == null) + return 0; + int left = minDepthByTraverseRefact2(root.left); + int right = minDepthByTraverseRefact2(root.right); + return (left == 0 || right == 0) ? (left + right + 1) : Math.min(left, right) + 1; + } + + + /** + * My refactoring version + * + * @param root + * @return + */ + public int minDepthByTraverseRefact(TreeNode root) { + if (root == null) + return 0; + int left = minDepthByTraverseRefact(root.left); + int right = minDepthByTraverseRefact(root.right); + if (left == 0) + return right + 1; + else if (right == 0) + return left + 1; + else + return Math.min(left, right) + 1; + } + + /** + * Original version + * Time complexity O(n), space complexity O(n) (worst case) + * If the given tree is balanced, the time complexity of both time and space is O(logn). + * + * @param root + * @return + */ + public int minDepthByTraverse(TreeNode root) { + if (root == null) + return 0; + if (root.left == null && root.right == null) + return 1; + else if (root.left == null) + return minDepthByTraverse(root.right) + 1; + else if (root.right == null) + return minDepthByTraverse(root.left) + 1; + else + return Math.min(minDepthByTraverse(root.left), minDepthByTraverse(root.right)) + 1; + } + + /** + * Use iteration + * Time complexity O(n), space complexity O(n) (worst case) + * + * @param root + * @return + */ + public int minDepthByInteration(TreeNode root) { + if (root == null) return 0; + int depth = 0; + Deque queue = new ArrayDeque(); + queue.add(root); + int size = 0; + while (!queue.isEmpty()) { + size = queue.size(); + for (int i = 0; i < size; i++) { + root = queue.remove(); + if (root.left != null) + queue.add(root.left); + if (root.right != null) + queue.add(root.right); + if (root.left == null && root.right == null) { + return depth + 1; + } + } + depth++; + } + return depth; + } + + /** + * Another easier method for iteration by using sentinel. + * @param root + * @return + */ + public int minDepthByInteration2(TreeNode root) { + if (root == null) return 0; + int depth = 0; + Deque queue = new ArrayDeque(); + queue.add(root); + TreeNode endOfLevel = root; + while (!queue.isEmpty()) { + root = queue.remove(); + if (root.left != null) + queue.add(root.left); + if (root.right != null) + queue.add(root.right); + if (root.left == null && root.right == null) { + return depth + 1; + } + if (root == endOfLevel) { + endOfLevel = (root.right == null ? root.left : root.right); + depth++; + } + } + return depth; + } + +} diff --git a/Week_02/id_2/LeetCode_235_2.java b/Week_02/id_2/LeetCode_235_2.java new file mode 100644 index 00000000..08e396d7 --- /dev/null +++ b/Week_02/id_2/LeetCode_235_2.java @@ -0,0 +1,132 @@ +//Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST. +// +// According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).” +// +// Given binary search tree: root = [6,2,8,0,4,7,9,null,null,3,5] +// +// +// +// Example 1: +// +// +//Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 +//Output: 6 +//Explanation: The LCA of nodes 2 and 8 is 6. +// +// +// Example 2: +// +// +//Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 +//Output: 2 +//Explanation: The LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself according to the LCA definition. +// +// +// +// +// Note: +// +// +// All of the nodes' values will be unique. +// p and q are different and both values will exist in the BST. +// +// + +package com.llz.algorithm.algorithm2019.secondweek; + +import com.llz.algorithm.algorithm2019.firstweek.TreeNode; + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ + +public class LeetCode_235_2 { + + private TreeNode lca = null; + + /** + * For all the traverse methods regarding this solution, the time complexity is O(n) and space complexity + * is O(n) as we use stack for recursion. + * If the given BST is a balanced tree, the time complexity would be O(logn). + * @param root + * @param p + * @param q + * @return + */ + public TreeNode lowestCommonAncestorByTraverse1(TreeNode root, TreeNode p, TreeNode q) { + getLowestCommonAncestor(root, p, q); + return lca; + } + + public void getLowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + if (root == null) + return; + if (p.val < root.val && q.val < root.val) + getLowestCommonAncestor(root.left, p, q); + else if (p.val > root.val && q.val > root.val) + getLowestCommonAncestor(root.right, p, q); + else + lca = root; + } + + /** + * Another traverse method without create an Object just return the result + * + * @param root + * @param p + * @param q + * @return + */ + public TreeNode lowestCommonAncestorByTraverse2(TreeNode root, TreeNode p, TreeNode q) { + if (root == null) + return root; + if (p.val < root.val && q.val < root.val) + return lowestCommonAncestorByTraverse2(root.left, p, q); + else if (p.val > root.val && q.val > root.val) + return lowestCommonAncestorByTraverse2(root.right, p, q); + else + return root; + } + + /** + * Time complexity is O(n) and space complexity is O(1) + * @param root + * @param p + * @param q + * @return + */ + public TreeNode lowestCommonAncestorByIteraton(TreeNode root, TreeNode p, TreeNode q) { + while (root != null) { + if (p.val < root.val && q.val < root.val) + root = root.left; + else if (p.val > root.val && q.val > root.val) + root = root.right; + else + break; + } + return root; + } + + public static void main(String[] args) { + TreeNode root = new TreeNode(6); + TreeNode p = new TreeNode(2); + root.left = p; + root.right = new TreeNode(8); + root.left.left = new TreeNode(0); + root.left.right = new TreeNode(4); + root.left.right.left = new TreeNode(3); + TreeNode q = new TreeNode(5); + root.left.right.right = q; + root.right.left = new TreeNode(7); + root.right.right = new TreeNode(9); + LeetCode_235_2 lc1 = new LeetCode_235_2(); + TreeNode lc = lc1.lowestCommonAncestorByTraverse2(root, p, q); + System.out.println(lc.val); + } +} diff --git a/Week_02/id_2/LeetCode_236_2.java b/Week_02/id_2/LeetCode_236_2.java new file mode 100644 index 00000000..ee8f444a --- /dev/null +++ b/Week_02/id_2/LeetCode_236_2.java @@ -0,0 +1,146 @@ +//Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. +// +// According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).” +// +// Given the following binary tree: root = [3,5,1,6,2,0,8,null,null,7,4] +// +// +// +// Example 1: +// +// +//Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 +//Output: 3 +//Explanation: The LCA of nodes 5 and 1 is 3. +// +// +// Example 2: +// +// +//Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 +//Output: 5 +//Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition. +// +// +// +// +// Note: +// +// +// All of the nodes' values will be unique. +// p and q are different and both values will exist in the binary tree. +// +// + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ + +package com.llz.algorithm.algorithm2019.secondweek; + +import com.llz.algorithm.algorithm2019.firstweek.TreeNode; + +import java.util.*; + +public class LeetCode_236_2 { + + /** + * Time complexity is O(n), space complexity is O(n). + * + * @param root + * @param p + * @param q + * @return + */ + public TreeNode lowestCommonAncestorByIteration(TreeNode root, TreeNode p, TreeNode q) { + if (root == null) return null; + Queue queue = new ArrayDeque<>(); + Map map = new HashMap(); + map.put(root, null); + queue.add(root); + int find = 2; + while (!queue.isEmpty() && find != 0) { + root = queue.remove(); + if (root == p) + find--; + if (root == q) + find--; + if (root.left != null) { + map.put(root.left, root); + queue.add(root.left); + } + if (root.right != null) { + map.put(root.right, root); + queue.add(root.right); + } + } + + List list = new ArrayList<>(); + TreeNode temp = q; + while (q != null) { + list.add(q); + q = map.get(q); + } + + while (!list.contains(p)) { + p = map.get(p); + } + return p; + } + + private TreeNode lca = null; + + /** + * Time complexity is O(n), space complexity is O(n). + * @param root + * @param p + * @param q + * @return + */ + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + lca = null; + dfs(root, p, q); + return lca; + } + + public boolean dfs(TreeNode root, TreeNode p, TreeNode q) { + if (root == null) + return false; + int left = dfs(root.left, p, q) ? 1 : 0; + int right = dfs(root.right, p, q) ? 1 : 0; + int mid = 0; + if (p == root | q == root) { + mid = 1; + } + if (left + mid + right >= 2) + lca = root; + return (left + right + mid) > 0; + } + + public static void test1() { + TreeNode root = new TreeNode(3); + TreeNode p = new TreeNode(5); + root.left = p; + root.right = new TreeNode(1); + root.left.left = new TreeNode(6); + root.left.right = new TreeNode(2); + root.left.right.left = new TreeNode(7); + TreeNode q = new TreeNode(4); + root.left.right.right = q; + root.right.left = new TreeNode(0); + root.right.right = new TreeNode(8); + LeetCode_236_2 lca = new LeetCode_236_2(); + TreeNode lc = lca.lowestCommonAncestor(root, p, q); + System.out.println(lc.val); + } + + public static void main(String[] args) { + test1(); + } +} diff --git a/Week_02/id_2/LeetCode_3_2.java b/Week_02/id_2/LeetCode_3_2.java new file mode 100644 index 00000000..72d4c10f --- /dev/null +++ b/Week_02/id_2/LeetCode_3_2.java @@ -0,0 +1,130 @@ +//Given a string, find the length of the longest substring without repeating characters. +// +// +// Example 1: +// +// +//Input: "abcabcbb" +//Output: 3 +//Explanation: The answer is "abc", with the length of 3. +// +// +// +// Example 2: +// +// +//Input: "bbbbb" +//Output: 1 +//Explanation: The answer is "b", with the length of 1. +// +// +// +// Example 3: +// +// +//Input: "pwwkew" +//Output: 3 +//Explanation: The answer is "wke", with the length of 3. +// Note that the answer must be a substring, "pwke" is a subsequence and not a substring. +// +// +// +// +// + +package com.llz.algorithm.algorithm2019.secondweek; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class LeetCode_3_2 { + + + /** + * Referenced from solution by using sliding window. + * Time complexity is O(n) and space complexity is O(n) (max value of n is the length of string). + * + * @param s + * @return + */ + public int lengthOfLongestSubstringBySW(String s) { + int maxLength = 0; + Set set = new HashSet<>(); + int length = s.length(); + int i = 0, j = 0; + while (i < length && j < length) { + if (!set.contains(s.charAt(j))) { + maxLength = Math.max(maxLength, j - i + 1); + set.add(s.charAt(j++)); + } else + set.remove(s.charAt(i++)); + } + return maxLength; + } + + /** + * An optimised version of lengthOfLongestSubstringBySW by further reducing iteration times. + * Time complexity is O(n) and space complexity is O(n). + *

+ * Watch the right boundary! + * + * @param s + * @return + */ + public int lengthOfLongestSubstringBySWOptimized(String s) { + Map map = new HashMap<>(); + int maxLength = 0; + int length = s.length(); + int i = 0, j = 0; + while (i < length && j < length) { + Character c = s.charAt(j); + if (map.containsKey(c)) { + i = Math.max(map.get(c) + 1, i); + } + map.put(c, j++); + maxLength = Math.max(maxLength, j - i); + } + return maxLength; + } + + private int maxLength = 1; + + /** + * Brutal Force + * Time complexity is O(n^3) and space complexity is O(n^3). + * Time Limit Exceed + * + * @param s + * @return + */ + public int lengthOfLongestSubstringByBrutalForce(String s) { + if (null == s || s.length() == 0) + return 0; + int length = s.length(); + for (int i = 0; i < length; i++) { + for (int j = i + 1; j < length; j++) + checkSubStr(i, j, s); + } + return maxLength; + } + + public void checkSubStr(int begin, int end, String s) { + Set set = new HashSet<>(); + String subStr = s.substring(begin, end + 1); + for (int i = 0; i < subStr.length(); i++) { + if (set.contains(subStr.charAt(i))) + return; + else + set.add(subStr.charAt(i)); + } + if (maxLength < (end - begin + 1)) + maxLength = end - begin + 1; + } + + public static void main(String[] args) { + LeetCode_3_2 l = new LeetCode_3_2(); + System.out.println(l.lengthOfLongestSubstringBySWOptimized("tmmzuxt)")); + } +} diff --git a/Week_02/id_2/LeetCode_692_2.java b/Week_02/id_2/LeetCode_692_2.java new file mode 100644 index 00000000..d039ae0c --- /dev/null +++ b/Week_02/id_2/LeetCode_692_2.java @@ -0,0 +1,101 @@ +//Given a non-empty list of words, return the k most frequent elements. +// Your answer should be sorted by frequency from highest to lowest. If two words have the same frequency, then the word with the lower alphabetical order comes first. +// +// Example 1: +// +//Input: ["i", "love", "leetcode", "i", "love", "coding"], k = 2 +//Output: ["i", "love"] +//Explanation: "i" and "love" are the two most frequent words. +// Note that "i" comes before "love" due to a lower alphabetical order. +// +// +// +// Example 2: +// +//Input: ["the", "day", "is", "sunny", "the", "the", "the", "sunny", "is", "is"], k = 4 +//Output: ["the", "is", "sunny", "day"] +//Explanation: "the", "is", "sunny" and "day" are the four most frequent words, +// with the number of occurrence being 4, 3, 2 and 1 respectively. +// +// +// +// Note: +// +// You may assume k is always valid, 1 ≤ k ≤ number of unique elements. +// Input words contain only lowercase letters. +// +// +// +// Follow up: +// +// Try to solve it in O(n log k) time and O(n) extra space. +// +// +package com.llz.algorithm.algorithm2019.secondweek; + +import java.util.*; + +public class LeetCode_692_2 { + + class WordNode implements Comparable { + String word; + int times; + + public WordNode(String word) { + this.word = word; + this.times = 1; + } + + + public int compareTo(WordNode o) { + if (this.times > o.times) + return -1; + else if (this.times == o.times) { + return this.word.compareTo(o.word); + + } else { + return 1; + } + } + } + + /** + * Using priorityQueue, time complexity is O(nlogn)+O(n)+O(k) = O(n). + * space complexity is O(n) + * @param words + * @param k + * @return + */ + public List topKFrequent(String[] words, int k) { + List list = new ArrayList<>(); + PriorityQueue pq = new PriorityQueue<>(k); + HashMap map = new HashMap<>(); + for (int i = 0; i < words.length; i++) { + if (map.containsKey(words[i])) { + WordNode wn = map.get(words[i]); + wn.times++; + map.put(words[i], wn); + } else + map.put(words[i], new WordNode(words[i])); + WordNode w = map.get(words[i]); + } + + Iterator> lt = map.entrySet().iterator(); + while (lt.hasNext()) { + pq.add(lt.next().getValue()); + } + + int j = 0; + while (!pq.isEmpty()) { + list.add(pq.poll().word); + if (++j == k) break; + } + return list; + } + + public static void main(String[] args) { + LeetCode_692_2 l = new LeetCode_692_2(); + String[] words = {"i", "love", "leetcode", "i", "love", "coding"}; + System.out.println(l.topKFrequent(words, 2)); + } +} diff --git a/Week_02/id_2/LeetCode_783_2.java b/Week_02/id_2/LeetCode_783_2.java new file mode 100644 index 00000000..7d205655 --- /dev/null +++ b/Week_02/id_2/LeetCode_783_2.java @@ -0,0 +1,94 @@ +//Given a Binary Search Tree (BST) with the root node root, return the minimum difference between the values of any two different nodes in the tree. +// +// Example : +// +// +//Input: root = [4,2,6,1,3,null,null] +//Output: 1 +//Explanation: +//Note that root is a TreeNode object, not an array. +// +//The given tree [4,2,6,1,3,null,null] is represented by the following diagram: +// +// 4 +// / \ +// 2 6 +// / \ +// 1 3 +// +//while the minimum difference in this tree is 1, it occurs between node 1 and node 2, also between node 3 and node 2. +// +// +// Note: +// +// +// The size of the BST will be between 2 and 100. +// The BST is always valid, each node's value is an integer, and each node's value is different. +// + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ + +package com.llz.algorithm.algorithm2019.secondweek; + +import com.llz.algorithm.algorithm2019.firstweek.TreeNode; + +import java.util.ArrayList; +import java.util.List; + +public class LeetCode_783_2 { + + + /** + * Using brutal force, calculate distance between any two separate nodes in BST + * and acquire the minDistance. + * Time complexity is O(n^2), space complexity is O(n). + * + * @param root + * @return + */ + public int minDiffInBSTByBF(TreeNode root) { + int minDistByBF = Integer.MAX_VALUE; + List list = new ArrayList<>(); + inOrder(root, list); + for (int i = 0; i < list.size(); i++) { + for (int j = i + 1; j < list.size(); j++) + if (Math.abs(list.get(j).val - list.get(i).val) < minDistByBF) + minDistByBF = Math.abs(list.get(j).val - list.get(i).val); + + } + return minDistByBF; + } + + public void inOrder(TreeNode root, List list) { + if (root == null) + return; + inOrder(root.left, list); + list.add(root); + inOrder(root.right, list); + } + + private int minDist = Integer.MAX_VALUE; + private TreeNode pre = null; + + /** + * Using InOrderTraverse, the time complexity is O(n) as well as space complexity. + * + * @param root + * @return + */ + public int minDiffInBST(TreeNode root) { + if (root.left != null) minDiffInBST(root.left); + if (pre != null) minDist = Math.min(root.val - pre.val, minDist); + pre = root; + if (root.right != null) minDiffInBST(root.right); + return minDist; + } +} diff --git a/Week_02/id_2/LeetCode_938_2.java b/Week_02/id_2/LeetCode_938_2.java new file mode 100644 index 00000000..72ae6499 --- /dev/null +++ b/Week_02/id_2/LeetCode_938_2.java @@ -0,0 +1,104 @@ +//Given the root node of a binary search tree, return the sum of values of all nodes with value between L and R (inclusive). +// +// The binary search tree is guaranteed to have unique values. +// +// +// +// +// Example 1: +// +// +//Input: root = [10,5,15,3,7,null,18], L = 7, R = 15 +//Output: 32 +// +// +// +// Example 2: +// +// +//Input: root = [10,5,15,3,7,13,18,1,null,6], L = 6, R = 10 +//Output: 23 +// +// +// +// +// Note: +// +// +// The number of nodes in the tree is at most 10000. +// The final answer is guaranteed to be less than 2^31. +// +// +// + +package com.llz.algorithm.algorithm2019.secondweek; + +import com.llz.algorithm.algorithm2019.firstweek.TreeNode; + +import java.util.ArrayDeque; +import java.util.Deque; + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class LeetCode_938_2 { + + private int sum = 0; + + public int rangeSumBSTByTraverse(TreeNode root, int L, int R) { + dfs(root, L, R); + return sum; + } + + /** + * There is time cost difference depends on how you deal with the case of null root. + * If you write "if (root == null) return;",then the function will backtrack + * and cost more time than if you just eliminate the "root equals null" situation by writing + * "if (root != null) {...} ". + * Time complexity is O(n) and space complexity is O(h)(h is height of BST). + * If the given BST is balanced, then the time complexity is O(logn) and space complexity is O(logn) as well. + * + * @param root + * @param L + * @param R + */ + public void dfs(TreeNode root, int L, int R) { + if (root != null) { + if (root.val >= L && root.val <= R) + sum += root.val; + if (root.val > L) dfs(root.left, L, R); + if (root.val < R) dfs(root.right, L, R); + } + } + + /** + * Use stack to record the possible target nodes. + * Time complexity is O(n) and space complexity is O(h)(h is height of BST). + * If the given BST is balanced, then the time complexity is O(logn) and space complexity is O(logn) as well. + * @param root + * @param L + * @param R + * @return + */ + public int rangeSumBSTByIteration(TreeNode root, int L, int R) { + if (root == null) return 0; + int sum = 0; + Deque stack = new ArrayDeque<>(); + stack.push(root); + while (!stack.isEmpty()) { + root = stack.pop(); + if (root.val >= L && root.val <= R) + sum += root.val; + if (root.val > L && null != root.left) stack.push(root.left); + if (root.val < R && null != root.right) stack.push(root.right); + } + return sum; + } + +} diff --git a/Week_02/id_2/LeetCode_98_2.java b/Week_02/id_2/LeetCode_98_2.java new file mode 100644 index 00000000..a0bb3343 --- /dev/null +++ b/Week_02/id_2/LeetCode_98_2.java @@ -0,0 +1,99 @@ +//Given a binary tree, determine if it is a valid binary search tree (BST). +// +// Assume a BST is defined as follows: +// +// +// The left subtree of a node contains only nodes with keys less than the node's key. +// The right subtree of a node contains only nodes with keys greater than the node's key. +// Both the left and right subtrees must also be binary search trees. +// +// +// +// +// Example 1: +// +// +// 2 +// / \ +// 1 3 +// +//Input: [2,1,3] +//Output: true +// +// +// Example 2: +// +// +// 5 +// / \ +// 1 4 +//  / \ +//  3 6 +// +//Input: [5,1,4,null,null,3,6] +//Output: false +//Explanation: The root node's value is 5 but its right child's value is 4. +// +// + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ + +package com.llz.algorithm.algorithm2019.secondweek; + +import com.llz.algorithm.algorithm2019.firstweek.TreeNode; + +import java.util.ArrayList; +import java.util.List; + +public class LeetCode_98_2 { + + /** + * Hard to think, referenced from solution. + * @param root + * @return + */ + public boolean isValidBSTByTraverse(TreeNode root) { + return judgeValidBSt(root, null, null); + } + + public boolean judgeValidBSt(TreeNode cur, TreeNode lower, TreeNode upper) { + if (cur == null) return true; + if (lower != null && cur.val <= lower.val) return false; + if (upper != null && cur.val >= upper.val) return false; + if (!judgeValidBSt(cur.right, cur, upper)) return false; + if (!judgeValidBSt(cur.left, lower, cur)) return false; + return true; + } + + private List list = new ArrayList<>(); + + /** + * Use inOrder traverse, both of time complexity and space complexity is O(n). + * + * @param root + * @return + */ + public boolean isValidBST(TreeNode root) { + getListByInOrderTraverse(root); + for (int i = 1; i < list.size(); i++) { + if (list.get(i) <= list.get(i - 1)) + return false; + } + return true; + } + + public void getListByInOrderTraverse(TreeNode root) { + if (root == null) return; + getListByInOrderTraverse(root.left); + list.add(root.val); + getListByInOrderTraverse(root.right); + } +} diff --git a/Week_02/id_2/SummaryAndReview.md b/Week_02/id_2/SummaryAndReview.md new file mode 100644 index 00000000..3b0bbc6d --- /dev/null +++ b/Week_02/id_2/SummaryAndReview.md @@ -0,0 +1,16 @@ +一周刷题感想 +比上周进步的地方:每道题多写了不同的解法,给出空间复杂度和时间复杂度。注意了代码的clean。 +3:滑动窗口没做过类似题型,直接看答案 +比较tricky的地方在于使用滑动窗口的优化版本解法,判断指针starter初始值i = Math.max(map.get(c) + 1, i);,为什么不直接是i=map.get(c)+1,这个很难想到, +只有在你遇到了tmmzuxt的test case,才会恍然大悟。 +98:非常容易想到通过In Order Traverse获取整个BST的节点值list,再判断该list是否有序即可。题解中有只用traverse的方法获得答案,关键是要想到增加upper,lower这几个变量,并且在遍历过程中想到如何更新lower和upper。这个方法速度是最快的。 +692:topk问题立马想到堆,很快实现出来,看了下解答用了java jdk8的内容用函数式编程的方式节省了相当多的代码。值得学习。 +101:第二次做,用了两种解法,基本树的题目都是那个套路,要么递归要么迭代。这个巧的地方,在于需要想到用两个root(其中一个是mirror node)。 +102:bfs做lever order基本都想得到,看到解法中有dfs,通过指定height这种想法挺有意思的。 +103:和102不一样在于遍历完一层要反过来,我自己的解法不是很好用了两个queue,解法只用了一个queue,思路比我清晰,想到了利用list.add(0,value)这个方法,不需要改变queue的存储数据的方式。 +111:用了5种方法,不停地重构,写出更优的代码。 +235:比较简单,利用bst特性,traverse要好写很多。 +236:第二次做,用递归方法仍然需要参考discussion,用迭代很快写出来了。所以得反复练习。递归要想到left,mid,right这样去遍历判断节点是否存在真的挺难的。我觉得有返回值的遍历都比没有返回值的难。 +783:递归想到用个pre存放上一个值,比较的时候Math.min(root.val-pre.val, minDist)有点难想到。 +983:比较简单。 +下周改进的地方:争取刷更多的题,然后争取在deadline前留下更宽裕的时间。另外做算法题一定要focus,focus,focus,提升效率。 diff --git a/Week_02/id_22/LeetCode_111_022.js b/Week_02/id_22/LeetCode_111_022.js new file mode 100644 index 00000000..8d9521e1 --- /dev/null +++ b/Week_02/id_22/LeetCode_111_022.js @@ -0,0 +1,36 @@ +/* + * @lc app=leetcode.cn id=111 lang=javascript + * + * [111] 二叉树的最小深度 + */ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ +var minDepth = function (root) { + if (root == null) { + return 0; + } + + if ((root.left == null) && (root.right == null)) { + return 1; + } + + let min_depth = Infinity; + if (root.left != null) { + min_depth = Math.min(minDepth(root.left), min_depth); + } + if (root.right != null) { + min_depth = Math.min(minDepth(root.right), min_depth); + } + + return min_depth + 1; +}; + diff --git a/Week_02/id_22/LeetCode_1_022.js b/Week_02/id_22/LeetCode_1_022.js new file mode 100644 index 00000000..229face3 --- /dev/null +++ b/Week_02/id_22/LeetCode_1_022.js @@ -0,0 +1,21 @@ +/* + * @lc app=leetcode.cn id=1 lang=javascript + * + * [1] 两数之和 + */ +/** + * @param {number[]} nums + * @param {number} target + * @return {number[]} + */ +var twoSum = function (nums, target) { + const map = {} + for (let i = 0; i < nums.length; i++) { + if (map[target - nums[i]] >= 0) { + return [map[target - nums[i]], i] + } + map[nums[i]] = i; + } +} + + diff --git a/Week_02/id_22/LeetCode_783_022.js b/Week_02/id_22/LeetCode_783_022.js new file mode 100644 index 00000000..6c78b67e --- /dev/null +++ b/Week_02/id_22/LeetCode_783_022.js @@ -0,0 +1,37 @@ +/* + * @lc app=leetcode.cn id=783 lang=javascript + * + * [783] 二叉搜索树结点最小距离 + */ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ +var minDiffInBST = function (root) { + let prev = null; + let min = Infinity; + + const inorder = curr => { + if (!curr) return; + + inorder(curr.left); + + if (prev) { + min = Math.min(min, Math.abs(curr.val - prev.val)); + } + prev = curr; + + inorder(curr.right); + }; + + inorder(root); + return min; +}; + diff --git a/Week_02/id_23/LeetCode_03_23.txt b/Week_02/id_23/LeetCode_03_23.txt new file mode 100644 index 00000000..619500d4 --- /dev/null +++ b/Week_02/id_23/LeetCode_03_23.txt @@ -0,0 +1,37 @@ +//给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。 +// +// 示例 1: +// +// 输入: "abcabcbb" +//输出: 3 +//解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 +// +// +// 示例 2: +// +// 输入: "bbbbb" +//输出: 1 +//解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。 +// +// +// 示例 3: +// +// 输入: "pwwkew" +//输出: 3 +//解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 +//请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。 +// +// +public class Solution { + public int lengthOfLongestSubstring(String s) { + int n = s.length(), ans = 0; + // current index of character + int[] index = new int[128]; + for (int j = 0, i = 0; j < n; j++) { + i = Math.max(index[s.charAt(j)], i); + ans = Math.max(ans, j - i + 1); + index[s.charAt(j)] = j + 1; + } + return ans; + } +} \ No newline at end of file diff --git a/Week_02/id_23/LeetCode_111_23.txt b/Week_02/id_23/LeetCode_111_23.txt new file mode 100644 index 00000000..6bfd65ab --- /dev/null +++ b/Week_02/id_23/LeetCode_111_23.txt @@ -0,0 +1,23 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +class Solution { + public int minDepth(TreeNode root) { + if (root == null) { + return 0; + } + if (root.left == null) { + return minDepth(root.right) + 1; + } + if (root.right == null) { + return minDepth(root.left) + 1; + } + return Math.min(minDepth(root.left), minDepth(root.right)) + 1; + } +} \ No newline at end of file diff --git a/Week_02/id_23/NOTE.md b/Week_02/id_23/NOTE.md index 107ea7d6..e1c7a336 100644 --- a/Week_02/id_23/NOTE.md +++ b/Week_02/id_23/NOTE.md @@ -1 +1,6 @@ -# 学习笔记 +# 学习笔记 +整数数组作为直接访问表来替换 Map,是大神一样的操作哇。 +int [26] 用于字母 ‘a’ - ‘z’ 或 ‘A’ - ‘Z’ +int [128] 用于ASCII码 +int [256] 用于扩展ASCII码 +以后关于char的题目可以都用这种思路去降维思考。 diff --git a/Week_02/id_24/LeetCode_1_024.py b/Week_02/id_24/LeetCode_1_024.py new file mode 100644 index 00000000..0fc2b325 --- /dev/null +++ b/Week_02/id_24/LeetCode_1_024.py @@ -0,0 +1,31 @@ +def twoSum(nums, target): + """ + :type nums: List[int] + :type target: int + :rtype: List[int] + """ + # s1 + # for i in range(len(nums) - 1): + # for j in range(i + 1, len(nums)): + # if nums[i] + nums[j] == target: + # return [i, j] + # return [] + + # s2 + # resHash = {} + # for i in range(len(nums)): + # resHash[target - nums[i]] = i + # for j in range(len(nums)): + # if (nums[j] in resHash and j != resHash[nums[j]]): + # return [j, resHash[nums[j]]] + # return [] + + # s3 + resHash = {} + for i in range(len(nums)): + if (nums[i] in resHash and i != resHash[nums[i]]): + return [resHash[nums[i]], i] + resHash[target - nums[i]] = i + return [] + +print(twoSum([3,2,4], 6)) \ No newline at end of file diff --git a/Week_02/id_24/LeetCode_242_024.py b/Week_02/id_24/LeetCode_242_024.py new file mode 100644 index 00000000..63b6c34b --- /dev/null +++ b/Week_02/id_24/LeetCode_242_024.py @@ -0,0 +1,32 @@ +def isAnagram(s, t): + # s1 + # return sorted(t) == sorted(s) + + # s2 + # if len(s) != len(t): + # return False + # setS = dict() + # setT = dict() + # for i in range(len(s)): + # if (s[i] in setS): + # setS[s[i]] = setS[s[i]] + 1 + # else: + # setS[s[i]] = 1 + # if (t[i] in setT): + # setT[t[i]] = setT[t[i]] + 1 + # else: + # setT[t[i]] = 1 + # return setS == setT + + # s3 + if len(s) != len(t): + return False + listS = [0] * 26 + listT = [0] * 26 + for i in range(len(s)): + listS[ord(s[i]) - ord('a')] += 1 + listT[ord(t[i]) - ord('a')] += 1 + return listS == listT + + +print(isAnagram("anagram", "nagaram")) \ No newline at end of file diff --git a/Week_02/id_24/LeetCode_3_024.py b/Week_02/id_24/LeetCode_3_024.py new file mode 100644 index 00000000..8084aa9a --- /dev/null +++ b/Week_02/id_24/LeetCode_3_024.py @@ -0,0 +1,23 @@ +def lengthOfLongestSubstring(s): + # s1 + # sub = {} + # sub_len = 0 + # for i in range(len(s)): + # if s[i] in sub: + # sub_len = max(sub_len, len(sub)) + # sub = {key : value for key, value in sub.items() if value > sub[s[i]]} + # sub[s[i]] = i + # return max(sub_len, len(sub)) + + # s2 + sub = {} + sub_len = 0 + mark = 0 + for i in range(len(s)): + if s[i] in s[mark:i]: + sub_len = max(sub_len, i - mark) + mark = sub[s[i]] + 1 + sub[s[i]] = i + return max(sub_len, len(s) - mark) + +print(lengthOfLongestSubstring("abcabcabghg")) diff --git a/Week_02/id_24/LeetCode_692_024.py b/Week_02/id_24/LeetCode_692_024.py new file mode 100644 index 00000000..2f49ae75 --- /dev/null +++ b/Week_02/id_24/LeetCode_692_024.py @@ -0,0 +1,13 @@ +def topKFrequent(words, k): + nums = {} + for i in range(len(words)): + if (words[i] in nums): + nums[words[i]] += 1 + else: + nums[words[i]] = 1 + sort_words = list(nums.keys()) + sort_words.sort() + sort_words.sort(key = lambda item: nums[item], reverse = True) + return sort_words[0:k] + +print(topKFrequent(["i", "love", "leetcode", "i", "love", "coding"], 3)) \ No newline at end of file diff --git a/Week_02/id_24/LeetCode_726_024.py b/Week_02/id_24/LeetCode_726_024.py new file mode 100644 index 00000000..348c56af --- /dev/null +++ b/Week_02/id_24/LeetCode_726_024.py @@ -0,0 +1,72 @@ +import re +from collections import deque + +def stuffSubStack(stack, sub_stack): + char = stack.pop() + while char != '(': + sub_stack.append(char) + char = stack.pop() + +def emptySubStack(stack, sub_stack): + while sub_stack: + stack.append(sub_stack.pop()) + +def enlargeSubStack(stack, sub_stack, multiple): + prev = '' + while sub_stack: + char = sub_stack.pop() + if re.match( r'\d', char): stack.append(str(int(char) * int(multiple))) + else: + if re.match( r'[A-Z]', char) and re.match( r'[a-zA-Z]', prev): stack.append(multiple) + stack.append(char) + if len(sub_stack) == 0 and re.match( r'[a-zA-Z]', char): stack.append(multiple) + prev = char + +def dealSubAndNum(stack, sub_stack, num_str): + if sub_stack and num_str: enlargeSubStack(stack, sub_stack, num_str) + elif sub_stack and not num_str: emptySubStack(stack, sub_stack) + elif not sub_stack and num_str: stack.append(num_str) + +def getAtomsNumHash(stack): + sub = '' + sub_hash = {} + while stack: + char = stack.popleft() + if re.match( r'\d', char): + sub_hash[sub] = int(char) + (sub_hash[sub] if sub in sub_hash else 0) + sub = '' + elif re.match( r'[A-Z]', char): + if (sub): sub_hash[sub] = 1 + sub = char + elif re.match( r'[a-z]', char): + sub += char + if sub: sub_hash[sub] = 1 + return sub_hash + +def getAtomsNumStr(sub_hash): + hash_str = '' + sorted_hash = sorted(sub_hash) + for i in range(len(sorted_hash)): + hash_str += sorted_hash[i] + hash_str += str(sub_hash[sorted_hash[i]]) if sub_hash[sorted_hash[i]] != 1 else '' + return hash_str + +def countOfAtoms(formula): + stack = deque() + sub_stack = [] + num_str = '' + for i in range(len(formula)): + if re.match( r'\(|\)', formula[i]): dealSubAndNum(stack, sub_stack, num_str) + if re.match( r'\)', formula[i]): stuffSubStack(stack, sub_stack) + elif re.match( r'[A-Z]', formula[i]) and num_str: + if sub_stack: enlargeSubStack(stack, sub_stack, num_str) + else: stack.append(num_str) + if not re.match( r'\)|\d', formula[i]): stack.append(formula[i]) + num_str = (num_str + formula[i]) if re.match( r'\d', formula[i]) else '' + + dealSubAndNum(stack, sub_stack, num_str) + + return getAtomsNumStr(getAtomsNumHash(stack)) + + +print(countOfAtoms("((N42)24(OB40Li30CHe3O48LiNN26)33(C12Li48N30H13HBe31)21(BHN30Li26BCBe47N40)15(H5)16)14")) \ No newline at end of file diff --git a/Week_02/id_24/NOTE.md b/Week_02/id_24/NOTE.md index 107ea7d6..302f2dd0 100644 --- a/Week_02/id_24/NOTE.md +++ b/Week_02/id_24/NOTE.md @@ -1 +1,9 @@ -# 学习笔记 +# 学习笔记:关于解 726 的一点心得体会 + +周四晚上在草稿纸上写出了 726 的思路,周五白天有事,晚上编码完成。编造了几个测试用例,执行成功后,直接提交,没想到失败了。“Be32” 是系统给出的失败测试用例,我看了这个用例才意识到,自己没有考虑到原子数量为多位数的情况,只是根据题目测试用例武断的认为,给出的 formula 中各原子分段出现的数量是个位数。 + +磕到周六晚上才把思路重新理清,加入多位数的判断,提交成功。周日对答案的主体方法进行了优化,没有改进算法,主要目的是防止一段时间后自己看不懂。 + +这个题目磕下来,暴露出自己的很多问题,大致有如下几点:解读题目不够深入,编造的测试用例覆盖面不够广,边界条件判断反复出现失误,编码能力弱写代码速度跟不上思路。 + +后期会针对上面的薄弱问题进行专项练习,希望自己的编码能力和算法能力提升后,可以回头来优化这道题的解法。 diff --git a/Week_02/id_25/LeetCode_24_025.java b/Week_02/id_25/LeetCode_24_025.java new file mode 100644 index 00000000..5359b243 --- /dev/null +++ b/Week_02/id_25/LeetCode_24_025.java @@ -0,0 +1,100 @@ +package com.mootal.algo.day8_24; + +/** + * Medium + * (注解文档查看快捷键 选中类名或方法名 按ctrl + Q) + *

+ * 思维全过程记录方案:

+ * 1 背基础结构和算法 | 记录在课程笔记

+ * 2 看题 -> 悟题 思考过程 | 记录在wiki

+ * 3 悟题 -> 写题 实现难点 | 记录在代码注解

+ * 4 写题 -> 优化 多种解法 | 记录在leetcode提交 + *

+ * 问题: + * Given a linked list, swap every two adjacent nodes and return its head. + * You may not modify the values in the list's nodes, only nodes itself may be changed. + * 1->2->3->4 | 2->1->4->3 + *

+ * 题解方案topics: + * linked list + * + * @author li tong + * @date 2019/6/10 9:41 + * @see Object + * @since 1.0 + */ +public class LeetCode_24_025 { + + private static class ListNode { + int val; + + ListNode next; + + ListNode(int x) { + val = x; + } + + @Override + public String toString() { + return "{" + val + + ", next=" + next + + '}'; + } + } + + public static void main(String[] args) { + ListNode a = new ListNode(1); + ListNode b = new ListNode(2); + ListNode c = new ListNode(3); + ListNode d = new ListNode(4); + a.next = b; + b.next = c; + c.next = d; + System.out.println(swapPairs(a)); + } + + /** + * 解法1 递归法

+ * + * @param head + * @return + */ + public static ListNode swapPairs(ListNode head) { + if (head == null || head.next == null) { + return head; + } + ListNode after = head.next; + ListNode nextTwo = after.next; + ListNode back = swapPairs(nextTwo); + head.next = back; + after.next = head; + return after; + } + + /** + * 解法2 遍历法

+ * + * @param head + * @return + */ + public static ListNode swapPairs2(ListNode head) { + if (head == null || head.next == null) { + return head; + } + ListNode newHead = new ListNode(0); + newHead.next = head; + ListNode temp = newHead; + ListNode one = null; + ListNode two = null; + while (temp.next != null && temp.next.next != null) { + one = temp.next; + two = temp.next.next; + one.next = two.next; + two.next = one; + temp.next = two; + temp = one; + } + return newHead.next; + } + +} diff --git a/Week_02/id_25/LeetCode_72_025.java b/Week_02/id_25/LeetCode_72_025.java new file mode 100644 index 00000000..2b76ee9a --- /dev/null +++ b/Week_02/id_25/LeetCode_72_025.java @@ -0,0 +1,123 @@ +package com.mootal.algo.day9_72; + +/** + * Hard + * (注解文档查看快捷键 选中类名或方法名 按ctrl + Q) + *

+ * 思维全过程记录方案:

+ * 1 背基础结构和算法 | 记录在课程笔记

+ * 2 看题 -> 悟题 思考过程 | 记录在wiki

+ * 3 悟题 -> 写题 实现难点 | 记录在代码注解

+ * 4 写题 -> 优化 多种解法 | 记录在leetcode提交 + *

+ * 问题: + * Given two words word1 and word2, + * find the minimum number of operations required to convert word1 to word2. + *

+ * 题解方案topics: + * string、dp + * + * @author li tong + * @date 2019/6/11 10:06 + * @see Object + * @since 1.0 + */ +public class LeetCode_72_025 { + + public static void main(String[] args) { + String word1 = "rose", word2 = "horse"; + System.out.println(minDistance(word1, word2)); + System.out.println(minDistanceDP(word1, word2)); + } + + /** + * 递归解法

+ * + * @param word1 + * @param word2 + * @return + */ + public static int minDistance(String word1, String word2) { + char[] w1 = word1.toCharArray(); + char[] w2 = word2.toCharArray(); + int l1 = w1.length, l2 = w2.length; + int[][] mem = new int[l1][l2]; + return helpWithMem(0, w1, 0, w2, mem); + } + + private static int help(int i, char[] w1, int j, char[] w2, int[][] mem) { + int insertCnt, deleteCnt, replaceCnt; + if (i == w1.length) { + return w2.length - j; + } + if (j == w2.length) { + return w1.length - i; + } + int res = 0; + if (w1[i] == w2[j]) { + res = help(i + 1, w1, j + 1, w2, mem); + return res; + } else { + deleteCnt = help(i + 1, w1, j, w2, mem); + insertCnt = help(i, w1, j + 1, w2, mem); + replaceCnt = help(i + 1, w1, j + 1, w2, mem); + res = Math.min(insertCnt, Math.min(deleteCnt, replaceCnt)) + 1; + } + return res; + } + + private static int helpWithMem(int i, char[] w1, int j, char[] w2, int[][] mem) { + int insertCnt, deleteCnt, replaceCnt; + if (i == w1.length) { + return w2.length - j; + } + if (j == w2.length) { + return w1.length - i; + } + if (mem[i][j] > 0) { + return mem[i][j]; + } + int res = 0; + if (w1[i] == w2[j]) { + res = helpWithMem(i + 1, w1, j + 1, w2, mem); + return res; + } else { + deleteCnt = helpWithMem(i + 1, w1, j, w2, mem); + insertCnt = helpWithMem(i, w1, j + 1, w2, mem); + replaceCnt = helpWithMem(i + 1, w1, j + 1, w2, mem); + mem[i][j] = Math.min(insertCnt, Math.min(deleteCnt, replaceCnt)) + 1; + } + return mem[i][j]; + } + + /** + * DP解法

+ * + * @param word1 + * @param word2 + * @return + */ + public static int minDistanceDP(String word1, String word2) { + char[] w1 = word1.toCharArray(); + char[] w2 = word2.toCharArray(); + int l1 = w1.length, l2 = w2.length; + int[][] dp = new int[l1 + 1][l2 + 1]; + for (int i = 0; i <= l1; ++i) { + dp[i][0] = i; + } + for (int i = 0; i <= l2; ++i) { + dp[0][i] = i; + } + for (int i = 1; i <= l1; ++i) { + for (int j = 1; j <= l2; ++j) { + if (w1[i - 1] == w2[j - 1]) { + dp[i][j] = dp[i - 1][j - 1]; + } else { + dp[i][j] = Math.min(dp[i - 1][j - 1], Math.min(dp[i - 1][j], dp[i][j - 1])) + 1; + } + } + } + return dp[l1][l2]; + } + +} diff --git a/Week_02/id_26/LeetCode_101_26.py b/Week_02/id_26/LeetCode_101_26.py new file mode 100644 index 00000000..821c749b --- /dev/null +++ b/Week_02/id_26/LeetCode_101_26.py @@ -0,0 +1,66 @@ +# +# @lc app=leetcode.cn id=101 lang=python +# +# [101] 对称二叉树 +# +# https://leetcode-cn.com/problems/symmetric-tree/description/ +# +# algorithms +# Easy (46.65%) +# Likes: 351 +# Dislikes: 0 +# Total Accepted: 34.7K +# Total Submissions: 74.4K +# Testcase Example: '[1,2,2,3,4,4,3]' +# +# 给定一个二叉树,检查它是否是镜像对称的。 +# +# 例如,二叉树 [1,2,2,3,4,4,3] 是对称的。 +# +# ⁠ 1 +# ⁠ / \ +# ⁠ 2 2 +# ⁠/ \ / \ +# 3 4 4 3 +# +# +# 但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的: +# +# ⁠ 1 +# ⁠ / \ +# ⁠ 2 2 +# ⁠ \ \ +# ⁠ 3 3 +# +# +# 说明: +# +# 如果你可以运用递归和迭代两种方法解决这个问题,会很加分。 +# +# +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + + +class Solution(object): + def isSymmetric(self, root): + """ + :type root: TreeNode + :rtype: bool + """ + + def _isSymmetric(node1, node2): + if not node1 and not node2: + return True + if not node1 or not node2: + return False + if node1.val != node2.val: + return False + return _isSymmetric(node1.left, node2.right) and _isSymmetric( + node1.right, node2.left) + + return _isSymmetric(root, root) diff --git a/Week_02/id_26/LeetCode_102_26.py b/Week_02/id_26/LeetCode_102_26.py new file mode 100644 index 00000000..76655d91 --- /dev/null +++ b/Week_02/id_26/LeetCode_102_26.py @@ -0,0 +1,65 @@ +# +# @lc app=leetcode.cn id=102 lang=python +# +# [102] 二叉树的层次遍历 +# +# https://leetcode-cn.com/problems/binary-tree-level-order-traversal/description/ +# +# algorithms +# Medium (56.47%) +# Likes: 213 +# Dislikes: 0 +# Total Accepted: 28.4K +# Total Submissions: 50.2K +# Testcase Example: '[3,9,20,null,null,15,7]' +# +# 给定一个二叉树,返回其按层次遍历的节点值。 (即逐层地,从左到右访问所有节点)。 +# +# 例如: +# 给定二叉树: [3,9,20,null,null,15,7], +# +# ⁠ 3 +# ⁠ / \ +# ⁠ 9 20 +# ⁠ / \ +# ⁠ 15 7 +# +# +# 返回其层次遍历结果: +# +# [ +# ⁠ [3], +# ⁠ [9,20], +# ⁠ [15,7] +# ] +# +# +# +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + + +class Solution(object): + def levelOrder(self, root): + """ + :type root: TreeNode + :rtype: List[List[int]] + """ + if not root: + return [] + ret, layer = [], [root] + while layer: + tmp_layer, line = [], [] + for i in layer: + line.append(i.val) + if i.left: + tmp_layer.append(i.left) + if i.right: + tmp_layer.append(i.right) + layer = tmp_layer + ret.append(line) + return ret diff --git a/Week_02/id_26/LeetCode_103_26.py b/Week_02/id_26/LeetCode_103_26.py new file mode 100644 index 00000000..d567c83f --- /dev/null +++ b/Week_02/id_26/LeetCode_103_26.py @@ -0,0 +1,68 @@ +# +# @lc app=leetcode.cn id=103 lang=python +# +# [103] 二叉树的锯齿形层次遍历 +# +# https://leetcode-cn.com/problems/binary-tree-zigzag-level-order-traversal/description/ +# +# algorithms +# Medium (49.74%) +# Likes: 64 +# Dislikes: 0 +# Total Accepted: 11.7K +# Total Submissions: 23.5K +# Testcase Example: '[3,9,20,null,null,15,7]' +# +# 给定一个二叉树,返回其节点值的锯齿形层次遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。 +# +# 例如: +# 给定二叉树 [3,9,20,null,null,15,7], +# +# ⁠ 3 +# ⁠ / \ +# ⁠ 9 20 +# ⁠ / \ +# ⁠ 15 7 +# +# +# 返回锯齿形层次遍历如下: +# +# [ +# ⁠ [3], +# ⁠ [20,9], +# ⁠ [15,7] +# ] +# +# +# +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + + +class Solution(object): + def zigzagLevelOrder(self, root): + """ + 思路:层序遍历,每隔一层换一个方向遍历 + :type root: TreeNode + :rtype: List[List[int]] + """ + if not root: + return [] + line, ret, rot = [root], [], 1 + while line: + tmp1, tmp2 = [], [] + for i in line: + if i.left: + tmp1.append(i.left) + if i.right: + tmp1.append(i.right) + for j in line[::rot]: + tmp2.append(j.val) + ret.append(tmp2) + line = tmp1 + rot *= -1 + return ret diff --git a/Week_02/id_26/LeetCode_111_26.py b/Week_02/id_26/LeetCode_111_26.py new file mode 100644 index 00000000..396edc39 --- /dev/null +++ b/Week_02/id_26/LeetCode_111_26.py @@ -0,0 +1,55 @@ +# +# @lc app=leetcode.cn id=111 lang=python +# +# [111] 二叉树的最小深度 +# +# https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/description/ +# +# algorithms +# Easy (38.70%) +# Likes: 125 +# Dislikes: 0 +# Total Accepted: 19K +# Total Submissions: 49K +# Testcase Example: '[3,9,20,null,null,15,7]' +# +# 给定一个二叉树,找出其最小深度。 +# +# 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 +# +# 说明: 叶子节点是指没有子节点的节点。 +# +# 示例: +# +# 给定二叉树 [3,9,20,null,null,15,7], +# +# ⁠ 3 +# ⁠ / \ +# ⁠ 9 20 +# ⁠ / \ +# ⁠ 15 7 +# +# 返回它的最小深度  2. +# +# +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + + +class Solution(object): + def minDepth(self, root): + """ + :type root: TreeNode + :rtype: int + """ + if not root: + return 0 + left = self.minDepth(root.left) + right = self.minDepth(root.right) + if not left or not right: + return 1 + left + right + return 1 + min(left, right) diff --git a/Week_02/id_26/LeetCode_1_26.py b/Week_02/id_26/LeetCode_1_26.py new file mode 100644 index 00000000..7a0033a4 --- /dev/null +++ b/Week_02/id_26/LeetCode_1_26.py @@ -0,0 +1,43 @@ +# +# @lc app=leetcode.cn id=1 lang=python +# +# [1] 两数之和 +# +# https://leetcode-cn.com/problems/two-sum/description/ +# +# algorithms +# Easy (46.10%) +# Likes: 5365 +# Dislikes: 0 +# Total Accepted: 397.2K +# Total Submissions: 861.4K +# Testcase Example: '[2,7,11,15]\n9' +# +# 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 +# +# 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 +# +# 示例: +# +# 给定 nums = [2, 7, 11, 15], target = 9 +# +# 因为 nums[0] + nums[1] = 2 + 7 = 9 +# 所以返回 [0, 1] +# +# +# + + +class Solution(object): + def twoSum(self, nums, target): + """ + :type nums: List[int] + :type target: int + :rtype: List[int] + """ + s = {} + for i in range(len(nums)): + tmp = target - nums[i] + if tmp in s: + return [s[tmp], i] + s[nums[i]] = i diff --git a/Week_02/id_26/LeetCode_220_26.py b/Week_02/id_26/LeetCode_220_26.py new file mode 100644 index 00000000..9065a0fc --- /dev/null +++ b/Week_02/id_26/LeetCode_220_26.py @@ -0,0 +1,117 @@ +# +# @lc app=leetcode.cn id=220 lang=python +# +# [220] 存在重复元素 III +# +# https://leetcode-cn.com/problems/contains-duplicate-iii/description/ +# +# algorithms +# Medium (24.08%) +# Likes: 63 +# Dislikes: 0 +# Total Accepted: 5.1K +# Total Submissions: 20.9K +# Testcase Example: '[1,2,3,1]\n3\n0' +# +# 给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j +# 之间的差的绝对值最大为 ķ。 +# +# 示例 1: +# +# 输入: nums = [1,2,3,1], k = 3, t = 0 +# 输出: true +# +# 示例 2: +# +# 输入: nums = [1,0,1,1], k = 1, t = 2 +# 输出: true +# +# 示例 3: +# +# 输入: nums = [1,5,9,1,5,9], k = 2, t = 3 +# 输出: false +# +# + + +class Solution(object): + def containsNearbyAlmostDuplicate(self, nums, k, t): + """ + :type nums: List[int] + :type k: int + :type t: int + :rtype: bool + 解法1:暴力求解,复杂度O(n*k),容易超时,最后一个用例过不了。面向用例编程 - -。真的香 + """ + if not nums: + return False + n = len(nums) + wins = set() + for i in range(n): + if t == 0: + if nums[i] in wins: + return True + else: + for v in wins: + if abs(nums[i] - v) <= t: + return True + wins.add(nums[i]) + if len(wins) == k + 1: + wins.remove(nums[i - k]) + return False + + def containsNearbyAlmostDuplicate2(self, nums, k, t): + """ + :type nums: List[int] + :type k: int + :type t: int + :rtype: bool + 解法2:来自https://leetcode.com/problems/contains-duplicate-iii/discuss/61756/Python-OrderedDict + 证明=》 + 如果: | nums[i] - nums[j] | <= t 式a + 等价: | nums[i] / t - nums[j] / t | <= 1 式b + 推出: | floor(nums[i] / t) - floor(nums[j] / t) | <= 1 式c + ​等价: floor(nums[j] / t) ∈ {floor(nums[i] / t) - 1, floor(nums[i] / t), floor(nums[i] / t) + 1} 式d + 其中式b是式c的充分非必要条件,因为逆否命题与原命题等价,所以: + 如果: floor(nums[j] / t) ∉ {floor(nums[i] / t) - 1, floor(nums[i] / t), floor(nums[i] / t) + 1} 非d + 推出: | nums[i] - nums[j] | > t 非a + """ + import collections + if k < 1 or t < 0: + return False + dic = collections.OrderedDict() + for n in nums: + key = n if not t else n // t + for m in (dic.get(key - 1), dic.get(key), dic.get(key + 1)): + if m is not None and abs(n - m) <= t: + return True + if len(dic) == k: + dic.popitem(False) + dic[key] = n + return False + + + def containsNearbyAlmostDuplicate3(self, nums, k, t): + if t < 0: + return False + cache = {} + for i in range(len(nums)): + if i - k > 0: + bucket_id_to_delete = nums[i - k - 1] // (t + 1) + del cache[bucket_id_to_delete] + bucket_id = nums[i] // (t + 1) + condition1 = (bucket_id in cache) + condition2 = ((bucket_id - 1 in cache + and abs(cache[bucket_id - 1] - nums[i]) <= t)) + condition3 = ((bucket_id + 1 in cache + and abs(cache[bucket_id + 1] - nums[i]) <= t)) + if condition1 or condition2 or condition3: + return True + cache[bucket_id] = nums[i] + return False + + +# print(Solution().containsNearbyAlmostDuplicate([1, 2, 3, 1], 3, 0)) +# print(Solution().containsNearbyAlmostDuplicate([1, 0, 1, 1], 1, 2)) +# print(Solution().containsNearbyAlmostDuplicate([1, 5, 9, 1, 5, 9], 2, 3)) +# print(Solution().containsNearbyAlmostDuplicate([2, 2], 3, 0)) diff --git a/Week_02/id_26/LeetCode_235_26.py b/Week_02/id_26/LeetCode_235_26.py new file mode 100644 index 00000000..af7b31be --- /dev/null +++ b/Week_02/id_26/LeetCode_235_26.py @@ -0,0 +1,89 @@ +# +# @lc app=leetcode.cn id=235 lang=python +# +# [235] 二叉搜索树的最近公共祖先 +# +# https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree/description/ +# +# algorithms +# Easy (59.44%) +# Likes: 122 +# Dislikes: 0 +# Total Accepted: 15.7K +# Total Submissions: 26.3K +# Testcase Example: '[6,2,8,0,4,7,9,null,null,3,5]\n2\n8' +# +# 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 +# +# 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x +# 的深度尽可能大(一个节点也可以是它自己的祖先)。” +# +# 例如,给定如下二叉搜索树:  root = [6,2,8,0,4,7,9,null,null,3,5] +# +# +# +# +# +# 示例 1: +# +# 输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 +# 输出: 6 +# 解释: 节点 2 和节点 8 的最近公共祖先是 6。 +# +# +# 示例 2: +# +# 输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 +# 输出: 2 +# 解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。 +# +# +# +# 说明: +# +# +# 所有节点的值都是唯一的。 +# p、q 为不同节点且均存在于给定的二叉搜索树中。 +# +# +# +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + + +class Solution(object): + def lowestCommonAncestor1(self, root, p, q): + """ + :type root: TreeNode + :type p: TreeNode + :type q: TreeNode + :rtype: TreeNode + 解法1:和二叉树的解法一样 + """ + if not root or root == q or root == p: + return root + left = self.lowestCommonAncestor(root.left, p, q) + right = self.lowestCommonAncestor(root.right, p, q) + if not left: + return right + if not right: + return left + return root + + def lowestCommonAncestor(self, root, p, q): + """ + :type root: TreeNode + :type p: TreeNode + :type q: TreeNode + :rtype: TreeNode + 解法2:利用二叉搜索树的特性 + """ + if p.val < root.val > q.val: + return self.lowestCommonAncestor(root.left, p, q) + if p.val > root.val < q.val: + return self.lowestCommonAncestor(root.right, p, q) + return root diff --git a/Week_02/id_26/LeetCode_236_26.py b/Week_02/id_26/LeetCode_236_26.py new file mode 100644 index 00000000..6cd059c5 --- /dev/null +++ b/Week_02/id_26/LeetCode_236_26.py @@ -0,0 +1,75 @@ +# +# @lc app=leetcode.cn id=236 lang=python +# +# [236] 二叉树的最近公共祖先 +# +# https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/description/ +# +# algorithms +# Medium (54.67%) +# Likes: 180 +# Dislikes: 0 +# Total Accepted: 14.4K +# Total Submissions: 26.4K +# Testcase Example: '[3,5,1,6,2,0,8,null,null,7,4]\n5\n1' +# +# 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 +# +# 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x +# 的深度尽可能大(一个节点也可以是它自己的祖先)。” +# +# 例如,给定如下二叉树:  root = [3,5,1,6,2,0,8,null,null,7,4] +# +# +# +# +# +# 示例 1: +# +# 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 +# 输出: 3 +# 解释: 节点 5 和节点 1 的最近公共祖先是节点 3。 +# +# +# 示例 2: +# +# 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 +# 输出: 5 +# 解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。 +# +# +# +# +# 说明: +# +# +# 所有节点的值都是唯一的。 +# p、q 为不同节点且均存在于给定的二叉树中。 +# +# +# +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + + +class Solution(object): + def lowestCommonAncestor(self, root, p, q): + """ + :type root: TreeNode + :type p: TreeNode + :type q: TreeNode + :rtype: TreeNode + """ + if not root or root == q or root == p: + return root + left = self.lowestCommonAncestor(root.left, p, q) + right = self.lowestCommonAncestor(root.right, p, q) + if not left: + return right + if not right: + return left + return root diff --git a/Week_02/id_26/LeetCode_242_26.py b/Week_02/id_26/LeetCode_242_26.py new file mode 100644 index 00000000..27a1942c --- /dev/null +++ b/Week_02/id_26/LeetCode_242_26.py @@ -0,0 +1,74 @@ +# +# @lc app=leetcode.cn id=242 lang=python +# +# [242] 有效的字母异位词 +# +# https://leetcode-cn.com/problems/valid-anagram/description/ +# +# algorithms +# Easy (53.28%) +# Likes: 82 +# Dislikes: 0 +# Total Accepted: 32.3K +# Total Submissions: 60.6K +# Testcase Example: '"anagram"\n"nagaram"' +# +# 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 +# +# 示例 1: +# +# 输入: s = "anagram", t = "nagaram" +# 输出: true +# +# +# 示例 2: +# +# 输入: s = "rat", t = "car" +# 输出: false +# +# 说明: +# 你可以假设字符串只包含小写字母。 +# +# 进阶: +# 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况? +# +# + + +class Solution(object): + """ + 解法1:排序比较 + 解法2:清点字母数量 + """ + def isAnagram1(self, s, t): + """ + :type s: str + :type t: str + :rtype: bool + """ + return sorted(s) == sorted(t) + + def isAnagram2(self, s, t): + """ + :type s: str + :type t: str + :rtype: bool + """ + if len(s) != len(t): + return False + map = {} + for i in s: + if i not in map: + map[i] = 0 + map[i] += 1 + for i in t: + if i not in map: + return False + map[i] -= 1 + if map[i] < 0: + return False + for i in map: + if map[i] != 0: + return False + return True + diff --git a/Week_02/id_26/LeetCode_297_26.py b/Week_02/id_26/LeetCode_297_26.py new file mode 100644 index 00000000..166bc74a --- /dev/null +++ b/Week_02/id_26/LeetCode_297_26.py @@ -0,0 +1,108 @@ +# +# @lc app=leetcode.cn id=297 lang=python +# +# [297] 二叉树的序列化与反序列化 +# +# https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree/description/ +# +# algorithms +# Hard (39.27%) +# Likes: 49 +# Dislikes: 0 +# Total Accepted: 4.7K +# Total Submissions: 12K +# Testcase Example: '[1,2,3,null,null,4,5]' +# +# +# 序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。 +# +# 请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / +# 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。 +# +# 示例: +# +# 你可以将以下二叉树: +# +# ⁠ 1 +# ⁠ / \ +# ⁠ 2 3 +# ⁠ / \ +# ⁠ 4 5 +# +# 序列化为 "[1,2,3,null,null,4,5]" +# +# 提示: 这与 LeetCode 目前使用的方式一致,详情请参阅 LeetCode +# 序列化二叉树的格式。你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。 +# +# 说明: 不要使用类的成员 / 全局 / 静态变量来存储状态,你的序列化和反序列化算法应该是无状态的。 +# +# +# Definition for a binary tree node. + + +class TreeNode(object): + def __init__(self, x): + self.val = x + self.left = None + self.right = None + + +class Codec: + def serialize(self, root): + """Encodes a tree to a single string. + + :type root: TreeNode + :rtype: str + """ + if not root: + return '' + line, ret = [root], [str(root.val)] + while line: + next_line = [] + for node in line: + if not node.left: + ret.append('') + else: + next_line.append(node.left) + ret.append(str(node.left.val)) + if not node.right: + ret.append('') + else: + next_line.append(node.right) + ret.append(str(node.right.val)) + line = next_line + return ','.join(ret) + + def deserialize(self, data): + """Decodes your encoded data to tree. + + :type data: str + :rtype: TreeNode + """ + if not data: + return None + data = data.split(',')[::-1] + root = TreeNode(int(data.pop())) + line = [root] + while line and data: + next_line = [] + for node in line: + left, right = data.pop(), data.pop() + if left != '': + node.left = TreeNode(int(left)) + next_line.append(node.left) + if right != '': + node.right = TreeNode(int(right)) + next_line.append(node.right) + line = next_line + return root + + +# Your Codec object will be instantiated and called as such: +# codec = Codec() +# codec.deserialize('1') +# tmp = codec.deserialize('1,2,3,,,4,5') +# tmp = codec.serialize(tmp) +# print(tmp) + +# codec.deserialize(codec.serialize(root)) diff --git a/Week_02/id_26/LeetCode_315_26.py b/Week_02/id_26/LeetCode_315_26.py new file mode 100644 index 00000000..14ec5a97 --- /dev/null +++ b/Week_02/id_26/LeetCode_315_26.py @@ -0,0 +1,90 @@ +# +# @lc app=leetcode.cn id=315 lang=python +# +# [315] 计算右侧小于当前元素的个数 +# +# https://leetcode-cn.com/problems/count-of-smaller-numbers-after-self/description/ +# +# algorithms +# Hard (37.52%) +# Likes: 63 +# Dislikes: 0 +# Total Accepted: 2.9K +# Total Submissions: 7.8K +# Testcase Example: '[5,2,6,1]' +# +# 给定一个整数数组 nums,按要求返回一个新数组 counts。数组 counts 有该性质: counts[i] 的值是  nums[i] 右侧小于 +# nums[i] 的元素的数量。 +# +# 示例: +# +# 输入: [5,2,6,1] +# 输出: [2,1,1,0] +# 解释: +# 5 的右侧有 2 个更小的元素 (2 和 1). +# 2 的右侧仅有 1 个更小的元素 (1). +# 6 的右侧有 1 个更小的元素 (1). +# 1 的右侧有 0 个更小的元素. +# +# +# 思路: 构建一个二叉搜索树,左子树小于等于根节点,右子树大于根节点 +# 节点内记录下标,所有左节点的个数,以及右侧小于该节点的总数 +# 若插入节点小于等于当前节点,则当前节点的左节点总数+1 +# 若插入节点大于当前节点,则当前节点的右侧小于该节点的总数=当前节点的左节点总数+1(当前节点) +# 最后深度遍历 + + +class BST(object): + def __init__(self, index, val): + self.left = None + self.right = None + self.index = index + self.val = val + # 右侧小于该节点的总数 + self.count = 0 + # 左子树总数 + self.left_count = 0 + + def insert(self, node): + if node.val <= self.val: + self.left_count += 1 + if not self.left: + self.left = node + else: + self.left.insert(node) + else: + node.count += self.left_count + 1 + if not self.right: + self.right = node + else: + self.right.insert(node) + + +class Solution(object): + def countSmaller(self, nums): + """ + :type nums: List[int] + :rtype: List[int] + """ + if not nums: + return [] + nums = nums[::-1] + root = BST(0, nums[0]) + for i in range(1, len(nums)): + root.insert(BST(i, nums[i])) + ret = [0] * len(nums) + + def _dfs(root): + if not root: + return ret + ret[root.index] = root.count + _dfs(root.left) + _dfs(root.right) + return ret + + return _dfs(root)[::-1] + + +# print(Solution().countSmaller([5, 2, 6, 1])) +# print(Solution().countSmaller([1, 2, 7, 8, 5])) +# print(Solution().countSmaller([-1, -1])) diff --git a/Week_02/id_26/LeetCode_3_26.py b/Week_02/id_26/LeetCode_3_26.py new file mode 100644 index 00000000..acde72eb --- /dev/null +++ b/Week_02/id_26/LeetCode_3_26.py @@ -0,0 +1,65 @@ +# +# @lc app=leetcode.cn id=3 lang=python +# +# [3] 无重复字符的最长子串 +# +# https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/description/ +# +# algorithms +# Medium (29.78%) +# Likes: 1897 +# Dislikes: 0 +# Total Accepted: 135.1K +# Total Submissions: 453.3K +# Testcase Example: '"abcabcbb"' +# +# 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。 +# +# 示例 1: +# +# 输入: "abcabcbb" +# 输出: 3 +# 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 +# +# +# 示例 2: +# +# 输入: "bbbbb" +# 输出: 1 +# 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。 +# +# +# 示例 3: +# +# 输入: "pwwkew" +# 输出: 3 +# 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 +# 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。 +# +# +# + + +class Solution(object): + def lengthOfLongestSubstring(self, s): + """ + :type s: str + :rtype: int + """ + map = {} + j = 0 + ret = 0 + for i in range(len(s)): + if s[i] in map: + j = max(map[s[i]], j) + ret = max(ret, i - j + 1) + map[s[i]] = i + 1 + return ret + + +print(Solution().lengthOfLongestSubstring('abcabcbb')) +print(Solution().lengthOfLongestSubstring('pwwkew')) +print(Solution().lengthOfLongestSubstring('bbbbb')) +print(Solution().lengthOfLongestSubstring(' ')) +print(Solution().lengthOfLongestSubstring('dvdf')) +print(Solution().lengthOfLongestSubstring('abba')) diff --git a/Week_02/id_26/LeetCode_692_26.py b/Week_02/id_26/LeetCode_692_26.py new file mode 100644 index 00000000..e8c36211 --- /dev/null +++ b/Week_02/id_26/LeetCode_692_26.py @@ -0,0 +1,77 @@ +# +# @lc app=leetcode.cn id=692 lang=python +# +# [692] 前K个高频单词 +# +# https://leetcode-cn.com/problems/top-k-frequent-words/description/ +# +# algorithms +# Medium (39.56%) +# Likes: 37 +# Dislikes: 0 +# Total Accepted: 2K +# Total Submissions: 5.1K +# Testcase Example: '["i", "love", "leetcode", "i", "love", "coding"]\n2' +# +# 给一非空的单词列表,返回前 k 个出现次数最多的单词。 +# +# 返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率,按字母顺序排序。 +# +# 示例 1: +# +# +# 输入: ["i", "love", "leetcode", "i", "love", "coding"], k = 2 +# 输出: ["i", "love"] +# 解析: "i" 和 "love" 为出现次数最多的两个单词,均为2次。 +# ⁠ 注意,按字母顺序 "i" 在 "love" 之前。 +# +# +# +# +# 示例 2: +# +# +# 输入: ["the", "day", "is", "sunny", "the", "the", "the", "sunny", "is", "is"], +# k = 4 +# 输出: ["the", "is", "sunny", "day"] +# 解析: "the", "is", "sunny" 和 "day" 是出现次数最多的四个单词, +# ⁠ 出现次数依次为 4, 3, 2 和 1 次。 +# +# +# +# +# 注意: +# +# +# 假定 k 总为有效值, 1 ≤ k ≤ 集合元素数。 +# 输入的单词均由小写字母组成。 +# +# +# +# +# 扩展练习: +# +# +# 尝试以 O(n log k) 时间复杂度和 O(n) 空间复杂度解决。 +# +# +# + + +class Solution(object): + def topKFrequent(self, words, k): + """ + :type words: List[str] + :type k: int + :rtype: List[str] + """ + map = {} + for i in words: + map[i] = map.get(i, 0) + 1 + ret = sorted(map, key=lambda word: (-map[word], word)) + return ret[:k] + + +# print(Solution().topKFrequent( +# ["the", "day", "is", "sunny", "the", "the", "the", "sunny", "is", "is"], +# 2)) diff --git a/Week_02/id_26/LeetCode_783_26.py b/Week_02/id_26/LeetCode_783_26.py new file mode 100644 index 00000000..e78c1f14 --- /dev/null +++ b/Week_02/id_26/LeetCode_783_26.py @@ -0,0 +1,72 @@ +# +# @lc app=leetcode.cn id=783 lang=python +# +# [783] 二叉搜索树结点最小距离 +# +# https://leetcode-cn.com/problems/minimum-distance-between-bst-nodes/description/ +# +# algorithms +# Easy (51.59%) +# Likes: 24 +# Dislikes: 0 +# Total Accepted: 3.2K +# Total Submissions: 6.2K +# Testcase Example: '[4,2,6,1,3,null,null]' +# +# 给定一个二叉搜索树的根结点 root, 返回树中任意两节点的差的最小值。 +# +# 示例: +# +# +# 输入: root = [4,2,6,1,3,null,null] +# 输出: 1 +# 解释: +# 注意,root是树结点对象(TreeNode object),而不是数组。 +# +# 给定的树 [4,2,6,1,3,null,null] 可表示为下图: +# +# ⁠ 4 +# ⁠ / \ +# ⁠ 2 6 +# ⁠ / \ +# ⁠ 1 3 +# +# 最小的差值是 1, 它是节点1和节点2的差值, 也是节点3和节点2的差值。 +# +# 注意: +# +# +# 二叉树的大小范围在 2 到 100。 +# 二叉树总是有效的,每个节点的值都是整数,且不重复。 +# +# +# +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + + +class Solution(object): + def minDiffInBST(self, root): + """ + :type root: TreeNode + :rtype: int + """ + self.ans = 31 << 1 + self.last = -31 << 1 + + def dfs(root): + if not root: + return + if root.left: + dfs(root.left) + self.ans = min(self.ans, root.val - self.last) + self.last = root.val + if root.right: + dfs(root.right) + + dfs(root) + return self.ans diff --git a/Week_02/id_26/LeetCode_938_26.py b/Week_02/id_26/LeetCode_938_26.py new file mode 100644 index 00000000..f57f99e3 --- /dev/null +++ b/Week_02/id_26/LeetCode_938_26.py @@ -0,0 +1,73 @@ +# +# @lc app=leetcode.cn id=938 lang=python +# +# [938] 二叉搜索树的范围和 +# +# https://leetcode-cn.com/problems/range-sum-of-bst/description/ +# +# algorithms +# Easy (74.72%) +# Likes: 39 +# Dislikes: 0 +# Total Accepted: 4.8K +# Total Submissions: 6.4K +# Testcase Example: '[10,5,15,3,7,null,18]\n7\n15' +# +# 给定二叉搜索树的根结点 root,返回 L 和 R(含)之间的所有结点的值的和。 +# +# 二叉搜索树保证具有唯一的值。 +# +# +# +# 示例 1: +# +# 输入:root = [10,5,15,3,7,null,18], L = 7, R = 15 +# 输出:32 +# +# +# 示例 2: +# +# 输入:root = [10,5,15,3,7,13,18,1,null,6], L = 6, R = 10 +# 输出:23 +# +# +# +# +# 提示: +# +# +# 树中的结点数量最多为 10000 个。 +# 最终的答案保证小于 2^31。 +# +# +# +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + + +class Solution(object): + def rangeSumBST(self, root, L, R): + """ + :type root: TreeNode + :type L: int + :type R: int + :rtype: int + """ + self.ans = 0 + + def _rangeSumBST(root): + if not root: + return + if root.val > L: + _rangeSumBST(root.left) + if L <= root.val <= R: + self.ans += root.val + if root.val < R: + _rangeSumBST(root.right) + + _rangeSumBST(root) + return self.ans diff --git a/Week_02/id_26/LeetCode_98_26.py b/Week_02/id_26/LeetCode_98_26.py new file mode 100644 index 00000000..f87a78cf --- /dev/null +++ b/Week_02/id_26/LeetCode_98_26.py @@ -0,0 +1,93 @@ +# +# @lc app=leetcode.cn id=98 lang=python +# +# [98] 验证二叉搜索树 +# +# https://leetcode-cn.com/problems/validate-binary-search-tree/description/ +# +# algorithms +# Medium (26.07%) +# Likes: 204 +# Dislikes: 0 +# Total Accepted: 25K +# Total Submissions: 95.8K +# Testcase Example: '[2,1,3]' +# +# 给定一个二叉树,判断其是否是一个有效的二叉搜索树。 +# +# 假设一个二叉搜索树具有如下特征: +# +# +# 节点的左子树只包含小于当前节点的数。 +# 节点的右子树只包含大于当前节点的数。 +# 所有左子树和右子树自身必须也是二叉搜索树。 +# +# +# 示例 1: +# +# 输入: +# ⁠ 2 +# ⁠ / \ +# ⁠ 1 3 +# 输出: true +# +# +# 示例 2: +# +# 输入: +# ⁠ 5 +# ⁠ / \ +# ⁠ 1 4 +# / \ +# 3 6 +# 输出: false +# 解释: 输入为: [5,1,4,null,null,3,6]。 +# 根节点的值为 5 ,但是其右子节点值为 4 。 +# +# +# +# Definition for a binary tree node. + +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + + +class Solution(object): + def isValidBST(self, root): + """ + :type root: TreeNode + :rtype: bool + 解法1:当前节点的值为 左子树的最大值 and 右子树的最小值 + """ + + def _isValidBST(root, min, max): + if not root: + return True + if root.val >= max or root.val <= min: + return False + return _isValidBST(root.left, min, root.val) and _isValidBST( + root.right, root.val, max) + + return _isValidBST(root, -1 << 32, 1 << 31) + + def isValidBST2(self, root): + """ + :type root: TreeNode + :rtype: bool + 解法2:中序遍历递增 + """ + self.last = -1 << 32 + + def _isValidBST(root): + if not root: + return True + left = _isValidBST(root.left) + ret = root.val > self.last + self.last = root.val + right = _isValidBST(root.right) + return left and ret and right + + return _isValidBST(root) diff --git a/Week_02/id_28/src/LeetCode_03_28.java b/Week_02/id_28/src/LeetCode_03_28.java new file mode 100644 index 00000000..21ed132f --- /dev/null +++ b/Week_02/id_28/src/LeetCode_03_28.java @@ -0,0 +1,34 @@ +import java.util.HashMap; +import java.util.Map; + +public class LeetCode_03_28 { + public int lengthOfLongestSubstring(String s) { + int first=0; + int last; + int len=s.length(); + if (len==0){ + return 0; + } + int max=Integer.MIN_VALUE; + Map map=new HashMap<>(); + for (last=0;last=root.val){ + return false; + } + this.prev=root; + boolean right_flag=inOrderVisit(root.right); + if(right_flag==false){ + return false; + } + return true; + } +} diff --git a/Week_02/id_28/src/TreeNode.java b/Week_02/id_28/src/TreeNode.java new file mode 100644 index 00000000..93e36291 --- /dev/null +++ b/Week_02/id_28/src/TreeNode.java @@ -0,0 +1,6 @@ +public class TreeNode { + int val; + TreeNode left; + TreeNode right; + TreeNode(int x) { val = x; } + } diff --git a/Week_02/id_29/LeetCode_001_29.go b/Week_02/id_29/LeetCode_001_29.go new file mode 100644 index 00000000..bb7dda8b --- /dev/null +++ b/Week_02/id_29/LeetCode_001_29.go @@ -0,0 +1,21 @@ +package leetcode + +func twoSum(nums []int, target int) []int { + // m store value and index + visited := make(map[int]int) + + for currentIndex, v := range nums { + // 找對應的元素 + counterPart := target - v + + counterPartIndex, ok := visited[counterPart] + if ok { + // 在 map 找到直接回傳 + return []int{counterPartIndex, currentIndex} + } + // 找不到就把自己加入到 map 裡面 + visited[v] = currentIndex + } + + return []int{-1, -1} +} diff --git a/Week_02/id_29/LeetCode_003_29.go b/Week_02/id_29/LeetCode_003_29.go new file mode 100644 index 00000000..220b7a28 --- /dev/null +++ b/Week_02/id_29/LeetCode_003_29.go @@ -0,0 +1,24 @@ +package leetcode + +import "strings" + +func lengthOfLongestSubstring(s string) int { + maxLength := 0 + right := 0 + curr := "" + + for right < len(s) { + char := string(s[right]) + if !strings.Contains(curr, char) { + curr += char + if len(curr) > maxLength { + maxLength = len(curr) + } + right++ + } else { + curr = curr[1:] + } + } + + return maxLength +} diff --git a/Week_02/id_29/LeetCode_098_29.go b/Week_02/id_29/LeetCode_098_29.go new file mode 100644 index 00000000..51154d16 --- /dev/null +++ b/Week_02/id_29/LeetCode_098_29.go @@ -0,0 +1,17 @@ +package leetcode + +func isValidBST(root *TreeNode) bool { + return rec(root, nil, nil) +} + +func rec(node *TreeNode, min, max *int) bool { + if node == nil { + return true + } + + if min != nil && node.Val <= *min || max != nil && node.Val >= *max { + return false + } + + return rec(node.Left, min, &node.Val) && rec(node.Right, &node.Val, max) +} diff --git a/Week_02/id_29/LeetCode_100_29.go b/Week_02/id_29/LeetCode_100_29.go new file mode 100644 index 00000000..da90b194 --- /dev/null +++ b/Week_02/id_29/LeetCode_100_29.go @@ -0,0 +1,21 @@ +package leetcode + +func isSymmetric(root *TreeNode) bool { + if root == nil { + return true + } + + return ish(root.Left, root.Right) +} + +func ish(l, r *TreeNode) bool { + if l == nil || r == nil { + return l == r + } + + if l.Val != r.Val { + return false + } + + return ish(l.Left, r.Right) && ish(l.Right, r.Left) +} diff --git a/Week_02/id_29/LeetCode_102_29.go b/Week_02/id_29/LeetCode_102_29.go new file mode 100644 index 00000000..3a05721d --- /dev/null +++ b/Week_02/id_29/LeetCode_102_29.go @@ -0,0 +1,25 @@ +package leetcode + +func levelOrder(root *TreeNode) [][]int { + var ret [][]int + + level := 1 + helper(root, level, &ret) + + return ret +} + +func helper(root *TreeNode, level int, ret *[][]int) { + if root == nil { + return + } + + if len(*ret) < level { + *ret = append(*ret, []int{root.Val}) + } else { + (*ret)[level-1] = append((*ret)[level-1], root.Val) + } + + helper(root.Left, level+1, ret) + helper(root.Right, level+1, ret) +} diff --git a/Week_02/id_29/LeetCode_103_29.go b/Week_02/id_29/LeetCode_103_29.go new file mode 100644 index 00000000..65352afe --- /dev/null +++ b/Week_02/id_29/LeetCode_103_29.go @@ -0,0 +1,32 @@ +package leetcode + +func zigzagLevelOrder(root *TreeNode) [][]int { + var result [][]int + + vector := 1 + stack := []*TreeNode{root} + + for len(stack) > 0 { + var tmp []*TreeNode + var levelVal []int + for i := len(stack) - 1; i >= 0; i-- { + node := stack[i] + if node == nil { + continue + } + if vector == 1 { + tmp = append(tmp, node.Left, node.Right) + } else { + tmp = append(tmp, node.Right, node.Left) + } + levelVal = append(levelVal, node.Val) + } + vector = -vector + stack = tmp + if len(levelVal) > 0 { + result = append(result, levelVal) + } + } + + return result +} diff --git a/Week_02/id_29/LeetCode_111_29.go b/Week_02/id_29/LeetCode_111_29.go new file mode 100644 index 00000000..7f5680cd --- /dev/null +++ b/Week_02/id_29/LeetCode_111_29.go @@ -0,0 +1,29 @@ +package leetcode + +func minDepth(root *TreeNode) int { + if root == nil { + return 0 + } + left := minDepth(root.Left) + right := minDepth(root.Right) + if left == 0 || right == 0 { + return 1 + max(left, right) + } + return 1 + min(left, right) +} + +func min(x, y int) int { + if x >= y { + return y + } else { + return x + } +} + +func max(x, y int) int { + if x <= y { + return y + } else { + return x + } +} diff --git a/Week_02/id_29/LeetCode_236_29.go b/Week_02/id_29/LeetCode_236_29.go new file mode 100644 index 00000000..ab1b7fc7 --- /dev/null +++ b/Week_02/id_29/LeetCode_236_29.go @@ -0,0 +1,19 @@ +package leetcode + +func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode { + if root == nil { + return nil + } + if root == p || root == q { + return root + } + left := lowestCommonAncestor(root.Left, p, q) + right := lowestCommonAncestor(root.Right, p, q) + if left != nil && right != nil { + return root + } + if left == nil { + return right + } + return left +} diff --git a/Week_02/id_29/LeetCode_242_29.go b/Week_02/id_29/LeetCode_242_29.go new file mode 100644 index 00000000..71466695 --- /dev/null +++ b/Week_02/id_29/LeetCode_242_29.go @@ -0,0 +1,36 @@ +package leetcode + +func isAnagram(s string, t string) bool { + if len(s) != len(t) { + return false + } + + mapA := buildCharMap(s) + mapB := buildCharMap(t) + + for key, Acount := range mapA { + Bcount, ok := mapB[key] + if !ok { + return false + } + if Acount != Bcount { + return false + } + } + + return true +} + +func buildCharMap(s string) map[rune]int { + m := make(map[rune]int) + + for _, char := range s { + if _, ok := m[char]; ok { + m[char]++ + } else { + m[char] = 1 + } + } + + return m +} diff --git a/Week_02/id_29/LeetCode_692_29.go b/Week_02/id_29/LeetCode_692_29.go new file mode 100644 index 00000000..0d16f64b --- /dev/null +++ b/Week_02/id_29/LeetCode_692_29.go @@ -0,0 +1,39 @@ +package leetcode + +import "sort" + +type entry struct { + word string + frequence int +} + +type freWords []*entry + +func topKFrequent(words []string, k int) []string { + count := make(map[string]int, len(words)) + for _, w := range words { + count[w]++ + } + + fw := make(freWords, 0, len(count)) + for w, c := range count { + fw = append(fw, &entry{ + word: w, + frequence: c, + }) + } + + sort.Slice(fw, func(i, j int) bool { + if fw[i].frequence == fw[j].frequence { + return fw[i].word < fw[j].word + } + return fw[i].frequence > fw[j].frequence + }) + + res := make([]string, k) + for i := 0; i < k; i++ { + res[i] = fw[i].word + } + + return res +} diff --git a/Week_02/id_29/LeetCode_938_29.go b/Week_02/id_29/LeetCode_938_29.go new file mode 100644 index 00000000..41dcc321 --- /dev/null +++ b/Week_02/id_29/LeetCode_938_29.go @@ -0,0 +1,22 @@ +package leetcode + +func rangeSumBST(root *TreeNode, L int, R int) int { + if root == nil { + return 0 + } + + sum := 0 + + switch { + case root.Val < L: + sum = rangeSumBST(root.Right, L, R) + case R < root.Val: + sum = rangeSumBST(root.Left, L, R) + default: + sum += root.Val + sum += rangeSumBST(root.Left, L, R) + sum += rangeSumBST(root.Right, L, R) + } + + return sum +} diff --git a/Week_02/id_29/main.go b/Week_02/id_29/main.go new file mode 100644 index 00000000..8aaf4acf --- /dev/null +++ b/Week_02/id_29/main.go @@ -0,0 +1,12 @@ +package leetcode + +type ListNode struct { + Val int + Next *ListNode +} + +type TreeNode struct { + Val int + Left *TreeNode + Right *TreeNode +} diff --git a/Week_02/id_3/NOTE.md b/Week_02/id_3/NOTE.md index 107ea7d6..b22dea54 100644 --- a/Week_02/id_3/NOTE.md +++ b/Week_02/id_3/NOTE.md @@ -1 +1,21 @@ # 学习笔记 +Iterator + +读题很重要 二叉树的序列化的教训 + +import heapq 堆 + +技巧 python中处理数字的时候小心使用 if v 或者 if not v 这种写法 +有时候想判断None,结果在0上栽了跟头 + +问题: +bst + 最大值 是否等价于堆 +python 的链表/堆等数据结构是否缺失 + +bs中很多实现使用系统最大值最小值,是否有隐患 + +python 整除 // + +实现数据结构,借助面向对象的成员变量,是一个好办法吗? + +python 的整除写法似乎比 int()来处理更快 diff --git a/Week_02/id_3/bstree/220/LeetCode_220_3_v1.py b/Week_02/id_3/bstree/220/LeetCode_220_3_v1.py new file mode 100644 index 00000000..b42c0b0e --- /dev/null +++ b/Week_02/id_3/bstree/220/LeetCode_220_3_v1.py @@ -0,0 +1,81 @@ +""" +暴力解法时间复杂度 O(kn) 似乎实现没什么难度,但是想必无法通过测试 +目前的思路是 维护一个空间为k的bst做为窗口 只要bst中距离目标值最近的元素绝对值小于等于t 即可返回True +在迭代数组的时候,对bst进行增与删的维护 +由于python似乎没有bst的数据结构,所以使用一个排序数组替代实现 +""" + + +class Solution: + def containsNearbyAlmostDuplicate(self, nums, k, t): + if not nums: + return False + if k == 0: + return False + if t < 0: + return False + + length = len(nums) + + if k > length: + k = length - 1 + + if length == 1: + return False + + sort_list = [nums[0]] + for i in range(1, length): + v = nums[i] + p = self.position(sort_list, v) + if sort_list[p] == v: + return True + + # 这里想写的优雅还挺难 边界处理起来很复杂 + if t >= abs(sort_list[p]-v): + return True + if sort_list[p] > v: + if p >= 0 and t >= abs(sort_list[p - 1]-v): + return True + else: + if (p+1) < len(sort_list) and t >= abs(sort_list[p + 1]-v): + return True + + if i < k: + self.insert(sort_list, p, v) + continue + + need_pop = nums[i-k] + if need_pop == v: + continue + else: + self.insert(sort_list, p, v) + sort_list.pop(self.position(sort_list, need_pop)) + return False + + def insert(self, sort_list, p, v): + if sort_list[p] > v: + sort_list.insert(p, v) + else: + sort_list.insert(p + 1, v) + + def position(self, sort_list, v): + low = 0 + high = len(sort_list) - 1 + while low <= high: + mid = low + int((high - low)/2) + if sort_list[mid] == v: + return mid + if sort_list[mid] > v: + high = mid - 1 + else: + low = mid + 1 + + return mid + + +s = Solution() + +print(s.containsNearbyAlmostDuplicate([1, 2, 3, 1], 3, 0)) +print(s.containsNearbyAlmostDuplicate([1, 0, 1, 1], 1, 2)) +print(s.containsNearbyAlmostDuplicate([1, 5, 9, 1, 5, 9], 2, 3)) +print(s.containsNearbyAlmostDuplicate([4, 1, 6, 3], 100, 1)) diff --git a/Week_02/id_3/bstree/220/LeetCode_220_3_v2.py b/Week_02/id_3/bstree/220/LeetCode_220_3_v2.py new file mode 100644 index 00000000..5a5f8855 --- /dev/null +++ b/Week_02/id_3/bstree/220/LeetCode_220_3_v2.py @@ -0,0 +1,56 @@ +""" +暴力解法时间复杂度 O(kn) 似乎实现没什么难度,但是想必无法通过测试 +但是上一个解法python实现效率太差了,试试暴力行不行 +没想到还真通过了 +""" + + +class Solution: + def containsNearbyAlmostDuplicate(self, nums, k, t): + if not nums: + return False + if k == 0: + return False + if t < 0: + return False + + if k > t: + return self.tn(nums, k, t) + else: + return self.kn(nums, k, t) + + def tn(self, nums, k, t): + m = {} + for i in range(len(nums)): + v = nums[i] + for j in range(-t, t + 1): + if (v+j) in m and k >= (i - m[v+j]): + return True + m[v] = i + return False + + def kn(self, nums, k, t): + length = len(nums) + if k > length: + k = length - 1 + for i in range(length): + v = nums[i] + for p in range(1, k + 1): + index = i + p + if index == length: + break + if t >= abs(v - nums[index]): + return True + + return False + + +s = Solution() + +print(s.containsNearbyAlmostDuplicate([1, 2, 3, 1], 3, 0)) +print(s.containsNearbyAlmostDuplicate([1, 0, 1, 1], 1, 2)) +print(s.containsNearbyAlmostDuplicate([1, 5, 9, 1, 5, 9], 2, 3)) +print(s.containsNearbyAlmostDuplicate([4, 1, 6, 3], 100, 1)) +print(s.containsNearbyAlmostDuplicate([7, 1, 3], 2, 3)) +print(s.containsNearbyAlmostDuplicate([7, 2, 8], 2, 1)) +print(s.containsNearbyAlmostDuplicate([2, 0, -2, 2], 2, 1)) diff --git a/Week_02/id_3/bstree/220/LeetCode_220_3_v3.py b/Week_02/id_3/bstree/220/LeetCode_220_3_v3.py new file mode 100644 index 00000000..fb88f25b --- /dev/null +++ b/Week_02/id_3/bstree/220/LeetCode_220_3_v3.py @@ -0,0 +1,60 @@ +""" +参考高人的写法 震惊 + +如果abs(n1, n2) <= t +那么 abs(n1//t - n2//t) <= 1 + +数字 n 只需要在缓存中查找 n//t-1, n//t, n//t+1 (以下记为 m1, m2, m3) 三个对应的数据即可找到是否有符合条件的数据存在。 +n如果存在满足条件的目标答案,必然会首先出现在 m1, m2, m3所对应的数据中。 +nums中可能存在多个数据与m123映射,其中可能存在符合条件与不符合条件的数据, +但当迭代到n时,m123必然不会出现曾经有效的数据被无效数据覆盖的情况。 +例如m3对应n3_1与n3_2两个值,其中abs(n3_1-n)<=t, abs(n3_2-n)>t,如果存在这种情况,当数据遍历至n3_2时即可返回True,不会迭代至n。 +缓存维护k个数据即可满足下标不超过k的条件。 + +整体时间复杂度O(n) 神了 跪下了 +""" + + +class Solution: + def containsNearbyAlmostDuplicate(self, nums, k, t): + if not nums: + return False + if k == 0: + return False + if t < 0: + return False + + m = {} + length = len(nums) + if k > length: + k = length - 1 + + for i in range(length): + v = nums[i] + + key = v if not t else v//t + + for j in (-1, 0, 1): + x = m.get(key + j, None) + if x is None: + continue + if t >= abs(x - v): + return True + + if i >= k: + m.pop(nums[i-k] if not t else nums[i-k]//t) + + m[key] = v + + return False + + +s = Solution() + +print(s.containsNearbyAlmostDuplicate([1, 2, 3, 1], 3, 0)) +print(s.containsNearbyAlmostDuplicate([1, 0, 1, 1], 1, 2)) +print(s.containsNearbyAlmostDuplicate([1, 5, 9, 1, 5, 9], 2, 3)) +print(s.containsNearbyAlmostDuplicate([4, 1, 6, 3], 100, 1)) +print(s.containsNearbyAlmostDuplicate([7, 1, 3], 2, 3)) +print(s.containsNearbyAlmostDuplicate([7, 2, 8], 2, 1)) +print(s.containsNearbyAlmostDuplicate([2, 0, -2, 2], 2, 1)) diff --git a/Week_02/id_3/bstree/235/LeetCode_235_3_v1.py b/Week_02/id_3/bstree/235/LeetCode_235_3_v1.py new file mode 100644 index 00000000..17cb938b --- /dev/null +++ b/Week_02/id_3/bstree/235/LeetCode_235_3_v1.py @@ -0,0 +1,14 @@ +class Solution: + def lowestCommonAncestor(self, root, p, q): + if p.val > q.val: + p, q = q, p + while True: + if root.val < p.val: + root = root.right + continue + + if root.val > q.val: + root = root.left + continue + + return root diff --git a/Week_02/id_3/bstree/315/LeetCode_315_3_v1.py b/Week_02/id_3/bstree/315/LeetCode_315_3_v1.py new file mode 100644 index 00000000..3d6c0c84 --- /dev/null +++ b/Week_02/id_3/bstree/315/LeetCode_315_3_v1.py @@ -0,0 +1,34 @@ +""" + 0 建立排序数组 + 1 倒序遍历 + 2 二分查找找到坐标 +""" + + +class Solution: + def countSmaller(self, nums): + _sorted = [] + length = len(nums) + for i in range(length - 1, -1, -1): + v = nums[i] + nums[i] = self.bs(_sorted, v) + + return nums + + def bs(self, _sorted, v): + low = 0 + high = len(_sorted) - 1 + while low <= high: + mid = low + (high-low)//2 + if _sorted[mid] >= v: + high = mid - 1 + else: + low = mid + 1 + + _sorted.insert(low, v) + return low + + +s = Solution() +print(s.countSmaller([5, 2, 6, 1]) == [2, 1, 1, 0]) +print(s.countSmaller([-1, -1]) == [0, 0]) diff --git a/Week_02/id_3/bstree/938/LeetCode_938_3_v1.py b/Week_02/id_3/bstree/938/LeetCode_938_3_v1.py new file mode 100644 index 00000000..656c7b91 --- /dev/null +++ b/Week_02/id_3/bstree/938/LeetCode_938_3_v1.py @@ -0,0 +1,15 @@ +class Solution: + def rangeSumBST(self, root, l, r): + return self.dfs(root, l, r) + + def dfs(self, node, l, r): + if not node: + return 0 + + if node.val < l: + return self.dfs(node.right, l, r) + + if node.val > r: + return self.dfs(node.left, l, r) + + return self.dfs(node.left, l, r) + node.val + self.dfs(node.right, l, r) diff --git a/Week_02/id_3/bstree/98/LeetCode_98_3_v1.py b/Week_02/id_3/bstree/98/LeetCode_98_3_v1.py new file mode 100644 index 00000000..98c50800 --- /dev/null +++ b/Week_02/id_3/bstree/98/LeetCode_98_3_v1.py @@ -0,0 +1,21 @@ +class Solution: + def isValidBST(self, root): + """ + 深度优先中序遍历方案 + """ + stack = [] + node = root + last = None + while stack or node: + if node: + stack.append(node) + node = node.left + else: + node = stack.pop() + if last is None or last < node.val: + last = node.val + else: + return False + node = node.right + + return True diff --git a/Week_02/id_3/bstree/98/LeetCode_98_3_v2.py b/Week_02/id_3/bstree/98/LeetCode_98_3_v2.py new file mode 100644 index 00000000..004d48ea --- /dev/null +++ b/Week_02/id_3/bstree/98/LeetCode_98_3_v2.py @@ -0,0 +1,32 @@ +class Solution: + def isValidBST(self, root): + """ + 递归 + """ + if not root: + return True + + return self.min_max(root)[0] + + def min_max(self, node): + if not node.left and not node.right: + return [True, node.val, node.val] + + result = [True, None, None] + if node.left: + r = self.min_max(node.left) + if not r[0] or r[2] >= node.val: + return [False] + result[1] = r[1] + else: + result[1] = node.val + + if node.right: + r = self.min_max(node.right) + if not r[0] or r[1] <= node.val: + return [False] + result[2] = r[2] + else: + result[2] = node.val + + return result diff --git a/Week_02/id_3/bstree/98/LeetCode_98_3_v3.py b/Week_02/id_3/bstree/98/LeetCode_98_3_v3.py new file mode 100644 index 00000000..7ad22d93 --- /dev/null +++ b/Week_02/id_3/bstree/98/LeetCode_98_3_v3.py @@ -0,0 +1,20 @@ +class Solution: + def isValidBST(self, root): + """ + bst定义 + 左子树都比节点小 + 右子树都比节点大 + 并且所有子树都一样 + 写起来代码更好看,更优雅 + """ + return self.valid(root, None, None) + + def valid(self, node, left, right): + if not node: + return True + if left is not None and left >= node.val: + return False + if right is not None and right <= node.val: + return False + + return self.valid(node.left, left, node.val) and self.valid(node.right, node.val, right) diff --git a/Week_02/id_3/hash/1/LeetCode_1_3_v1.py b/Week_02/id_3/hash/1/LeetCode_1_3_v1.py new file mode 100644 index 00000000..ed2e04c3 --- /dev/null +++ b/Week_02/id_3/hash/1/LeetCode_1_3_v1.py @@ -0,0 +1,16 @@ +class Solution: + def twoSum(self, nums, target): + cache = {} + for i in range(len(nums)): + n = nums[i] + v = target - n + if v in cache: + return [cache.get(v), i] + else: + cache[n] = i + + return [] + + +s = Solution() +print(s.twoSum([2, 7, 11, 15], 9)) diff --git a/Week_02/id_3/hash/242/LeetCode_242_3_v1.py b/Week_02/id_3/hash/242/LeetCode_242_3_v1.py new file mode 100644 index 00000000..01c623fc --- /dev/null +++ b/Week_02/id_3/hash/242/LeetCode_242_3_v1.py @@ -0,0 +1,23 @@ +c_a = ord('a') + + +class Solution: + def isAnagram(self, s: str, t: str) -> bool: + if len(s) != len(t): + return False + arr = [0] * 26 + for c in s: + arr[ord(c) % c_a] += 1 + + for c in t: + i = ord(c) % c_a + if arr[i] == 0: + return False + arr[i] -= 1 + + return True + + +s = Solution() +print(s.isAnagram("anagram", "nagaram")) +print(s.isAnagram("rat", "car")) diff --git a/Week_02/id_3/hash/3/LeetCode_3_3_v1.py b/Week_02/id_3/hash/3/LeetCode_3_3_v1.py new file mode 100644 index 00000000..e337faba --- /dev/null +++ b/Week_02/id_3/hash/3/LeetCode_3_3_v1.py @@ -0,0 +1,29 @@ +class Solution: + def lengthOfLongestSubstring(self, s: str) -> int: + if not s or len(s) == 0: + return 0 + low = high = 0 + length = len(s) + result = 1 + cache_set = set() + while high < length: + v = s[high] + if v not in cache_set: + cache_set.add(v) + high += 1 + result = max(result, high - low) + else: + while low < high: + low_v = s[low] + cache_set.remove(low_v) + low += 1 + if low_v == v: + break + + return result + + +s = Solution() +print(s.lengthOfLongestSubstring("abcabcbb") == 3) +print(s.lengthOfLongestSubstring("bbbbb") == 1) +print(s.lengthOfLongestSubstring("pwwkew") == 3) diff --git a/Week_02/id_3/hash/692/LeetCode_692_3_v1.py b/Week_02/id_3/hash/692/LeetCode_692_3_v1.py new file mode 100644 index 00000000..64babe7e --- /dev/null +++ b/Week_02/id_3/hash/692/LeetCode_692_3_v1.py @@ -0,0 +1,40 @@ +""" + 使用数组排序,居然就过了 + 代码有些丑陋,主要是对python不熟悉,不知道怎么自定义排序规则 + 理论上使用最小堆做优化效果更好 +""" + + +class Solution: + def topKFrequent(self, words, k): + word_map = {} + count_list = [] + for w in words: + word_map[w] = word_map.get(w, 0) + 1 + + count_map = {} + for (w, count) in word_map.items(): + count_list.append(count) + wl = count_map.get(count, []) + wl.append(w) + count_map[count] = wl + + count_list.sort(reverse=True) + r = [] + last_count = 0 + for count in count_list: + if last_count == count: + continue + else: + last_count = count + count_map[count].sort() + for w in count_map[count]: + r.append(w) + if len(r) == k: + return r + + +s = Solution() +# print(s.topKFrequent(["i", "love", "leetcode", "i", "love", "coding"], 2)) +# print(s.topKFrequent(["the", "day", "is", "sunny", "the", "the", "the", "sunny", "is", "is"], 4)) +print(s.topKFrequent(["i", "love", "leetcode", "i", "love", "coding"], 3)) diff --git a/Week_02/id_3/hash/726/LeetCode_726_3_v1.py b/Week_02/id_3/hash/726/LeetCode_726_3_v1.py new file mode 100644 index 00000000..cfd87755 --- /dev/null +++ b/Week_02/id_3/hash/726/LeetCode_726_3_v1.py @@ -0,0 +1,73 @@ +n0, n9 = ord('0'), ord('9') +a, z = ord('a'), ord('z') +A, Z = ord('A'), ord('Z') + +STATUS_INIT = 0 +STATUS_ATOM = 1 +STATUS_NUMBER = 2 + + +class Solution: + def countOfAtoms(self, formula: str) -> str: + stack = [] + atom_map = {} + cur_map = {} + status = STATUS_INIT + letter_list = [] + for c in formula: + if c == '(' or c == ')': + self.handle(letter_list, status, cur_map) + self.merge_map(atom_map, cur_map) + if c == '(': + stack.append(atom_map) + atom_map = {} + continue + elif c == ')': + cur_map = atom_map + atom_map = stack.pop() + status = STATUS_INIT + continue + + v = ord(c) + if A <= v <= Z: + self.handle(letter_list, status, cur_map) + self.merge_map(atom_map, cur_map) + status = STATUS_ATOM + elif n0 <= v <= n9: + if status != STATUS_NUMBER: + self.handle(letter_list, status, cur_map) + status = STATUS_NUMBER + + letter_list.append(c) + + self.handle(letter_list, status, cur_map) + self.merge_map(atom_map, cur_map) + + r = [] + for k in sorted(atom_map.keys()): + v = atom_map[k] + r.append('%s%s' % (k, v if v != 1 else '')) + return ''.join(r) + + def handle(self, letter_list, status, cur_map): + if not letter_list: + return + + s = ''.join(letter_list) + if status == STATUS_NUMBER: + n = int(s) + for (k, v) in cur_map.items(): + cur_map[k] = v * n + elif status == STATUS_ATOM: + cur_map[s] = 1 + + letter_list.clear() + + def merge_map(self, m1, m2): + if not m2: + return m1 + for (k, v) in m2.items(): + m1[k] = m1.get(k, 0) + v + m2.clear() + return m1 + diff --git a/Week_02/id_3/hash/726/LeetCode_726_3_v2.py b/Week_02/id_3/hash/726/LeetCode_726_3_v2.py new file mode 100644 index 00000000..b96baa89 --- /dev/null +++ b/Week_02/id_3/hash/726/LeetCode_726_3_v2.py @@ -0,0 +1,83 @@ +n0, n9 = ord('0'), ord('9') +a, z = ord('a'), ord('z') +A, Z = ord('A'), ord('Z') + +STATUS_INIT = 0 +STATUS_ATOM = 1 +STATUS_NUMBER = 2 + + +class Solution: + def countOfAtoms(self, formula: str) -> str: + atom_map = self.parse(iter(formula)) + r = [] + for k in sorted(atom_map.keys()): + r.append(k) + v = atom_map[k] + r.append(str(v) if v != 1 else '') + return ''.join(r) + + def parse(self, iterator) -> dict: + atom_map = {} + cur_map = {} + letters = [] + status = STATUS_ATOM + while True: + try: + c = next(iterator) + if ')' == c: + break + + if '(' == c: + self.handle(cur_map, letters, status) + self.merge(atom_map, cur_map) + cur_map = self.parse(iterator) + continue + + v = ord(c) + + if A <= v <= Z: + self.handle(cur_map, letters, status) + self.merge(atom_map, cur_map) + status = STATUS_ATOM + elif n0 <= v <= n9 and status != STATUS_NUMBER: + self.handle(cur_map, letters, status) + status = STATUS_NUMBER + + letters.append(c) + + except StopIteration: + break + + self.handle(cur_map, letters, status) + self.merge(atom_map, cur_map) + return atom_map + + def letters(self, letters): + r = ''.join(letters) + letters.clear() + return r + + def atom(self, cur_map, letters): + cur_map[self.letters(letters)] = 1 + + def numbers(self, cur_map, letters): + numbers = int(self.letters(letters)) + for (k, v) in cur_map.items(): + cur_map[k] = v * numbers + + def handle(self, cur_map, letters, status): + if not letters: + return + if status == STATUS_NUMBER: + self.numbers(cur_map, letters) + else: + self.atom(cur_map, letters) + + def merge(self, atom_map, cur_map): + if not cur_map: + return + for (k, v) in cur_map.items(): + atom_map[k] = atom_map.get(k, 0) + v + + cur_map.clear() diff --git a/Week_02/id_3/hash/726/test_726.py b/Week_02/id_3/hash/726/test_726.py new file mode 100644 index 00000000..244414e5 --- /dev/null +++ b/Week_02/id_3/hash/726/test_726.py @@ -0,0 +1,10 @@ +import LeetCode_726_3_v1 +import LeetCode_726_3_v2 + +# Solution = LeetCode_726_3_v1.Solution +Solution = LeetCode_726_3_v2.Solution + +s1 = Solution() +print(s1.countOfAtoms('H2O') == 'H2O') +print(s1.countOfAtoms('Mg(OH)2') == 'H2MgO2') +print(s1.countOfAtoms('K4(ON(SO3)2)2') == 'K4N2O14S4') diff --git a/Week_02/id_3/tree/LeetCode_101_3_v1.py b/Week_02/id_3/tree/LeetCode_101_3_v1.py new file mode 100644 index 00000000..87c02651 --- /dev/null +++ b/Week_02/id_3/tree/LeetCode_101_3_v1.py @@ -0,0 +1,21 @@ +class Solution: + def isSymmetric(self, root): + if not root: + return True + stack = [root.left, root.right] + while stack: + n1 = stack.pop() + n2 = stack.pop() + + if not n1 and not n2: + continue + if not n1 or not n2: + return False + if n1.val != n2.val: + return False + + stack.append(n1.left) + stack.append(n2.right) + stack.append(n1.right) + stack.append(n2.left) + return True diff --git a/Week_02/id_3/tree/LeetCode_103_3_v1.py b/Week_02/id_3/tree/LeetCode_103_3_v1.py new file mode 100644 index 00000000..81838d61 --- /dev/null +++ b/Week_02/id_3/tree/LeetCode_103_3_v1.py @@ -0,0 +1,26 @@ +""" +正常广度优先遍历 在插入结果的时候进行反转 +""" + +class Solution: + def zigzagLevelOrder(self, root): + r = [] + if not root: + return r + queue = [root] + while queue: + _queue = [] + for i in range(len(queue)): + node = queue[i] + queue[i] = node.val + if node.left: + _queue.append(node.left) + if node.right: + _queue.append(node.right) + + r.append(queue) + if len(r) % 2 == 0: + queue.reverse() + queue = _queue + + return r diff --git a/Week_02/id_3/tree/LeetCode_103_3_v2.py b/Week_02/id_3/tree/LeetCode_103_3_v2.py new file mode 100644 index 00000000..a22d929e --- /dev/null +++ b/Week_02/id_3/tree/LeetCode_103_3_v2.py @@ -0,0 +1,38 @@ +""" +复杂版本的实现 在插入和迭代的时候就直接有倒序的元素 +""" + + +class Solution: + def zigzagLevelOrder(self, root): + r = [] + if not root: + return r + queue = [root] + while queue: + r.append(queue) + need_reverse = len(r) % 2 == 0 + _queue = [] + + if need_reverse: + rg = range(len(queue) - 1, -1, -1) + else: + rg = range(len(queue)) + + for i in rg: + node = queue[i] + queue[i] = node.val + if need_reverse: + if node.left: + _queue.append(node.left) + if node.right: + _queue.append(node.right) + else: + if node.left: + _queue.insert(0, node.left) + if node.right: + _queue.insert(0, node.right) + + queue = _queue + + return r diff --git a/Week_02/id_3/tree/LeetCode_10_3_v1.py b/Week_02/id_3/tree/LeetCode_10_3_v1.py new file mode 100644 index 00000000..16ac45c9 --- /dev/null +++ b/Week_02/id_3/tree/LeetCode_10_3_v1.py @@ -0,0 +1,20 @@ +class Solution: + def levelOrder(self, root): + r = [] + if not root: + return r + queue = [root] + while queue: + _queue = [] + for i in range(len(queue)): + node = queue[i] + queue[i] = node.val + if node.left: + _queue.append(node.left) + if node.right: + _queue.append(node.right) + + r.append(queue) + queue = _queue + + return r diff --git a/Week_02/id_3/tree/LeetCode_111_3_v1.py b/Week_02/id_3/tree/LeetCode_111_3_v1.py new file mode 100644 index 00000000..dadc6d29 --- /dev/null +++ b/Week_02/id_3/tree/LeetCode_111_3_v1.py @@ -0,0 +1,21 @@ +class Solution: + def minDepth(self, root) -> int: + if root is None: + return 0 + + queue = [root] + + level = 0 + while queue: + level += 1 + _queue = [] + for node in queue: + if not node.left and not node.right: + return level + + if node.left: + _queue.append(node.left) + if node.right: + _queue.append(node.right) + + queue = _queue diff --git a/Week_02/id_3/tree/LeetCode_111_3_v2.py b/Week_02/id_3/tree/LeetCode_111_3_v2.py new file mode 100644 index 00000000..f61c3539 --- /dev/null +++ b/Week_02/id_3/tree/LeetCode_111_3_v2.py @@ -0,0 +1,21 @@ +class Solution: + def minDepth(self, root) -> int: + if root is None: + return 0 + + self.level = None + self.dfs(root, 0) + return self.level + + def dfs(self, node, level): + if not node: + return + level += 1 + if self.level and self.level <= level: + return + if not node.left and not node.right: + self.level = level + return + + self.dfs(node.left, level) + self.dfs(node.right, level) diff --git a/Week_02/id_3/tree/LeetCode_297_3_v1.py b/Week_02/id_3/tree/LeetCode_297_3_v1.py new file mode 100644 index 00000000..c026cd4d --- /dev/null +++ b/Week_02/id_3/tree/LeetCode_297_3_v1.py @@ -0,0 +1,62 @@ +class TreeNode(object): + def __init__(self, x): + self.val = x + self.left = None + self.right = None + + +class Codec: + + def serialize(self, root): + data = [] + queue = [root] + none_count = 0 + while len(queue) != 0: + if none_count >= len(queue): + break + _queue = [] + for i in range(len(queue)): + node = queue[i] + if not node: + none_count += 1 + data.append(None) + continue + + none_count = 0 + data.append(node.val) + _queue.append(node.left) + _queue.append(node.right) + queue = _queue + return data[:-none_count] + + def deserialize(self, data): + if not data: + return None + + root = TreeNode(data[0]) + queue = [root] + length = len(data) + + index = 1 + while len(queue) != 0: + _queue = [] + for i in range(len(queue)): + node = queue[i] + # 不可思议的问题 + if not node: + continue + if index >= length: + return root + d = data[index] + node.left = TreeNode(d) if d is not None else None + _queue.append(node.left) + index += 1 + if index >= length: + return root + d = data[index] + node.right = TreeNode(d) if d is not None else None + _queue.append(node.right) + index += 1 + queue = _queue + + return root diff --git a/Week_02/id_3/tree/test_297.py b/Week_02/id_3/tree/test_297.py new file mode 100644 index 00000000..22bbdb8b --- /dev/null +++ b/Week_02/id_3/tree/test_297.py @@ -0,0 +1,2015 @@ +import LeetCode_297_3_v1 + +Codec = LeetCode_297_3_v1.Codec + +codec = Codec() + + +def check(nums): + print(len(nums)) + r = codec.serialize(codec.deserialize(nums)) + print(r, r == nums) + + +check([1, 2, 3, None, None, 4, 5]) +# check([ +# 1, +# None, +# 2, +# None, +# 3, +# None, +# 4, +# None, +# 5, +# None, +# 6, +# None, +# 7, +# None, +# 8, +# None, +# 9, +# None, +# 10, +# None, +# 11, +# None, +# 12, +# None, +# 13, +# None, +# 14, +# None, +# 15, +# None, +# 16, +# None, +# 17, +# None, +# 18, +# None, +# 19, +# None, +# 20, +# None, +# 21, +# None, +# 22, +# None, +# 23, +# None, +# 24, +# None, +# 25, +# None, +# 26, +# None, +# 27, +# None, +# 28, +# None, +# 29, +# None, +# 30, +# None, +# 31, +# None, +# 32, +# None, +# 33, +# None, +# 34, +# None, +# 35, +# None, +# 36, +# None, +# 37, +# None, +# 38, +# None, +# 39, +# None, +# 40, +# None, +# 41, +# None, +# 42, +# None, +# 43, +# None, +# 44, +# None, +# 45, +# None, +# 46, +# None, +# 47, +# None, +# 48, +# None, +# 49, +# None, +# 50, +# None, +# 51, +# None, +# 52, +# None, +# 53, +# None, +# 54, +# None, +# 55, +# None, +# 56, +# None, +# 57, +# None, +# 58, +# None, +# 59, +# None, +# 60, +# None, +# 61, +# None, +# 62, +# None, +# 63, +# None, +# 64, +# None, +# 65, +# None, +# 66, +# None, +# 67, +# None, +# 68, +# None, +# 69, +# None, +# 70, +# None, +# 71, +# None, +# 72, +# None, +# 73, +# None, +# 74, +# None, +# 75, +# None, +# 76, +# None, +# 77, +# None, +# 78, +# None, +# 79, +# None, +# 80, +# None, +# 81, +# None, +# 82, +# None, +# 83, +# None, +# 84, +# None, +# 85, +# None, +# 86, +# None, +# 87, +# None, +# 88, +# None, +# 89, +# None, +# 90, +# None, +# 91, +# None, +# 92, +# None, +# 93, +# None, +# 94, +# None, +# 95, +# None, +# 96, +# None, +# 97, +# None, +# 98, +# None, +# 99, +# None, +# 100, +# None, +# 101, +# None, +# 102, +# None, +# 103, +# None, +# 104, +# None, +# 105, +# None, +# 106, +# None, +# 107, +# None, +# 108, +# None, +# 109, +# None, +# 110, +# None, +# 111, +# None, +# 112, +# None, +# 113, +# None, +# 114, +# None, +# 115, +# None, +# 116, +# None, +# 117, +# None, +# 118, +# None, +# 119, +# None, +# 120, +# None, +# 121, +# None, +# 122, +# None, +# 123, +# None, +# 124, +# None, +# 125, +# None, +# 126, +# None, +# 127, +# None, +# 128, +# None, +# 129, +# None, +# 130, +# None, +# 131, +# None, +# 132, +# None, +# 133, +# None, +# 134, +# None, +# 135, +# None, +# 136, +# None, +# 137, +# None, +# 138, +# None, +# 139, +# None, +# 140, +# None, +# 141, +# None, +# 142, +# None, +# 143, +# None, +# 144, +# None, +# 145, +# None, +# 146, +# None, +# 147, +# None, +# 148, +# None, +# 149, +# None, +# 150, +# None, +# 151, +# None, +# 152, +# None, +# 153, +# None, +# 154, +# None, +# 155, +# None, +# 156, +# None, +# 157, +# None, +# 158, +# None, +# 159, +# None, +# 160, +# None, +# 161, +# None, +# 162, +# None, +# 163, +# None, +# 164, +# None, +# 165, +# None, +# 166, +# None, +# 167, +# None, +# 168, +# None, +# 169, +# None, +# 170, +# None, +# 171, +# None, +# 172, +# None, +# 173, +# None, +# 174, +# None, +# 175, +# None, +# 176, +# None, +# 177, +# None, +# 178, +# None, +# 179, +# None, +# 180, +# None, +# 181, +# None, +# 182, +# None, +# 183, +# None, +# 184, +# None, +# 185, +# None, +# 186, +# None, +# 187, +# None, +# 188, +# None, +# 189, +# None, +# 190, +# None, +# 191, +# None, +# 192, +# None, +# 193, +# None, +# 194, +# None, +# 195, +# None, +# 196, +# None, +# 197, +# None, +# 198, +# None, +# 199, +# None, +# 200, +# None, +# 201, +# None, +# 202, +# None, +# 203, +# None, +# 204, +# None, +# 205, +# None, +# 206, +# None, +# 207, +# None, +# 208, +# None, +# 209, +# None, +# 210, +# None, +# 211, +# None, +# 212, +# None, +# 213, +# None, +# 214, +# None, +# 215, +# None, +# 216, +# None, +# 217, +# None, +# 218, +# None, +# 219, +# None, +# 220, +# None, +# 221, +# None, +# 222, +# None, +# 223, +# None, +# 224, +# None, +# 225, +# None, +# 226, +# None, +# 227, +# None, +# 228, +# None, +# 229, +# None, +# 230, +# None, +# 231, +# None, +# 232, +# None, +# 233, +# None, +# 234, +# None, +# 235, +# None, +# 236, +# None, +# 237, +# None, +# 238, +# None, +# 239, +# None, +# 240, +# None, +# 241, +# None, +# 242, +# None, +# 243, +# None, +# 244, +# None, +# 245, +# None, +# 246, +# None, +# 247, +# None, +# 248, +# None, +# 249, +# None, +# 250, +# None, +# 251, +# None, +# 252, +# None, +# 253, +# None, +# 254, +# None, +# 255, +# None, +# 256, +# None, +# 257, +# None, +# 258, +# None, +# 259, +# None, +# 260, +# None, +# 261, +# None, +# 262, +# None, +# 263, +# None, +# 264, +# None, +# 265, +# None, +# 266, +# None, +# 267, +# None, +# 268, +# None, +# 269, +# None, +# 270, +# None, +# 271, +# None, +# 272, +# None, +# 273, +# None, +# 274, +# None, +# 275, +# None, +# 276, +# None, +# 277, +# None, +# 278, +# None, +# 279, +# None, +# 280, +# None, +# 281, +# None, +# 282, +# None, +# 283, +# None, +# 284, +# None, +# 285, +# None, +# 286, +# None, +# 287, +# None, +# 288, +# None, +# 289, +# None, +# 290, +# None, +# 291, +# None, +# 292, +# None, +# 293, +# None, +# 294, +# None, +# 295, +# None, +# 296, +# None, +# 297, +# None, +# 298, +# None, +# 299, +# None, +# 300, +# None, +# 301, +# None, +# 302, +# None, +# 303, +# None, +# 304, +# None, +# 305, +# None, +# 306, +# None, +# 307, +# None, +# 308, +# None, +# 309, +# None, +# 310, +# None, +# 311, +# None, +# 312, +# None, +# 313, +# None, +# 314, +# None, +# 315, +# None, +# 316, +# None, +# 317, +# None, +# 318, +# None, +# 319, +# None, +# 320, +# None, +# 321, +# None, +# 322, +# None, +# 323, +# None, +# 324, +# None, +# 325, +# None, +# 326, +# None, +# 327, +# None, +# 328, +# None, +# 329, +# None, +# 330, +# None, +# 331, +# None, +# 332, +# None, +# 333, +# None, +# 334, +# None, +# 335, +# None, +# 336, +# None, +# 337, +# None, +# 338, +# None, +# 339, +# None, +# 340, +# None, +# 341, +# None, +# 342, +# None, +# 343, +# None, +# 344, +# None, +# 345, +# None, +# 346, +# None, +# 347, +# None, +# 348, +# None, +# 349, +# None, +# 350, +# None, +# 351, +# None, +# 352, +# None, +# 353, +# None, +# 354, +# None, +# 355, +# None, +# 356, +# None, +# 357, +# None, +# 358, +# None, +# 359, +# None, +# 360, +# None, +# 361, +# None, +# 362, +# None, +# 363, +# None, +# 364, +# None, +# 365, +# None, +# 366, +# None, +# 367, +# None, +# 368, +# None, +# 369, +# None, +# 370, +# None, +# 371, +# None, +# 372, +# None, +# 373, +# None, +# 374, +# None, +# 375, +# None, +# 376, +# None, +# 377, +# None, +# 378, +# None, +# 379, +# None, +# 380, +# None, +# 381, +# None, +# 382, +# None, +# 383, +# None, +# 384, +# None, +# 385, +# None, +# 386, +# None, +# 387, +# None, +# 388, +# None, +# 389, +# None, +# 390, +# None, +# 391, +# None, +# 392, +# None, +# 393, +# None, +# 394, +# None, +# 395, +# None, +# 396, +# None, +# 397, +# None, +# 398, +# None, +# 399, +# None, +# 400, +# None, +# 401, +# None, +# 402, +# None, +# 403, +# None, +# 404, +# None, +# 405, +# None, +# 406, +# None, +# 407, +# None, +# 408, +# None, +# 409, +# None, +# 410, +# None, +# 411, +# None, +# 412, +# None, +# 413, +# None, +# 414, +# None, +# 415, +# None, +# 416, +# None, +# 417, +# None, +# 418, +# None, +# 419, +# None, +# 420, +# None, +# 421, +# None, +# 422, +# None, +# 423, +# None, +# 424, +# None, +# 425, +# None, +# 426, +# None, +# 427, +# None, +# 428, +# None, +# 429, +# None, +# 430, +# None, +# 431, +# None, +# 432, +# None, +# 433, +# None, +# 434, +# None, +# 435, +# None, +# 436, +# None, +# 437, +# None, +# 438, +# None, +# 439, +# None, +# 440, +# None, +# 441, +# None, +# 442, +# None, +# 443, +# None, +# 444, +# None, +# 445, +# None, +# 446, +# None, +# 447, +# None, +# 448, +# None, +# 449, +# None, +# 450, +# None, +# 451, +# None, +# 452, +# None, +# 453, +# None, +# 454, +# None, +# 455, +# None, +# 456, +# None, +# 457, +# None, +# 458, +# None, +# 459, +# None, +# 460, +# None, +# 461, +# None, +# 462, +# None, +# 463, +# None, +# 464, +# None, +# 465, +# None, +# 466, +# None, +# 467, +# None, +# 468, +# None, +# 469, +# None, +# 470, +# None, +# 471, +# None, +# 472, +# None, +# 473, +# None, +# 474, +# None, +# 475, +# None, +# 476, +# None, +# 477, +# None, +# 478, +# None, +# 479, +# None, +# 480, +# None, +# 481, +# None, +# 482, +# None, +# 483, +# None, +# 484, +# None, +# 485, +# None, +# 486, +# None, +# 487, +# None, +# 488, +# None, +# 489, +# None, +# 490, +# None, +# 491, +# None, +# 492, +# None, +# 493, +# None, +# 494, +# None, +# 495, +# None, +# 496, +# None, +# 497, +# None, +# 498, +# None, +# 499, +# None, +# 500, +# None, +# 501, +# None, +# 502, +# None, +# 503, +# None, +# 504, +# None, +# 505, +# None, +# 506, +# None, +# 507, +# None, +# 508, +# None, +# 509, +# None, +# 510, +# None, +# 511, +# None, +# 512, +# None, +# 513, +# None, +# 514, +# None, +# 515, +# None, +# 516, +# None, +# 517, +# None, +# 518, +# None, +# 519, +# None, +# 520, +# None, +# 521, +# None, +# 522, +# None, +# 523, +# None, +# 524, +# None, +# 525, +# None, +# 526, +# None, +# 527, +# None, +# 528, +# None, +# 529, +# None, +# 530, +# None, +# 531, +# None, +# 532, +# None, +# 533, +# None, +# 534, +# None, +# 535, +# None, +# 536, +# None, +# 537, +# None, +# 538, +# None, +# 539, +# None, +# 540, +# None, +# 541, +# None, +# 542, +# None, +# 543, +# None, +# 544, +# None, +# 545, +# None, +# 546, +# None, +# 547, +# None, +# 548, +# None, +# 549, +# None, +# 550, +# None, +# 551, +# None, +# 552, +# None, +# 553, +# None, +# 554, +# None, +# 555, +# None, +# 556, +# None, +# 557, +# None, +# 558, +# None, +# 559, +# None, +# 560, +# None, +# 561, +# None, +# 562, +# None, +# 563, +# None, +# 564, +# None, +# 565, +# None, +# 566, +# None, +# 567, +# None, +# 568, +# None, +# 569, +# None, +# 570, +# None, +# 571, +# None, +# 572, +# None, +# 573, +# None, +# 574, +# None, +# 575, +# None, +# 576, +# None, +# 577, +# None, +# 578, +# None, +# 579, +# None, +# 580, +# None, +# 581, +# None, +# 582, +# None, +# 583, +# None, +# 584, +# None, +# 585, +# None, +# 586, +# None, +# 587, +# None, +# 588, +# None, +# 589, +# None, +# 590, +# None, +# 591, +# None, +# 592, +# None, +# 593, +# None, +# 594, +# None, +# 595, +# None, +# 596, +# None, +# 597, +# None, +# 598, +# None, +# 599, +# None, +# 600, +# None, +# 601, +# None, +# 602, +# None, +# 603, +# None, +# 604, +# None, +# 605, +# None, +# 606, +# None, +# 607, +# None, +# 608, +# None, +# 609, +# None, +# 610, +# None, +# 611, +# None, +# 612, +# None, +# 613, +# None, +# 614, +# None, +# 615, +# None, +# 616, +# None, +# 617, +# None, +# 618, +# None, +# 619, +# None, +# 620, +# None, +# 621, +# None, +# 622, +# None, +# 623, +# None, +# 624, +# None, +# 625, +# None, +# 626, +# None, +# 627, +# None, +# 628, +# None, +# 629, +# None, +# 630, +# None, +# 631, +# None, +# 632, +# None, +# 633, +# None, +# 634, +# None, +# 635, +# None, +# 636, +# None, +# 637, +# None, +# 638, +# None, +# 639, +# None, +# 640, +# None, +# 641, +# None, +# 642, +# None, +# 643, +# None, +# 644, +# None, +# 645, +# None, +# 646, +# None, +# 647, +# None, +# 648, +# None, +# 649, +# None, +# 650, +# None, +# 651, +# None, +# 652, +# None, +# 653, +# None, +# 654, +# None, +# 655, +# None, +# 656, +# None, +# 657, +# None, +# 658, +# None, +# 659, +# None, +# 660, +# None, +# 661, +# None, +# 662, +# None, +# 663, +# None, +# 664, +# None, +# 665, +# None, +# 666, +# None, +# 667, +# None, +# 668, +# None, +# 669, +# None, +# 670, +# None, +# 671, +# None, +# 672, +# None, +# 673, +# None, +# 674, +# None, +# 675, +# None, +# 676, +# None, +# 677, +# None, +# 678, +# None, +# 679, +# None, +# 680, +# None, +# 681, +# None, +# 682, +# None, +# 683, +# None, +# 684, +# None, +# 685, +# None, +# 686, +# None, +# 687, +# None, +# 688, +# None, +# 689, +# None, +# 690, +# None, +# 691, +# None, +# 692, +# None, +# 693, +# None, +# 694, +# None, +# 695, +# None, +# 696, +# None, +# 697, +# None, +# 698, +# None, +# 699, +# None, +# 700, +# None, +# 701, +# None, +# 702, +# None, +# 703, +# None, +# 704, +# None, +# 705, +# None, +# 706, +# None, +# 707, +# None, +# 708, +# None, +# 709, +# None, +# 710, +# None, +# 711, +# None, +# 712, +# None, +# 713, +# None, +# 714, +# None, +# 715, +# None, +# 716, +# None, +# 717, +# None, +# 718, +# None, +# 719, +# None, +# 720, +# None, +# 721, +# None, +# 722, +# None, +# 723, +# None, +# 724, +# None, +# 725, +# None, +# 726, +# None, +# 727, +# None, +# 728, +# None, +# 729, +# None, +# 730, +# None, +# 731, +# None, +# 732, +# None, +# 733, +# None, +# 734, +# None, +# 735, +# None, +# 736, +# None, +# 737, +# None, +# 738, +# None, +# 739, +# None, +# 740, +# None, +# 741, +# None, +# 742, +# None, +# 743, +# None, +# 744, +# None, +# 745, +# None, +# 746, +# None, +# 747, +# None, +# 748, +# None, +# 749, +# None, +# 750, +# None, +# 751, +# None, +# 752, +# None, +# 753, +# None, +# 754, +# None, +# 755, +# None, +# 756, +# None, +# 757, +# None, +# 758, +# None, +# 759, +# None, +# 760, +# None, +# 761, +# None, +# 762, +# None, +# 763, +# None, +# 764, +# None, +# 765, +# None, +# 766, +# None, +# 767, +# None, +# 768, +# None, +# 769, +# None, +# 770, +# None, +# 771, +# None, +# 772, +# None, +# 773, +# None, +# 774, +# None, +# 775, +# None, +# 776, +# None, +# 777, +# None, +# 778, +# None, +# 779, +# None, +# 780, +# None, +# 781, +# None, +# 782, +# None, +# 783, +# None, +# 784, +# None, +# 785, +# None, +# 786, +# None, +# 787, +# None, +# 788, +# None, +# 789, +# None, +# 790, +# None, +# 791, +# None, +# 792, +# None, +# 793, +# None, +# 794, +# None, +# 795, +# None, +# 796, +# None, +# 797, +# None, +# 798, +# None, +# 799, +# None, +# 800, +# None, +# 801, +# None, +# 802, +# None, +# 803, +# None, +# 804, +# None, +# 805, +# None, +# 806, +# None, +# 807, +# None, +# 808, +# None, +# 809, +# None, +# 810, +# None, +# 811, +# None, +# 812, +# None, +# 813, +# None, +# 814, +# None, +# 815, +# None, +# 816, +# None, +# 817, +# None, +# 818, +# None, +# 819, +# None, +# 820, +# None, +# 821, +# None, +# 822, +# None, +# 823, +# None, +# 824, +# None, +# 825, +# None, +# 826, +# None, +# 827, +# None, +# 828, +# None, +# 829, +# None, +# 830, +# None, +# 831, +# None, +# 832, +# None, +# 833, +# None, +# 834, +# None, +# 835, +# None, +# 836, +# None, +# 837, +# None, +# 838, +# None, +# 839, +# None, +# 840, +# None, +# 841, +# None, +# 842, +# None, +# 843, +# None, +# 844, +# None, +# 845, +# None, +# 846, +# None, +# 847, +# None, +# 848, +# None, +# 849, +# None, +# 850, +# None, +# 851, +# None, +# 852, +# None, +# 853, +# None, +# 854, +# None, +# 855, +# None, +# 856, +# None, +# 857, +# None, +# 858, +# None, +# 859, +# None, +# 860, +# None, +# 861, +# None, +# 862, +# None, +# 863, +# None, +# 864, +# None, +# 865, +# None, +# 866, +# None, +# 867, +# None, +# 868, +# None, +# 869, +# None, +# 870, +# None, +# 871, +# None, +# 872, +# None, +# 873, +# None, +# 874, +# None, +# 875, +# None, +# 876, +# None, +# 877, +# None, +# 878, +# None, +# 879, +# None, +# 880, +# None, +# 881, +# None, +# 882, +# None, +# 883, +# None, +# 884, +# None, +# 885, +# None, +# 886, +# None, +# 887, +# None, +# 888, +# None, +# 889, +# None, +# 890, +# None, +# 891, +# None, +# 892, +# None, +# 893, +# None, +# 894, +# None, +# 895, +# None, +# 896, +# None, +# 897, +# None, +# 898, +# None, +# 899, +# None, +# 900, +# None, +# 901, +# None, +# 902, +# None, +# 903, +# None, +# 904, +# None, +# 905, +# None, +# 906, +# None, +# 907, +# None, +# 908, +# None, +# 909, +# None, +# 910, +# None, +# 911, +# None, +# 912, +# None, +# 913, +# None, +# 914, +# None, +# 915, +# None, +# 916, +# None, +# 917, +# None, +# 918, +# None, +# 919, +# None, +# 920, +# None, +# 921, +# None, +# 922, +# None, +# 923, +# None, +# 924, +# None, +# 925, +# None, +# 926, +# None, +# 927, +# None, +# 928, +# None, +# 929, +# None, +# 930, +# None, +# 931, +# None, +# 932, +# None, +# 933, +# None, +# 934, +# None, +# 935, +# None, +# 936, +# None, +# 937, +# None, +# 938, +# None, +# 939, +# None, +# 940, +# None, +# 941, +# None, +# 942, +# None, +# 943, +# None, +# 944, +# None, +# 945, +# None, +# 946, +# None, +# 947, +# None, +# 948, +# None, +# 949, +# None, +# 950, +# None, +# 951, +# None, +# 952, +# None, +# 953, +# None, +# 954, +# None, +# 955, +# None, +# 956, +# None, +# 957, +# None, +# 958, +# None, +# 959, +# None, +# 960, +# None, +# 961, +# None, +# 962, +# None, +# 963, +# None, +# 964, +# None, +# 965, +# None, +# 966, +# None, +# 967, +# None, +# 968, +# None, +# 969, +# None, +# 970, +# None, +# 971, +# None, +# 972, +# None, +# 973, +# None, +# 974, +# None, +# 975, +# None, +# 976, +# None, +# 977, +# None, +# 978, +# None, +# 979, +# None, +# 980, +# None, +# 981, +# None, +# 982, +# None, +# 983, +# None, +# 984, +# None, +# 985, +# None, +# 986, +# None, +# 987, +# None, +# 988, +# None, +# 989, +# None, +# 990, +# None, +# 991, +# None, +# 992, +# None, +# 993, +# None, +# 994, +# None, +# 995, +# None, +# 996, +# None, +# 997, +# None, +# 998, +# None, +# 999, +# None, +# 1000 +# ]) diff --git a/Week_02/id_30/LeetCode_102_030.cpp b/Week_02/id_30/LeetCode_102_030.cpp new file mode 100644 index 00000000..e1ada201 --- /dev/null +++ b/Week_02/id_30/LeetCode_102_030.cpp @@ -0,0 +1,34 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +class Solution { +public: + vector> levelOrder(TreeNode* root) { + vector> results; + if (root == nullptr) return results; + queue nodeQueue; + nodeQueue.push(root); + while (!nodeQueue.empty()) + { + vector oneLevelResult; + int nodesCountInLevel = nodeQueue.size(); + while(nodesCountInLevel > 0) + { + TreeNode* node = nodeQueue.front(); + nodeQueue.pop(); + oneLevelResult.push_back(node->val); + if (node->left) nodeQueue.push(node->left); + if (node->right) nodeQueue.push(node->right); + --nodesCountInLevel; + } + results.push_back(oneLevelResult); + } + return results; + } +}; \ No newline at end of file diff --git a/Week_02/id_30/LeetCode_103_030.cpp b/Week_02/id_30/LeetCode_103_030.cpp new file mode 100644 index 00000000..2750c758 --- /dev/null +++ b/Week_02/id_30/LeetCode_103_030.cpp @@ -0,0 +1,45 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +class Solution { +public: + vector> zigzagLevelOrder(TreeNode* root) { + vector> results; + if (root == nullptr) return results; + stack s[2]; + int currentStack = 0; + int anotherStack = 1 - currentStack; + s[currentStack].push(root); + bool reverse = false; + do + { + vector oneLevelResult; + do + { + TreeNode* node = s[currentStack].top(); + s[currentStack].pop(); + oneLevelResult.push_back(node->val); + if (reverse) + { + if (node->right) s[anotherStack].push(node->right); + if (node->left) s[anotherStack].push(node->left); + } + else + { + if (node->left) s[anotherStack].push(node->left); + if (node->right) s[anotherStack].push(node->right); + } + }while (!s[currentStack].empty()); + results.push_back(oneLevelResult); + swap(currentStack, anotherStack); + reverse = !reverse; + } while (!s[currentStack].empty()); + return results; + } +}; \ No newline at end of file diff --git a/Week_02/id_30/LeetCode_220_030.cpp b/Week_02/id_30/LeetCode_220_030.cpp new file mode 100644 index 00000000..3f2c34f0 --- /dev/null +++ b/Week_02/id_30/LeetCode_220_030.cpp @@ -0,0 +1,20 @@ +class Solution { +public: + bool containsNearbyAlmostDuplicate(vector& nums, int k, int t) { + if (nums.size() <= 1) return false; + if (k <= 0 || t < 0) return false; + set kNums; + kNums.insert(nums[0]); + for (int i = 1; i < nums.size(); ++i) + { + set::iterator iter = kNums.lower_bound(static_cast(nums[i]) - t); + if (iter != kNums.end() && abs(*iter - nums[i]) <= t) return true; + kNums.insert(nums[i]); + if (kNums.size() == k + 1) + { + kNums.erase(nums[i - k]); + } + } + return false; + } +}; \ No newline at end of file diff --git a/Week_02/id_30/LeetCode_3_030.cpp b/Week_02/id_30/LeetCode_3_030.cpp new file mode 100644 index 00000000..9346c4b4 --- /dev/null +++ b/Week_02/id_30/LeetCode_3_030.cpp @@ -0,0 +1,28 @@ +class Solution { +public: + int lengthOfLongestSubstring(string s) { + unordered_map lettersIndexMap; + int startIndex = 0, endIndex = 0; + int maxLength = 0; + while(endIndex < s.size()) + { + char c = s[endIndex]; + auto lettersIndexIter = lettersIndexMap.find(c); + if (lettersIndexIter != lettersIndexMap.end()) + { + maxLength = max(maxLength, endIndex - startIndex); + int letterIndex = lettersIndexIter->second; + if (letterIndex >= s.size() - maxLength - 1) break; + for (int j = startIndex; j <= letterIndex - 1; ++j) + { + lettersIndexMap.erase(s[j]); + } + startIndex = letterIndex + 1; + } + lettersIndexMap[c] = endIndex; + ++endIndex; + } + maxLength = max(maxLength, endIndex - startIndex); + return maxLength; + } +}; \ No newline at end of file diff --git a/Week_02/id_30/LeetCode_692_030.cpp b/Week_02/id_30/LeetCode_692_030.cpp new file mode 100644 index 00000000..7b928e52 --- /dev/null +++ b/Week_02/id_30/LeetCode_692_030.cpp @@ -0,0 +1,25 @@ +class Solution { +public: + vector topKFrequent(vector& words, int k) { + vector topKFrequent(vector& words, int k) { + unordered_map wordsFreqCountMap; + for (const string& w : words) + { + ++wordsFreqCountMap[w]; + } + auto WordsComparer = [](const pair& p1, const pair& p2) + { + if (p1.second != p2.second) return p1.second < p2.second; + else return p1.first.compare(p2.first) > 0; + }; + priority_queue, vector>, decltype(WordsComparer)> wordsQueue(wordsFreqCountMap.begin(), wordsFreqCountMap.end(), WordsComparer); + vector results; + for (int i = 0; i < k; ++i) + { + results.push_back(wordsQueue.top().first); + wordsQueue.pop(); + } + return results; + } + } +}; \ No newline at end of file diff --git a/Week_02/id_30/LeetCode_726_030.cpp b/Week_02/id_30/LeetCode_726_030.cpp new file mode 100644 index 00000000..08f3cc25 --- /dev/null +++ b/Week_02/id_30/LeetCode_726_030.cpp @@ -0,0 +1,102 @@ +class Solution { +public: + map atomsCountMap; + + void insertOrUpdateAtomsCountMap(const pair& p) + { + auto iter = atomsCountMap.find(p.first); + if (iter != atomsCountMap.end()) + { + iter->second += p.second; + } + else + { + atomsCountMap.insert(p); + } + } + + int parseNumber(const string& formula, int startIndex, int& endIndex) + { + if (!isdigit(formula[startIndex])) + { + endIndex = startIndex - 1; + return 1; + } + int i = startIndex + 1; + while (isdigit(formula[i])) ++i; + string numStr = formula.substr(startIndex, i - startIndex); + endIndex = i - 1; + return stoi(numStr); + } + + string countOfAtoms(string formula) { + stack> parenthesesStack; + for (int i = 0; i < formula.size(); ++i) + { + char c = formula[i]; + if (isupper(c)) + { + int strParseStartIndex = i; + while (islower(formula[i + 1])) ++i; + string atomName = formula.substr(strParseStartIndex, i - strParseStartIndex + 1); + int count = parseNumber(formula, i + 1, i); + if (parenthesesStack.empty()) + { + insertOrUpdateAtomsCountMap(make_pair(atomName, count)); + } + else + { + parenthesesStack.push(make_pair(atomName, count)); + } + } + else if (c == '(') + { + parenthesesStack.push(make_pair("(", 0)); + } + else if (c == ')') + { + int multiplier = parseNumber(formula, i + 1, i); + stack> multiplierStack; + while (!parenthesesStack.empty()) + { + pair namePair = parenthesesStack.top(); + parenthesesStack.pop(); + if (namePair.first == "(") + { + if (parenthesesStack.empty()) + { + while (!multiplierStack.empty()) + { + pair mPair = multiplierStack.top(); + multiplierStack.pop(); + insertOrUpdateAtomsCountMap(mPair); + } + } + else + { + while (!multiplierStack.empty()) + { + parenthesesStack.push(multiplierStack.top()); + multiplierStack.pop(); + } + } + break; + } + else + { + namePair.second *= multiplier; + multiplierStack.push(namePair); + } + } + } + } + + string elements; + for (pair p : atomsCountMap) + { + elements += p.first; + if (p.second > 1) elements += to_string(p.second); + } + return elements; + } +}; \ No newline at end of file diff --git a/Week_02/id_30/LeetCode_98_030.cpp b/Week_02/id_30/LeetCode_98_030.cpp new file mode 100644 index 00000000..f346a40a --- /dev/null +++ b/Week_02/id_30/LeetCode_98_030.cpp @@ -0,0 +1,23 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +class Solution { +public: + bool isValidBST(TreeNode* root) { + return isValidBST(root, nullptr, nullptr); + } + + bool isValidBST(TreeNode* root, TreeNode* minValueNode, TreeNode* maxValueNode) + { + if (root == nullptr) return true; + if (minValueNode && root->val <= minValueNode->val) return false; + if (maxValueNode && root->val >= maxValueNode->val) return false; + return isValidBST(root->left, minValueNode, root) && isValidBST(root->right, root, maxValueNode); + } +}; \ No newline at end of file diff --git "a/Week_02/id_32/1. \344\270\244\346\225\260\344\271\213\345\222\214.py" "b/Week_02/id_32/1. \344\270\244\346\225\260\344\271\213\345\222\214.py" new file mode 100644 index 00000000..8f022f65 --- /dev/null +++ "b/Week_02/id_32/1. \344\270\244\346\225\260\344\271\213\345\222\214.py" @@ -0,0 +1,8 @@ +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + m = {} + for index, value in enumerate(nums): + if target-value in m: + return m[target-value],index + m[value] = index + return "no" \ No newline at end of file diff --git "a/Week_02/id_32/242. \346\234\211\346\225\210\347\232\204\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215.py" "b/Week_02/id_32/242. \346\234\211\346\225\210\347\232\204\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215.py" new file mode 100644 index 00000000..bb8fcca2 --- /dev/null +++ "b/Week_02/id_32/242. \346\234\211\346\225\210\347\232\204\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215.py" @@ -0,0 +1,18 @@ +class Solution: + def isAnagram(self, s: str, t: str) -> bool: + m = {} + for i in s: + if i not in m: + m[i] = 1 + else: + m[i] += 1 + for i in t: + if i not in m: + return False + else: + m[i] -= 1 + for i in m.values(): + if i != 0: + return False + return True + \ No newline at end of file diff --git a/Week_02/id_33/Leetcode_111_33.java b/Week_02/id_33/Leetcode_111_33.java new file mode 100644 index 00000000..4b30b8ba --- /dev/null +++ b/Week_02/id_33/Leetcode_111_33.java @@ -0,0 +1,28 @@ +/* + * @lc app=leetcode id=111 lang=java + * + * [111] Minimum Depth of Binary Tree + */ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +class Solution { + public int minDepth(TreeNode root) { + if(root == null) + return 0; + if(root.left == null && root.right == null) + return 1; + if(root.left == null) + return minDepth(root.right) + 1; + if(root.right == null) + return minDepth(root.left) + 1; + return Math.min(minDepth(root.left), minDepth(root.right)) + 1; + } +} + diff --git a/Week_02/id_33/Leetcode_1_33.java b/Week_02/id_33/Leetcode_1_33.java new file mode 100644 index 00000000..31db9c58 --- /dev/null +++ b/Week_02/id_33/Leetcode_1_33.java @@ -0,0 +1,21 @@ +/* + * @lc app=leetcode id=1 lang=java + * + * [1] Two Sum + */ +class Solution { + public int[] twoSum(int[] nums, int target) { + Map map = new HashMap<>(); + if (nums != null && nums.length > 0) { + for (int i = 0; i < nums.length; i++) { + int result = target - nums[i]; + if (map.containsKey(result)) { + return new int[]{map.get(result), i}; + } + map.put(nums[i], i); + } + } + return new int[]{}; + } +} + diff --git a/Week_02/id_33/Leetcode_3_33.java b/Week_02/id_33/Leetcode_3_33.java new file mode 100644 index 00000000..259adc27 --- /dev/null +++ b/Week_02/id_33/Leetcode_3_33.java @@ -0,0 +1,23 @@ + + +/* + * @lc app=leetcode id=3 lang=java + * + * [3] Longest Substring Without Repeating Characters + */ +class Solution { + public int lengthOfLongestSubstring(String s) { + int maxStr = 0; + Map map = new HashMap<>(); + int temp = 0; + for(int i = 0;i < s.length(); i++){ + if(map.containsKey(s.charAt(i))){ + temp = Math.max(map.get(s.charAt(i)), temp); + } + maxStr = Math.max(maxStr, i-temp+1); + map.put(s.charAt(i),i+1); + } + return maxStr; + } +} + diff --git a/Week_02/id_33/Leetcode_98_33.java b/Week_02/id_33/Leetcode_98_33.java new file mode 100644 index 00000000..334249e6 --- /dev/null +++ b/Week_02/id_33/Leetcode_98_33.java @@ -0,0 +1,28 @@ +/* + * @lc app=leetcode id=98 lang=java + * + * [98] Validate Binary Search Tree + */ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +class Solution { + public boolean isValidBST(TreeNode root) { + return isBST(root, Long.MIN_VALUE, Long.MAX_VALUE); + } + + public boolean isBST(TreeNode root, long min, long max) { + if (root == null) + return true; + if (root.val <= min || root.val >= max) + return false; + return isBST(root.left, min, root.val) && isBST(root.right, root.val, max); + } +} + diff --git a/Week_02/id_35/LeetCode_03_35.java b/Week_02/id_35/LeetCode_03_35.java new file mode 100644 index 00000000..9187802a --- /dev/null +++ b/Week_02/id_35/LeetCode_03_35.java @@ -0,0 +1,131 @@ +package com.leecode.week02; + +import com.sun.org.apache.xpath.internal.operations.Bool; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/ + * 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。 + */ +public class LeetCode_03_35 { + public void printAllSubstring(String s){ + char[] chs=s.toCharArray(); + for(int i=0;i set=new HashSet<>(); + for(int i=0;i set=new HashSet<>(); + for(int i=0;i cache=new HashMap<>(); + public boolean hasRepeatingChar(String s){ + + if(cache.containsKey(s)){ + return cache.get(s); + } + + char[] chs=s.toCharArray(); + Set characters=new HashSet<>(); + for (char ch:chs) { + if(characters.contains(ch)){ + cache.put(s,true); + return true; + }else { + characters.add(ch); + } + + } + cache.put(s,false); + return false; + }*/ +} diff --git a/Week_02/id_35/LeetCode_242_35.java b/Week_02/id_35/LeetCode_242_35.java new file mode 100644 index 00000000..ff02a35a --- /dev/null +++ b/Week_02/id_35/LeetCode_242_35.java @@ -0,0 +1,73 @@ +package com.leecode.week02; + +import java.util.Arrays; + +/** + * 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 + * 输入: s = "anagram", t = "nagaram" + * 输出: true + */ +public class LeetCode_242_35 { + public static void main(String[] args) { + LeetCode_242_35 lc=new LeetCode_242_35(); + System.out.println(lc.isAnagram("anagram","nagaram")); + + System.out.println(lc.isAnagram("rat","art")); + System.out.println(lc.isAnagram("rat"," car")); + //Arrays.equals("anagram".toCharArray(),"nagaram".toCharArray()); + } + + public boolean isAnagram(String s, String t) + { + if(s==null||t==null||s.length()!=t.length()){ + return false; + } + int[] sArr=new int[128]; + int[] tArr=new int[128]; + char[] sChs=s.toCharArray(); + char[] tChs=t.toCharArray(); + + for(int i=0;i cache=new HashMap<>(); + + for (int i=0;i bool: +# return self.isMirror(root, root) + +# def isMirror(self, root1: TreeNode, root2: TreeNode) -> bool: +# if root1 is None and root2 is None: +# return True +# if root1 is None or root2 is None: +# return False + +# return root1.val == root2.val and self.isMirror(root1.right, root2.left) and self.isMirror(root1.left, root2.right) + +# 迭代 +class Solution: + def isSymmetric(self, root: TreeNode) -> bool: + queue = [] + queue.append(root) + queue.append(root) + + while len(queue) > 0: + t1 = queue.pop() + t2 = queue.pop() + if t1 is None and t2 is None: + continue + if t1 is None or t2 is None: + return False + if t1.val != t2.val: + return False + + queue.append(t1.left) + queue.append(t2.right) + queue.append(t1.right) + queue.append(t2.left) + + return True + diff --git a/Week_02/id_36/LeetCode_111_36.py b/Week_02/id_36/LeetCode_111_36.py new file mode 100644 index 00000000..d822615b --- /dev/null +++ b/Week_02/id_36/LeetCode_111_36.py @@ -0,0 +1,73 @@ +# +# @lc app=leetcode.cn id=111 lang=python3 +# +# [111] 二叉树的最小深度 +# +# Definition for a binary tree node. + + +class TreeNode: + def __init__(self, x): + self.val = x + self.left = None + self.right = None + + +# #递归 +# class Solution: +# def minDepth(self, root: TreeNode) -> int: +# if root is None: +# return 0 + +# if root.left is None and root.right is not None: +# return self.minDepth(root.right) + 1 +# elif root.left is not None and root.right is None: +# return self.minDepth(root.left) + 1 + +# return min(self.minDepth(root.left), self.minDepth(root.right)) + 1 + +# #深度优先搜索迭代 +# class Solution: +# def minDepth(self, root: TreeNode) -> int: +# if root is None: +# return 0 + +# stack = [] +# import sys +# stack.append((root, 1)) +# min_depth = sys.maxsize +# while len(stack) > 0: +# current = stack.pop() +# root = current[0] +# current_depth = current[1] +# if root.left is None and root.right is None: +# min_depth = min(min_depth, current_depth) +# if root.left is not None: +# stack.append((root.left, current_depth + 1)) +# if root.right is not None: +# stack.append((root.right, current_depth + 1)) + +# return min_depth + +#宽度优先搜索迭代 +class Solution: + def minDepth(self, root: TreeNode) -> int: + if root is None: + return 0 + + stack = [] + stack.append((root, 1)) + current_depth = 0 + while len(stack) > 0: + current = stack.pop() + root = current[0] + current_depth = current[1] + if root.left is None and root.right is None: + break + if root.left is not None: + stack.insert(0, (root.left, current_depth + 1)) + if root.right is not None: + stack.insert(0, (root.right, current_depth + 1)) + + return current_depth + diff --git a/Week_02/id_36/LeetCode_1_36.py b/Week_02/id_36/LeetCode_1_36.py new file mode 100644 index 00000000..787695c3 --- /dev/null +++ b/Week_02/id_36/LeetCode_1_36.py @@ -0,0 +1,62 @@ +# +# @lc app=leetcode.cn id=1 lang=python3 +# +# [1] 两数之和 +# +# https://leetcode-cn.com/problems/two-sum/description/ +# +# algorithms +# Easy (46.08%) +# Likes: 5365 +# Dislikes: 0 +# Total Accepted: 397.2K +# Total Submissions: 861.4K +# Testcase Example: '[2,7,11,15]\n9' +# +# 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 +# +# 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 +# +# 示例: +# +# 给定 nums = [2, 7, 11, 15], target = 9 +# +# 因为 nums[0] + nums[1] = 2 + 7 = 9 +# 所以返回 [0, 1] +# +# +# 暴力解法: +# class Solution: +# def twoSum(self, nums: List[int], target: int) -> List[int]: +# l = len(nums) +# for i in range(l): +# for j in range(i + 1, l): +# if nums[j] == target - nums[i]: +# return [i, j] +# return [] +# +# 两遍哈希表 +# class Solution: +# def twoSum(self, nums: List[int], target: int) -> List[int]: +# map = dict() +# l = len(nums) +# for i in range(l): +# map[nums[i]] = i +# for i in range(l): +# r = target - nums[i] +# if map.get(r, i) != i: +# return [i, map.get(r)] +# return [] +# +# 一遍哈希表 +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + map = dict() + l = len(nums) + for i in range(l): + r = target - nums[i] + if map.get(r, i) != i: + return [map.get(r), i] + map[nums[i]] = i + return [] + diff --git a/Week_02/id_36/LeetCode_236_36.py b/Week_02/id_36/LeetCode_236_36.py new file mode 100644 index 00000000..6c8225ac --- /dev/null +++ b/Week_02/id_36/LeetCode_236_36.py @@ -0,0 +1,77 @@ +# +# @lc app=leetcode.cn id=236 lang=python3 +# +# [236] 二叉树的最近公共祖先 +# +# https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/description/ +# +# algorithms +# Medium (55.09%) +# Likes: 183 +# Dislikes: 0 +# Total Accepted: 15K +# Total Submissions: 27.3K +# Testcase Example: '[3,5,1,6,2,0,8,null,null,7,4]\n5\n1' +# +# 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 +# +# 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x +# 的深度尽可能大(一个节点也可以是它自己的祖先)。” +# +# 例如,给定如下二叉树:  root = [3,5,1,6,2,0,8,null,null,7,4] +# +# +# +# +# +# 示例 1: +# +# 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 +# 输出: 3 +# 解释: 节点 5 和节点 1 的最近公共祖先是节点 3。 +# +# +# 示例 2: +# +# 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 +# 输出: 5 +# 解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。 +# +# +# +# +# 说明: +# +# +# 所有节点的值都是唯一的。 +# p、q 为不同节点且均存在于给定的二叉树中。 +# +# +# +# Definition for a binary tree node. + + +class TreeNode: + def __init__(self, x): + self.val = x + self.left = None + self.right = None + + +class Solution: + def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': + if root == p or root == q or root is None: + return root + + left = self.lowestCommonAncestor(root.left, p, q) + right = self.lowestCommonAncestor(root.right, p, q) + + if left is None and right is None: + return None + elif left is not None and right is None: + return left + elif left is None and right is not None: + return right + + return root + diff --git a/Week_02/id_36/LeetCode_3_36.py b/Week_02/id_36/LeetCode_3_36.py new file mode 100644 index 00000000..670c7668 --- /dev/null +++ b/Week_02/id_36/LeetCode_3_36.py @@ -0,0 +1,77 @@ +# +# @lc app=leetcode.cn id=3 lang=python3 +# +# [3] 无重复字符的最长子串 +# +# https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/description/ +# +# algorithms +# Medium (29.74%) +# Likes: 1907 +# Dislikes: 0 +# Total Accepted: 136.6K +# Total Submissions: 457.9K +# Testcase Example: '"abcabcbb"' +# +# 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。 +# +# 示例 1: +# +# 输入: "abcabcbb" +# 输出: 3 +# 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 +# +# +# 示例 2: +# +# 输入: "bbbbb" +# 输出: 1 +# 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。 +# +# +# 示例 3: +# +# 输入: "pwwkew" +# 输出: 3 +# 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 +# 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。 +# +# +# +# class Solution: +# def lengthOfLongestSubstring(self, s: str) -> int: +# n = len(s) +# ans = 0 + +# for i in range(n): +# for j in range(i + 1, n + 1): +# if self.allUnique(s, i, j): +# ans = max(ans, j - i) + +# return ans + +# def allUnique(self, s, start, end): +# set_v = set() +# for i in range(start, end): +# ch = s[i] +# if ch in set_v: +# return False +# set_v.add(ch) + +# return True + + +class Solution: + def lengthOfLongestSubstring(self, s: str) -> int: + n = len(s) + ans = 0 + start = 0 + dict_v = dict() + for end in range(n): + ch = s[end] + if dict_v.get(ch, None): + start = max(dict_v.get(ch), start) + ans = max(ans, end - start + 1) + dict_v[ch] = end + 1 + + return ans diff --git a/Week_02/id_37/NOTE.md b/Week_02/id_37/NOTE.md index 107ea7d6..d98c5355 100644 --- a/Week_02/id_37/NOTE.md +++ b/Week_02/id_37/NOTE.md @@ -1 +1,18 @@ # 学习笔记 +## 关于递归的心得 +定义清楚递归函数的功能 +注意递归的终止条件 +回溯法是暴力解法(除非剪枝) +递归是算法结构,回溯是算法思想 +回溯用于搜索所有的可能性,如果使用循环无法解决(比如不知道几重循环),那么就可以用回溯 + +## 二叉树与散列表的对比 +二叉查找树要求,在树中的任意一个节点,其左子树中的每个节点的值,都要小于这个节点的值,而右子树节点的值都大于这个节点的值。 + +二叉查找树与散列表的对比: +我们在散列表那节中讲过,散列表的插入、删除、查找操作的时间复杂度可以做到常量级的 O(1),非常高效。而二叉查找树在比较平衡的情况下,插入、删除、查找操作时间复杂度才是 O(logn) +- 第一,散列表中的数据是无序存储的,如果要输出有序的数据,需要先进行排序。而对于二叉查找树来说,我们只需要中序遍历,就可以在 O(n) 的时间复杂度内,输出有序的数据序列。 +- 第二,散列表扩容耗时很多,而且当遇到散列冲突时,性能不稳定,尽管二叉查找树的性能不稳定,但是在工程中,我们最常用的平衡二叉查找树的性能非常稳定,时间复杂度稳定在 O(logn)。 +- 第三,笼统地来说,尽管散列表的查找等操作的时间复杂度是常量级的,但因为哈希冲突的存在,这个常量不一定比 logn 小,所以实际的查找速度可能不一定比 O(logn) 快。加上哈希函数的耗时,也不一定就比平衡二叉查找树的效率高。 +- 第四,散列表的构造比二叉查找树要复杂,需要考虑的东西很多。比如散列函数的设计、冲突解决办法、扩容、缩容等。平衡二叉查找树只需要考虑平衡性这一个问题,而且这个问题的解决方案比较成熟、固定。 +- 最后,为了避免过多的散列冲突,散列表装载因子不能太大,特别是基于开放寻址法解决冲突的散列表,不然会浪费一定的存储空间。 diff --git "a/Week_02/id_37/\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221/LeetCode_783_037.java" "b/Week_02/id_37/\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221/LeetCode_783_037.java" new file mode 100644 index 00000000..ab97e8eb --- /dev/null +++ "b/Week_02/id_37/\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221/LeetCode_783_037.java" @@ -0,0 +1,29 @@ +class Solution { + private int min=Integer.MAX_VALUE; + public int minDiffInBST(TreeNode root) { + + dfs(root); + return min; + } + + private void dfs(TreeNode root){ + if(root==null){ + return; + } + int m=root.val; + if(root.left!=null){ + int diff=m-root.left.val; + if(diff ap=new ArrayList<>(); + List aq=new ArrayList<>(); + findAncestors(root,p,ap); + findAncestors(root,q,aq); + TreeNode common=null; + for(TreeNode a1:ap){ + for(TreeNode a2:aq){ + if(a1==a2){ + common=a1; + } + } + } + return common; + } + + public boolean findAncestors(TreeNode root,TreeNode target,List ans){ + if(root==null){ + return false; + } + if(root==target){ + ans.add(root); + return true; + } + + ans.add(root); + boolean leftFind=findAncestors(root.left,target,ans); + if(!leftFind){ + ans.remove(root.left); + } + boolean rightFind=findAncestors(root.right,target,ans); + if(!rightFind){ + ans.remove(root.right); + } + if(leftFind||rightFind){ + return true; + } + return false; + + } +} \ No newline at end of file diff --git "a/Week_02/id_37/\345\223\210\345\270\214\350\241\250/LeetCode_1_037.java" "b/Week_02/id_37/\345\223\210\345\270\214\350\241\250/LeetCode_1_037.java" new file mode 100644 index 00000000..a0b75147 --- /dev/null +++ "b/Week_02/id_37/\345\223\210\345\270\214\350\241\250/LeetCode_1_037.java" @@ -0,0 +1,12 @@ +class Solution { + public int[] twoSum(int[] nums, int target) { + Map waitMap=new HashMap<>();//{以等待的值为key,i} + for(int i=0;i set = new HashSet<>(); + while(l numDic = new HashMap(); + // push and process + for (int i = 0; i < nums.length; ++i) { + if (numDic.containsKey(target - nums[i]) + && numDic.get(target - nums[i]) != i) { + return new int[]{numDic.get(target - nums[i]), i}; + } + numDic.put(nums[i], i); + } + + throw new IllegalArgumentException("No two sum solution"); + } + + public int[] twoSum1(int[] nums, int target) { + // hashmap, 时间 O(2n),空间 O(n) + Map numDic = new HashMap(); + // push + for (int i = 0; i < nums.length; ++i) { + numDic.put(nums[i], i); + } + + for (int i = 0; i < nums.length; ++i) { + if (numDic.containsKey(target - nums[i]) + && numDic.get(target - nums[i]) != i) { + return new int[]{i, numDic.get(target - nums[i])}; + } + } + + throw new IllegalArgumentException("No two sum solution"); + } + + public int[] twoSum2(int[] nums, int target) { + // check valid + + // 暴力,时间 O(n^2),空间 O(1) + for (int i = 0; i < nums.length - 1; ++i) { + for (int j = i + 1; j < nums.length; ++j) { + if (nums[i] + nums[j] == target) { + return new int[]{i, j}; + } + } + } + + throw new IllegalArgumentException("No two sum solution"); + } + + public static void main(String[] args) { + LeetCode_01_038 testCode_01_038 = new LeetCode_01_038(); + int[] nums = new int[]{-1}; + int[] result = testCode_01_038.twoSum2(nums, 3); + for (int i = 0; i < result.length; ++i) { + System.out.print(result[i] + ","); + } + } +} + diff --git a/Week_02/id_38/LeetCode_111_038.java b/Week_02/id_38/LeetCode_111_038.java new file mode 100644 index 00000000..5871e376 --- /dev/null +++ b/Week_02/id_38/LeetCode_111_038.java @@ -0,0 +1,26 @@ +import java.util.*; + +/* + * @lc app=leetcode.cn id=111 lang=java + * + * [111] 二叉树的最小深度 + */ +class LeetCode_111_038 { + public int minDepth(TreeNode root) { + if (root == null) return 0; + if ((root.l == null) && (root.r == null)) return 1; + if (root.l == null) return minDepth(root.r) + 1; + if (root.r == null) return minDepth(root.l) + 1; + return Math.min(minDepth(root.l), minDepth(root.r)) + 1; + } +} + +class TreeNode { + int val; + TreeNode l; + TreeNode r; + TreeNode(int x) { + this.val = x; + } +} + diff --git a/Week_02/id_38/LeetCode_242_038.java b/Week_02/id_38/LeetCode_242_038.java new file mode 100644 index 00000000..fdec858b --- /dev/null +++ b/Week_02/id_38/LeetCode_242_038.java @@ -0,0 +1,81 @@ +import java.util.Arrays; +import java.util.List; + +/* + * @lc app=leetcode.cn id=242 lang=java + * + * [242] 有效的字母异位词 + */ +class LeetCode_242_038 { + + /** + * hash + * 执行用时:11ms,内存消耗:38.2mb + * 时间:O(n), 空间:O(1),n为字符串长度 + * @param s + * @param t + * @return + */ + public boolean isAnagram(String s, String t) { + // check valid + if (equals(s, t)) return true; + if (length(s) != length(t)) return false; + + int[] charArr = new int[26]; + for (int i = 0; i < s.length(); ++i) { + charArr[s.charAt(i) - 'a']++; + charArr[t.charAt(i) - 'a']--; + } + + for (int i : charArr) { + if (i != 0) return false; + } + return true; + } + + /** + * 将两string排序,然后判断是否相同 + * 执行用时:317ms,内存消耗:58.2mb + * -。- + * 自行实现的算法效率正是低,代码也一大坨 + * @param s + * @param t + * @return + */ + public boolean isAnagram2(String s, String t) { + if (equals(s, t)) return true; + if (length(s) != length(t)) return false; + + return equals(stringSort(s), stringSort(t)); + } + + public String stringSort(String s) { + if (isEmpty(s)) return s; + String[] sa = s.split(""); + Arrays.sort(sa); + System.out.println(String.join("", sa)); + return String.join("", sa); + } + + public boolean isEmpty(String s) { + if (s == null || s.length() == 0) return true; + return false; + } + + public boolean equals(String s, String t) { + if (isEmpty(s) && isEmpty(t)) return true; + if (!isEmpty(s) && s.equals(t)) return true; + return false; + } + + public int length(String s) { + if (isEmpty(s)) return 0; + return s.length(); + } + + public static void main(String[] args) { + LeetCode_242_038 testCode_242_038 = new LeetCode_242_038(); + System.out.print(testCode_242_038.isAnagram("ab", "ba")); + } +} + diff --git a/Week_02/id_38/README.md b/Week_02/id_38/README.md new file mode 100644 index 00000000..7f497f14 --- /dev/null +++ b/Week_02/id_38/README.md @@ -0,0 +1,48 @@ +# 学习笔记 + +## 第二周题目 +--- +### 哈希表 +* [x] 【简单】[1. 两数之和 ](https://leetcode-cn.com/problems/two-sum/) + +* [ ] 【简单】[242. 有效的字母异位词](https://leetcode-cn.com/problems/valid-anagram/) + +* [ ] 【中等】[3. 无重复字符的最长子串](https://leetcode-cn.com/problems/longest-substring-without-repeating-characters) + +* [ ] 【中等】[692. 前K个高频单词](https://leetcode-cn.com/problems/top-k-frequent-words) + +* [ ] 【困难】[726. 原子的数量](https://leetcode-cn.com/problems/number-of-atoms/) + +--- + +### 二叉树 +* [ ] [111. 二叉树的最小深度【简单】](https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/) + +* [ ] [236. 二叉树的最近公共祖先【中等】](https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/) + +* [ ] [101. 对称二叉树【简单】](https://leetcode-cn.com/problems/symmetric-tree/) + +* [ ] [103. 二叉树的锯齿形层次遍历【中等】](https://leetcode-cn.com/problems/binary-tree-zigzag-level-order-traversal/) + +* [ ] [102. 二叉树的层次遍历【中等】](https://leetcode-cn.com/problems/binary-tree-level-order-traversal/) + +* [ ] [297. 二叉树的序列化与反序列化【困难】](https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree/) + + +--- + +### 二叉搜索树 +* [ ] [783. 二叉搜索树结点最小距离【简单】](https://leetcode-cn.com/problems/minimum-distance-between-bst-nodes/) + +* [ ] [235. 二叉搜索树的最近公共祖先【简单】](https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree/) + +* [ ] [98. 验证二叉搜索树【中等】](https://leetcode-cn.com/problems/validate-binary-search-tree/) + +* [ ] [938. 二叉搜索树的范围和【中等】](https://leetcode-cn.com/problems/range-sum-of-bst/) + +* [ ] [220. 存在重复元素 III【中等】](https://leetcode-cn.com/problems/contains-duplicate-iii/) + +* [ ] [315. 计算右侧小于当前元素的个数【困难】](https://leetcode-cn.com/problems/count-of-smaller-numbers-after-self/) + + +--- \ No newline at end of file diff --git a/Week_02/id_39/LeetCode_1_39.js b/Week_02/id_39/LeetCode_1_39.js new file mode 100644 index 00000000..c9a18b04 --- /dev/null +++ b/Week_02/id_39/LeetCode_1_39.js @@ -0,0 +1,17 @@ +/** + * @param {number[]} nums + * @param {number} target + * @return {number[]} + * https://leetcode.com/problems/two-sum/ + */ +var twoSum = function(nums, target) { + let hashTable = []; + for (let i = 0; i < nums.length; i++) { + let other = target - nums[i]; + if (hashTable[other] >= 0) { + return [hashTable[other], i]; + }; + hashTable[nums[i]] = i; + } + return null; +}; \ No newline at end of file diff --git a/Week_02/id_39/LeetCode_242_39.js b/Week_02/id_39/LeetCode_242_39.js new file mode 100644 index 00000000..559310ef --- /dev/null +++ b/Week_02/id_39/LeetCode_242_39.js @@ -0,0 +1,30 @@ +/** + * @param {string} s + * @param {string} t + * @return {boolean} + * https://leetcode.com/problems/valid-anagram/ + */ +var isAnagram = function(s, t) { + if (s.length !== t.length) { + return false; + } + let sArr = s.split(''); + let tArr = t.split(''); + let map = {}; + + for (let i = 0; i < sArr.length; i++) { + if (!map[sArr[i]]) { + map[sArr[i]] = 1; + } else { + map[sArr[i]]++; + } + } + + for (let i = 0; i < tArr.length; i++) { + if (!map[tArr[i]] || map[tArr[i]] <= 0) { + return false; + } + map[tArr[i]]--; + } + return true; +}; \ No newline at end of file diff --git a/Week_02/id_39/LeetCode_3_39.js b/Week_02/id_39/LeetCode_3_39.js new file mode 100644 index 00000000..b662e914 --- /dev/null +++ b/Week_02/id_39/LeetCode_3_39.js @@ -0,0 +1,20 @@ +/** + * @param {string} s + * @return {number} + * https://leetcode.com/problems/longest-substring-without-repeating-characters/ + */ +var lengthOfLongestSubstring = function(s) { + let sArr = s.split(''); + let max = 0; + let map = {}; + let left = 0; + for (let i = 0; i < sArr.length; i++) { + if (map[sArr[i]] != null) { + left = Math.max(left, map[sArr[i]] + 1); + } + map[sArr[i]] = i; + max = Math.max(max, i - left + 1); + } + + return max; +}; \ No newline at end of file diff --git a/Week_02/id_40/LeetCode_101_40.cpp b/Week_02/id_40/LeetCode_101_40.cpp new file mode 100644 index 00000000..2c0f99bd --- /dev/null +++ b/Week_02/id_40/LeetCode_101_40.cpp @@ -0,0 +1,34 @@ +/* + * @lc app=leetcode id=101 lang=cpp + * + * [101] Symmetric Tree + */ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +class Solution { +public: + bool isSymmetric(TreeNode* root) { + return isMirror(root, root); + } + + + + + bool isMirror(TreeNode* t1, TreeNode* t2) + { + if (t1 == NULL && t2 == NULL) + return true; + if (t1 == NULL || t2 == NULL) + return false; + return (t1->val == t2->val) && isMirror(t1->right, t2->left) && isMirror(t1->left, t2->right); + } + +}; + diff --git a/Week_02/id_40/LeetCode_102_40.cpp b/Week_02/id_40/LeetCode_102_40.cpp new file mode 100644 index 00000000..6a240896 --- /dev/null +++ b/Week_02/id_40/LeetCode_102_40.cpp @@ -0,0 +1,32 @@ +/* + * @lc app=leetcode id=102 lang=cpp + * + * [102] Binary Tree Level Order Traversal + */ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +class Solution { +public: + vector> levelOrder(TreeNode* root) { + vector> ans; + pre(root, 0, ans); + return ans; + } + + void pre(TreeNode *root, int depth, vector> &ans) { + if (!root) return ; + if (depth >= ans.size()) + ans.push_back(vector {}); + ans[depth].push_back(root->val); + pre(root->left, depth + 1, ans); + pre(root->right, depth + 1, ans); + } +}; + diff --git a/Week_02/id_40/LeetCode_3_40.cpp b/Week_02/id_40/LeetCode_3_40.cpp new file mode 100644 index 00000000..6f970466 --- /dev/null +++ b/Week_02/id_40/LeetCode_3_40.cpp @@ -0,0 +1,27 @@ +/* + * @lc app=leetcode id=3 lang=cpp + * + * [3] Longest Substring Without Repeating Characters + */ +class Solution { +public: + int lengthOfLongestSubstring(string s) { + int size,i=0,j,k,max=0; + size = s.size(); + for(j = 0;j max) + max = j-i+1; + } + return max; + } +}; + diff --git a/Week_02/id_40/LeetCode_98_40.cpp b/Week_02/id_40/LeetCode_98_40.cpp new file mode 100644 index 00000000..521e2fa6 --- /dev/null +++ b/Week_02/id_40/LeetCode_98_40.cpp @@ -0,0 +1,33 @@ +/* + * @lc app=leetcode id=98 lang=cpp + * + * [98] Validate Binary Search Tree + */ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +class Solution { +public: + int* last = NULL; + bool isValidBST(TreeNode* root) { + if (root){ + if(!isValidBST(root->left)) + return false; + if (last && *last>=root->val) + return false; + last = &root->val; + if(!isValidBST(root->right)) + return false; + return true; + } + else + return true; + }; +}; + diff --git a/Week_02/id_41/LeetCode_101_41.cpp b/Week_02/id_41/LeetCode_101_41.cpp new file mode 100644 index 00000000..95d83a7c --- /dev/null +++ b/Week_02/id_41/LeetCode_101_41.cpp @@ -0,0 +1,31 @@ +/* + * @lc app=leetcode id=101 lang=cpp + * + * [101] Symmetric Tree + * T(n) = O(N) + */ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +class Solution { +public: + bool isSymmetric(TreeNode* root) { + return root == NULL || isSymmetricHelp(root->left, root->right); + } + bool isSymmetricHelp(TreeNode* left, TreeNode* right) { + if (left == NULL || right == NULL) { + return left == right; + } + if (left->val != right->val) { + return false; + } + return isSymmetricHelp(left->left, right->right) && isSymmetricHelp(left->right, right->left); + } +}; + diff --git a/Week_02/id_41/LeetCode_103_41.cpp b/Week_02/id_41/LeetCode_103_41.cpp new file mode 100644 index 00000000..75820eba --- /dev/null +++ b/Week_02/id_41/LeetCode_103_41.cpp @@ -0,0 +1,50 @@ +/* + * @lc app=leetcode id=103 lang=cpp + * + * [103] Binary Tree Zigzag Level Order Traversal + */ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +class Solution { +public: + vector> zigzagLevelOrder(TreeNode* root) { + vector> res; + + if (root == NULL) { + return {}; + } + queue q; + int i = 0; + + q.push(root); + + while (!q.empty()) { + vector v; + int s = q.size(); + while (s--) { + root = q.front(); + q.pop(); + v.push_back(root->val); + if (root->left) { + q.push(root->left); + } + if (root->right) { + q.push(root->right); + } + } + if (i++ & 1) { + reverse(v.begin(), v.end()); + } + res.push_back(v); + } + return res; + } +}; + diff --git a/Week_02/id_41/LeetCode_111_41.cpp b/Week_02/id_41/LeetCode_111_41.cpp new file mode 100644 index 00000000..f2460186 --- /dev/null +++ b/Week_02/id_41/LeetCode_111_41.cpp @@ -0,0 +1,26 @@ +/* + * @lc app=leetcode id=111 lang=cpp + * + * [111] Minimum Depth of Binary Tree + */ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +class Solution +{ +public: + int minDepth(TreeNode *root) + { + if (root == NULL) + return 0; + int left = minDepth(root->left); + int right = minDepth(root->right); + return (left == 0 || right == 0) ? (left + right + 1) : min(left, right) + 1; + } +}; diff --git a/Week_02/id_41/LeetCode_1_41.cpp b/Week_02/id_41/LeetCode_1_41.cpp new file mode 100644 index 00000000..3ac4193b --- /dev/null +++ b/Week_02/id_41/LeetCode_1_41.cpp @@ -0,0 +1,25 @@ +/* + * @lc app=leetcode id=1 lang=cpp + * + * [1] Two Sum + * T(n) = O(N) + * S(n) = O(N) + */ +class Solution +{ +public: + vector twoSum(vector &nums, int target) + { + unordered_map m; + for (int i = 0; i < nums.size(); i++) + { + if (m.find(target - nums[i]) != m.end()) { + return { m[target - nums[i]], i }; + } + + m[nums[i]] = i; + } + return {}; + } +}; + diff --git a/Week_02/id_41/LeetCode_220_41.cpp b/Week_02/id_41/LeetCode_220_41.cpp new file mode 100644 index 00000000..ff3c359f --- /dev/null +++ b/Week_02/id_41/LeetCode_220_41.cpp @@ -0,0 +1,29 @@ +/* + * @lc app=leetcode id=220 lang=cpp + * + * [220] Contains Duplicate III + * T(n) = O(N) + */ +class Solution { +public: + bool containsNearbyAlmostDuplicate(vector& nums, int k, int t) { + if (nums.size() < 2 || k == 0) + return false; + deque windows_deq; + multiset windows; + for (int i = 0; i < nums.size(); i++) { + if (windows.size() > k) { + int num = windows_deq.front(); + windows_deq.pop_front(); + windows.erase(windows.find(num)); + } + auto it = windows.lower_bound((long)nums[i] - (long)t); + if (it == windows.end() || *it > (long)nums[i] + (long)t) { + windows_deq.push_back(nums[i]); + windows.insert(nums[i]); + } + else return true; + } + return false; + } +}; diff --git a/Week_02/id_41/LeetCode_242_41.cpp b/Week_02/id_41/LeetCode_242_41.cpp new file mode 100644 index 00000000..667b7867 --- /dev/null +++ b/Week_02/id_41/LeetCode_242_41.cpp @@ -0,0 +1,24 @@ +/* + * @lc app=leetcode id=242 lang=cpp + * + * [242] Valid Anagram + */ +class Solution { +public: + bool isAnagram(string s, string t) { + if (s.length() != t.length()) + return false; + int n = s.length(); + int count[26] = {0}; + for (int i = 0; i < n; i++) { + count[s[i] - 'a']++; + count[t[i] - 'a']--; + } + for (int i = 0; i < 26; i++) { + if (count[i] != 0) { + return false; + } + } + return true; + } +}; diff --git a/Week_02/id_41/LeetCode_315_41.cpp b/Week_02/id_41/LeetCode_315_41.cpp new file mode 100644 index 00000000..3ca5c6d2 --- /dev/null +++ b/Week_02/id_41/LeetCode_315_41.cpp @@ -0,0 +1,55 @@ +/* + * @lc app=leetcode id=315 lang=cpp + * + * [315] count of Smaller Numbers After Self + * T(n) = O(N) + * S(n) = O(N) + */ +class Solution +{ +public: + vector countSmaller(vector &nums) + { + TreeNode *root = NULL; + vector res(nums.size()); + for (int i = nums.size() - 1; i >= 0; i--) + res[i] = bstInsert(root, nums[i]); + return res; + } + +private: + struct TreeNode + { + int val; + int sum; + TreeNode *left; + TreeNode *right; + TreeNode(int v, int s) : val(v), sum(s), left(NULL), right(NULL) {} + }; + + int bstInsert(TreeNode* &root, + int val) + { + int count = 0; + if (root == NULL) + { + root = new TreeNode(val, 0); + return 0; + } + + if (val < root->val) + { + root->sum++; + count = bstInsert(root->left, val); + } + else + { + count = bstInsert(root->right, val) + + root->sum + + (root->val < val ? 1 : 0); + } + + return count; + } +}; + diff --git a/Week_02/id_41/LeetCode_3_41.cpp b/Week_02/id_41/LeetCode_3_41.cpp new file mode 100644 index 00000000..eb07ced0 --- /dev/null +++ b/Week_02/id_41/LeetCode_3_41.cpp @@ -0,0 +1,23 @@ +/* + * @lc app=leetcode id=3 lang=cpp + * + * [3] Longest Substring Without Repeating Characters + * T(n) = O(N) + */ +class Solution { +public: + int lengthOfLongestSubstring(string s) { + int n = s.length(); + int ans = 0; + unordered_map map; + for (int j = 0, i = 0; j < n; j++) { + if (map.find(s[j]) != map.end()) { + i = max(map[s[j]], i); + } + ans = max(ans, j - i + 1); + map[s[j]] = j + 1; + } + return ans; + } +}; + diff --git a/Week_02/id_41/LeetCode_692_41.cpp b/Week_02/id_41/LeetCode_692_41.cpp new file mode 100644 index 00000000..eef021f4 --- /dev/null +++ b/Week_02/id_41/LeetCode_692_41.cpp @@ -0,0 +1,36 @@ +/* +* @lc app=leetcode id=692 lang=cpp +* +* [692] Top K Frequent Words +*/ +class Solution +{ +public: + vector topKFrequent(vector &words, int k) + { + vector res; + unordered_map m; + auto comp = [](pair &a, pair &b) { + // first为出现次数,second为字母顺序排列 + return a.first == b.first ? a.second < b.second : a.first > b.first; + }; + priority_queue, vector>, decltype(comp)> pq(comp); + for (auto x : words) + { + m[x]++; + } + for (auto x : m) + { + pq.push({x.second, x.first}); + if (pq.size() > k) + pq.pop(); + } + while (!pq.empty()) + { + res.push_back(pq.top().second); + pq.pop(); + } + reverse(res.begin(), res.end()); + return res; + } +}; diff --git a/Week_02/id_41/LeetCode_726_41.cpp b/Week_02/id_41/LeetCode_726_41.cpp new file mode 100644 index 00000000..0832857f --- /dev/null +++ b/Week_02/id_41/LeetCode_726_41.cpp @@ -0,0 +1,84 @@ +/* + * @lc app=leetcode id=726 lang=cpp + * + * [726] Number of Atoms + * T(n) = O(N) + * S(n) = O(N) + */ +class Solution +{ +public: + string countOfAtoms(string f) + { + stack> st; + map cur; + int i = 0; + while (i < f.size()) + { + if (f[i] == '(') + { + processLeftBracket(cur, st, i); + } + else if (f[i] == ')') + { + processRightBracket(i, f, cur, st); + } + else + { + processCount(i, f, cur); + } + } + string ans; + for (auto p : cur) + { + ans += p.first; + if (p.second > 1) + ans += to_string(p.second); + } + + return ans; + } + +private: + void processLeftBracket(map &cur, + stack> &st, + int &i) + { + st.push(move(cur)); + cur = map(); + ++i; + } + + void processRightBracket(int &i, + string f, + map &cur, + stack> &st) + { + int j = i + 1; + int num = 0; + while (j < f.size() && isdigit(f[j])) + num = num * 10 + (f[j++] - '0'); + num = max(num, 1); + for (auto p : cur) + st.top()[p.first] += p.second * num; + cur = move(st.top()); + st.pop(); + i = j; + } + + void processCount(int &i, + string f, + map &cur) + { + int j = i + 1; + int num = 0; + while (j < f.size() && f[j] >= 'a' && f[j] <= 'z') + ++j; + auto name = f.substr(i, j - i); + while (j < f.size() && isdigit(f[j])) + num = num * 10 + (f[j++] - '0'); + num = max(num, 1); + cur[name] += num; + i = j; + } +}; diff --git a/Week_02/id_41/LeetCode_783_41.cpp b/Week_02/id_41/LeetCode_783_41.cpp new file mode 100644 index 00000000..052db226 --- /dev/null +++ b/Week_02/id_41/LeetCode_783_41.cpp @@ -0,0 +1,32 @@ +/* + * @lc app=leetcode id=783 lang=cpp + * + * [783] Minimum Distance Between BST Nodes + * T(n) = O(N) + */ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +class Solution +{ +public: + int res = INT_MAX; + int preVal = -1; + int minDiffInBST(TreeNode *root) + { + if (root->left != NULL) + minDiffInBST(root->left); + if (preVal >= 0) + res = min(res, root->val - preVal); + preVal = root->val; + if (root->right != NULL) + minDiffInBST(root->right); + return res; + } +}; diff --git a/Week_02/id_41/LeetCode_938_41.cpp b/Week_02/id_41/LeetCode_938_41.cpp new file mode 100644 index 00000000..659d7058 --- /dev/null +++ b/Week_02/id_41/LeetCode_938_41.cpp @@ -0,0 +1,29 @@ +/* + * @lc app=leetcode id=938 lang=cpp + * + * [938] Range Sum of BST + * T(n) = O(N) + */ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +class Solution +{ +public: + int rangeSumBST(TreeNode *root, int L, int R) + { + if (root == nullptr) + return 0; + if (root->val > R) + return rangeSumBST(root->left, L, R); //when val > R + if (root->val < L) + return rangeSumBST(root->right, L, R); // when val < L + return root->val + rangeSumBST(root->left, L, R) + rangeSumBST(root->right, L, R); + } +}; diff --git a/Week_02/id_41/NOTE.md b/Week_02/id_41/NOTE.md index 107ea7d6..d95e08f0 100644 --- a/Week_02/id_41/NOTE.md +++ b/Week_02/id_41/NOTE.md @@ -1 +1,2 @@ # 学习笔记 +这周时间比较紧,代码不多。 \ No newline at end of file diff --git a/Week_02/id_42/LeetCode_242_42.java b/Week_02/id_42/LeetCode_242_42.java new file mode 100644 index 00000000..42d7c2ad --- /dev/null +++ b/Week_02/id_42/LeetCode_242_42.java @@ -0,0 +1,16 @@ +class Solution { + public boolean isAnagram(String s, String t) { + if(s.length()!=t.length()) + return false; + int[] alpha = new int[26]; + for(int i=0;i= start){ //当前这个字符出现过 + if(i-start > len) + len = i-start; + start = last[w[i]-' '] + 1; //从这个字符首次出现的位置+1,重新扫描,相当于把前面抛开前面的字符串不谈 + } + last[w[i]-' '] = i;//更新当前字符的下标 + } + if(len > s.length() - start)//针对没有重复字符的字符串 + return len; + else + return s.length() - start; + } + +} \ No newline at end of file diff --git a/Week_02/id_42/NOTE.md b/Week_02/id_42/NOTE.md index 107ea7d6..f7fbdf0e 100644 --- a/Week_02/id_42/NOTE.md +++ b/Week_02/id_42/NOTE.md @@ -1 +1,48 @@ # 学习笔记 + +# leetcode 第三题 + +最长不重复子串: +最简单的方法还是: +public class Solution { + public int lengthOfLongestSubstring(String s) { + int n = s.length(), ans = 0; + Map map = new HashMap<>(); // current index of character + // try to extend the range [i, j] + for (int j = 0, i = 0; j < n; j++) { + if (map.containsKey(s.charAt(j))) { + i = Math.max(map.get(s.charAt(j)), i); + } + ans = Math.max(ans, j - i + 1); + map.put(s.charAt(j), j + 1); + } + return ans; + } +} + +这种方式较为易懂,而且时间复杂度为o(n) + + +#leetcode 242 +class Solution { + public boolean isAnagram(String s, String t) { + if(s.length()!=t.length()) + return false; + int[] alpha = new int[26]; + for(int i=0;i book = new HashMap<>(); + for (int i = 0;i window = new HashSet<>(); + int i = 0, j = 0, maxLength = 0; + + while (i < length && j < length) { + if (!window.contains(s.charAt(j))) { + window.add(s.charAt(j)); + j++; + maxLength = Math.max(maxLength, j - i); + }else{ + window.remove(s.charAt(i)); + i++; + } + } + return maxLength; + } + +} diff --git a/Week_02/id_6/LeetCode_101_6.php b/Week_02/id_6/LeetCode_101_6.php new file mode 100644 index 00000000..ccf80672 --- /dev/null +++ b/Week_02/id_6/LeetCode_101_6.php @@ -0,0 +1,37 @@ +val = $value; } + * } + */ +class Solution { + + /** + * @param TreeNode $root + * @return Boolean + */ + function isSymmetric($root) + { + $this->isSymmetricRec($root, $root); + } + + /** + * @param TreeNode $left_root + * @param TreeNode $right_root + * @return Boolean + */ + function isSymmetricRec($left_root, $right_root) + { + if ($left_root == null && $right_root == null) return true; + if ($left_root == null || $right_root == null) return false; + if ($left_root->val == $right_root->val) { + return $this->isSymmetricRec($left_root->left, $right_root->right) && $this->isSymmetricRec($left_root->right, $right_root->left); + } + return false; + } +} \ No newline at end of file diff --git a/Week_02/id_6/LeetCode_102_6.php b/Week_02/id_6/LeetCode_102_6.php new file mode 100644 index 00000000..2490120d --- /dev/null +++ b/Week_02/id_6/LeetCode_102_6.php @@ -0,0 +1,41 @@ +val = $value; } + * } + */ +class Solution { + + public $levels = []; + + /** + * @param TreeNode $root + * @return Integer[][] + */ + function levelOrder($root) + { + if ($root == null) return []; + // BFS + $this->bfs($root, 0); + return $this->levels; + + } + + function bfs($root, $level) + { + $this->levels[$level][] = $root->val; + + if ($root->left != null) { + $this->bfs($root->left, $level + 1); + } + + if ($root->right != null) { + $this->bfs($root->right, $level + 1); + } + } +} \ No newline at end of file diff --git a/Week_02/id_6/LeetCode_103_6.php b/Week_02/id_6/LeetCode_103_6.php new file mode 100644 index 00000000..51a38792 --- /dev/null +++ b/Week_02/id_6/LeetCode_103_6.php @@ -0,0 +1,44 @@ +val = $value; } + * } + */ +class Solution { + + public $levels = []; + + /** + * @param TreeNode $root + * @return Integer[][] + */ + function zigzagLevelOrder($root) { + if ($root == null) return []; + // BFS + $this->bfs($root, 0); + return $this->levels; + } + + function bfs($root, $level) + { + if ($level % 2 != 0) { + if (!isset($this->levels[$level])) $this->levels[$level] = []; + array_unshift($this->levels[$level], $root->val); + } else { + $this->levels[$level][] = $root->val; + } + + if ($root->left != null) { + $this->bfs($root->left, $level + 1); + } + + if ($root->right != null) { + $this->bfs($root->right, $level + 1); + } + } +} \ No newline at end of file diff --git a/Week_02/id_6/LeetCode_3_6.php b/Week_02/id_6/LeetCode_3_6.php new file mode 100644 index 00000000..75582df8 --- /dev/null +++ b/Week_02/id_6/LeetCode_3_6.php @@ -0,0 +1,30 @@ +lengthOfLongestSubstring($s)); \ No newline at end of file diff --git a/Week_02/id_6/LeetCode_938_6.php b/Week_02/id_6/LeetCode_938_6.php new file mode 100644 index 00000000..876ee4a6 --- /dev/null +++ b/Week_02/id_6/LeetCode_938_6.php @@ -0,0 +1,32 @@ +val = $value; } + * } + */ +class Solution { + + /** + * @param TreeNode $root + * @param Integer $L + * @param Integer $R + * @return Integer + */ + function rangeSumBST($root, $L, $R) + { + if ($root == null) return $this->sum; + if ($root->val > $R) { + return $this->rangeSumBST($root->left, $L, $R); + } + if ($root->val < $L) { + return $this->rangeSumBST($root->right, $L, $R); + } + return $root->val + $this->rangeSumBST($root->left, $L, $R) + $this->rangeSumBST($root->right, $L, $R); + } + +} \ No newline at end of file diff --git a/Week_02/id_6/LeetCode_98_6.php b/Week_02/id_6/LeetCode_98_6.php new file mode 100644 index 00000000..a3e23e60 --- /dev/null +++ b/Week_02/id_6/LeetCode_98_6.php @@ -0,0 +1,28 @@ +val = $value; } + * } + */ +class Solution { + + public $flag = PHP_INT_MIN; + + /** + * @param TreeNode $root + * @return Boolean + */ + function isValidBST($root) { + if ($root == null) return true; + if ($this->isValidBST($root->left)) { + if ($this->flag > $root->val) return false; + $this->flag = $root->val; + return $this->isValidBST($root->right); + } + } +} \ No newline at end of file diff --git a/Week_02/id_6/NOTE.md b/Week_02/id_6/NOTE.md index 107ea7d6..4d85a097 100644 --- a/Week_02/id_6/NOTE.md +++ b/Week_02/id_6/NOTE.md @@ -1 +1,9 @@ # 学习笔记 + +这一周主要是hash表、二叉树、二叉搜索树的练习。难度选择了在中等难度以上的题目进行练习。每道题目都会先自己思考,多多少少都会有一些想法和思路,但是在具体代码实现细节上面还有些欠缺,大部分题目还需要看过别人的讨论才有具体的实现思路。经过自己实现之后,对于同类型的问题做起来会更加有思路些,还是需要更多地练习。 + +Hash表的特点是使用hash函数构建键值对应关系,插入和查找的时间复杂度是O(1),可以应用到字符串搜索、匹配、数据缓存等场景下。LeetCode第3题构建使用hash表,一次循环即可找到最长子字符串,也是一种空间换时间的解决问题思路。 + +更多的对于二叉树和二叉搜索树进行了练习。主要的解题思路是递归,从做题中发现技巧是对于前序、中序、后序遍历以及BFS、DFS的合理运用,可以解决很多问题,至少可以提供一种解题思路。通过做题也对树的上面的遍历方式的具体实现代码有了更熟练的运用。对于二叉搜索树的解题思路,更多运用到二叉搜索树特性:1.左<根<右;2.每一节点都是二叉搜索树;3.中序遍历是递增数列。应用这三点特性,遇到二叉搜索树的问题,还是能提供不少的解题想法的。 + +还需要更多地做题练习来打开自己的解题思维。 \ No newline at end of file diff --git a/Week_02/id_7/LeetCode_101_7.cs b/Week_02/id_7/LeetCode_101_7.cs new file mode 100644 index 00000000..5f7b20ce --- /dev/null +++ b/Week_02/id_7/LeetCode_101_7.cs @@ -0,0 +1,39 @@ +/* + * @lc app=leetcode.cn id=101 lang=csharp + * + * [101] 对称二叉树 + */ + +using System.Collections; +/** + * Definition for a binary tree node. + * public class TreeNode { + * public int val; + * public TreeNode left; + * public TreeNode right; + * public TreeNode(int x) { val = x; } + * } + */ +public class Solution { + // 按层遍历,按顺序:左子树左节点、右子树右节点、左子树右节点、右子树左节点,进队列,然后每次出队列两个,比较是否相等,遇不等就直接返回false + public bool IsSymmetric (TreeNode root) { + Queue que = new Queue (); + que.Enqueue (root); + que.Enqueue (root); + while (que.Count > 0) { + TreeNode nodeL = (TreeNode) que.Dequeue (); + TreeNode nodeR = (TreeNode) que.Dequeue (); + if (nodeL == null && nodeR == null) + continue; + if (nodeL == null || nodeR == null) + return false; + if (nodeL.val != nodeR.val) + return false; + que.Enqueue (nodeL.left); + que.Enqueue (nodeR.right); + que.Enqueue (nodeL.right); + que.Enqueue (nodeR.left); + } + return true; + } +} \ No newline at end of file diff --git a/Week_02/id_7/LeetCode_111_7.cs b/Week_02/id_7/LeetCode_111_7.cs new file mode 100644 index 00000000..a20ea6fd --- /dev/null +++ b/Week_02/id_7/LeetCode_111_7.cs @@ -0,0 +1,45 @@ +/* + * @lc app=leetcode.cn id=111 lang=csharp + * + * [111] 二叉树的最小深度 + */ + +using System; +using System.Collections; +using System.Collections.Generic; +/** + * Definition for a binary tree node. + * public class TreeNode { + * public int val; + * public TreeNode left; + * public TreeNode right; + * public TreeNode(int x) { val = x; } + * } + */ +public class Solution { + // 深度优先遍历所有节点,最后输出最小深度(非递归实现) + public int MinDepth (TreeNode root) { + Stack sk = new Stack (); + if (root == null) { + return 0; + } else { + sk.Push (new KeyValuePair (root, 1)); + } + int nDepth = int.MaxValue; + while (sk.Count > 0) { + KeyValuePair kvp = (KeyValuePair) sk.Pop (); + root = kvp.Key; + int nTemp = kvp.Value; + if (root.left == null && root.right == null) { + nDepth = Math.Min (nDepth, nTemp); + } + if (root.left != null) { + sk.Push (new KeyValuePair (root.left, nTemp + 1)); + } + if (root.right != null) { + sk.Push (new KeyValuePair (root.right, nTemp + 1)); + } + } + return nDepth; + } +} \ No newline at end of file diff --git a/Week_02/id_7/LeetCode_1_7.cs b/Week_02/id_7/LeetCode_1_7.cs new file mode 100644 index 00000000..d6a87b3a --- /dev/null +++ b/Week_02/id_7/LeetCode_1_7.cs @@ -0,0 +1,24 @@ +/* + * @lc app=leetcode.cn id=1 lang=csharp + * + * [1] 两数之和 + */ + +using System.Collections.Generic; + +public class Solution { + public int[] TwoSum (int[] nums, int target) { + Dictionary dicNums = new Dictionary (); + for (int i = 0; i < nums.Length; i++) { + if (!dicNums.ContainsKey (target - nums[i])) { + if (!dicNums.ContainsKey (nums[i])) { + dicNums.Add (nums[i], i); + } + } else { + return new int[] { dicNums[target - nums[i]], i }; + } + } + + return null; + } +} \ No newline at end of file diff --git a/Week_02/id_7/LeetCode_242_7.cs b/Week_02/id_7/LeetCode_242_7.cs new file mode 100644 index 00000000..cfe573bf --- /dev/null +++ b/Week_02/id_7/LeetCode_242_7.cs @@ -0,0 +1,28 @@ +/* + * @lc app=leetcode.cn id=242 lang=csharp + * + * [242] 有效的字母异位词 + */ +using System.Collections.Generic; + +public class Solution { + public bool IsAnagram (string s, string t) { + if (s.Length != t.Length) { + return false; + } + + int[] arrRes = new int[26]; + for (int i = 0; i < s.Length; i++) { + arrRes[s[i] - 'a']++; + arrRes[t[i] - 'a']--; + } + + for (int i = 0; i < 26; i++) { + if (arrRes[i] != 0) { + return false; + } + } + + return true; + } +} \ No newline at end of file diff --git a/Week_02/id_7/LeetCode_3_7.cs b/Week_02/id_7/LeetCode_3_7.cs new file mode 100644 index 00000000..e2bb64cd --- /dev/null +++ b/Week_02/id_7/LeetCode_3_7.cs @@ -0,0 +1,24 @@ +/* + * @lc app=leetcode.cn id=3 lang=csharp + * + * [3] 无重复字符的最长子串 + */ +using System; +using System.Collections.Generic; + +public class Solution { + public int LengthOfLongestSubstring (string s) { + Dictionary dic = new Dictionary (); + int ans = 0; + for (int left = 0, right = 0; right < s.Length; right++) { + if (dic.ContainsKey (s[right])) { + left = Math.Max (left, dic[s[right]]); + dic[s[right]] = right + 1; + } else { + dic.Add (s[right], right + 1); + } + ans = Math.Max (ans, right - left + 1); + } + return ans; + } +} \ No newline at end of file diff --git a/Week_02/id_7/LeetCode_726_7.cs b/Week_02/id_7/LeetCode_726_7.cs new file mode 100644 index 00000000..2313119e --- /dev/null +++ b/Week_02/id_7/LeetCode_726_7.cs @@ -0,0 +1,71 @@ +/* + * @lc app=leetcode.cn id=726 lang=csharp + * + * [726] 原子的数量 + * a-z:97-122 + * A-Z:65-90 + * 0-9:48-57 + */ +using System; +using System.Collections; +using System.Collections.Generic; + +public class Solution { + public string CountOfAtoms (string formula) { + Stack> skRes = new Stack> (); + skRes.Push (new Dictionary ()); + int i = 0; + while (i < formula.Length) { + if (formula[i].Equals ('(')) { + skRes.Push (new Dictionary ()); + i++; + } else if (formula[i].Equals (')')) { + int start = ++i; + while (i < formula.Length && formula[i] >= 48 && formula[i] <= 57) i++; + int multiplicity = i > start? Convert.ToInt32 (formula.Substring (start, i - start)) : 1; + if (multiplicity != 1) { + Dictionary dicTemp = skRes.Pop (); + Dictionary dicTemp2 = skRes.Peek (); + foreach (var name in dicTemp.Keys) { + if (dicTemp2.ContainsKey (name)) { + dicTemp2[name] += dicTemp[name] * multiplicity; + } else { + dicTemp2.Add (name, dicTemp[name] * multiplicity); + } + } + } + } else { + int start = i++; + while (i < formula.Length && formula[i] >= 97 && formula[i] <= 122) i++; + string name = formula.Substring (start, i - start); + + start = i; + while (i < formula.Length && formula[i] >= 48 && formula[i] <= 57) i++; + int multiplicity = i > start? Convert.ToInt32 (formula.Substring (start, i - start)) : 1; + + Dictionary dicTemp = skRes.Peek (); + if (dicTemp.ContainsKey (name)) { + dicTemp[name] = dicTemp[name] + multiplicity; + } else { + dicTemp.Add (name, multiplicity); + } + } + } + + string strRes = ""; + Dictionary dicRes = skRes.Peek (); + List lst = new List (); + foreach (var name in dicRes.Keys) { + lst.Add (name); + } + lst.Sort (); + for (int k = 0; k < lst.Count; k++) { + if (dicRes[lst[k]] > 1) + strRes += (lst[k] + dicRes[lst[k]]); + else + strRes += (lst[k] + ""); + } + + return strRes; + } +} \ No newline at end of file diff --git a/Week_02/id_7/LeetCode_783_7.cs b/Week_02/id_7/LeetCode_783_7.cs new file mode 100644 index 00000000..0f28b662 --- /dev/null +++ b/Week_02/id_7/LeetCode_783_7.cs @@ -0,0 +1,30 @@ +/* + * @lc app=leetcode.cn id=783 lang=csharp + * + * [783] 二叉搜索树结点最小距离 + */ + +using System; +/** + * Definition for a binary tree node. + * public class TreeNode { + * public int val; + * public TreeNode left; + * public TreeNode right; + * public TreeNode(int x) { val = x; } + * } + */ +public class Solution { + int m_nRsult = int.MaxValue; + int m_nLastv = -999999; + public int MinDiffInBST (TreeNode root) { + if (root.left != null) + MinDiffInBST (root.left); + m_nRsult = Math.Min (m_nRsult, root.val - m_nLastv); + m_nLastv = root.val; + if (root.right != null) + MinDiffInBST (root.right); + + return m_nRsult; + } +} \ No newline at end of file diff --git a/Week_02/id_8/Leetcode_236_8.java b/Week_02/id_8/Leetcode_236_8.java new file mode 100644 index 00000000..06f93c90 --- /dev/null +++ b/Week_02/id_8/Leetcode_236_8.java @@ -0,0 +1,29 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +class Solution { + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + if (root == null) { + return root; + } + if (root == p || root == q) { + return root; + } + TreeNode left = lowestCommonAncestor(root.left, p, q); + TreeNode right = lowestCommonAncestor(root.right, p, q); + if (left != null && right != null) { + return root; + } else if (left != null) { + return left; + } else if (right != null) { + return right; + } + return null; + } +} \ No newline at end of file diff --git a/Week_02/id_8/Leetcode_242_8.java b/Week_02/id_8/Leetcode_242_8.java new file mode 100644 index 00000000..eff6b838 --- /dev/null +++ b/Week_02/id_8/Leetcode_242_8.java @@ -0,0 +1,33 @@ +class Solution { + public boolean isAnagram(String s, String t) { + // 优化,直接返回false + if (s.length() != t.length()) { + return false; + } + HashMap map = new HashMap<>(); + // 构建hashmap + for (int i = 0; i 这道题目的难点在于单词中可能存在多个相同的字符,常用的简单KV需要使用整数来表示value。 + +### 解题思路 +> 首先可以想到的是,如果两个单词的长度不一致,就直接可以返回false了。 +然后开始构建map, 假设前面单词是a,后面单词是b,则可以以a为标准构建这个map。 +如果存在这个字符,就将该字符的value+1,否则不存在直接置为1。 +然后遍历b,对每一个字符,在前面以a为标准创建出来的map中检查,将存在的那个字符对应的value减一。 +最后只要是不是这个map是不是全是0就行了。 + +### 参考代码AC +```Java +class Solution { + public boolean isAnagram(String s, String t) { + // 优化,直接返回false + if (s.length() != t.length()) { + return false; + } + HashMap map = new HashMap<>(); + // 构建hashmap + for (int i = 0; i这道题的思路挺难想的,可以通过先看答案的方式,理解就行了。 + +### 解题思路 +>这道题本来的解法是这样的,相当于要双重递归了,先DFS每个根节点,然后对每个根节点的左右 + 子树,分别再使用DFS来判断目标节点是否包含在书中。就算使用了一些剪枝的技巧,也超时。然后 + 就想了,是否可以一次递归就搞定,答案是肯定的。 + 优化的思路在于,节点一定都存在,所以只要right == null,就可以断定都在left中,并且祖先就是left + 反之亦然 + +### 参考AC代码 +```Java +class Solution { + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + if (root == null) { + return root; + } + if (root == p || root == q) { + return root; + } + TreeNode left = lowestCommonAncestor(root.left, p, q); + TreeNode right = lowestCommonAncestor(root.right, p, q); + if (left != null && right != null) { + return root; + } else if (left != null) { + return left; + } else if (right != null) { + return right; + } + return null; + } +} +``` diff --git a/Week_02/id_9/LeetCode_242_9.java b/Week_02/id_9/LeetCode_242_9.java new file mode 100644 index 00000000..9782a887 --- /dev/null +++ b/Week_02/id_9/LeetCode_242_9.java @@ -0,0 +1,67 @@ +package com.github.lifelab.leetcode.problemset; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * 有效的字母异位词 @see https://leetcode-cn.com/problems/valid-anagram/ + * + * @author Weichao Li (liweichao0102@gmail.com) + * @since 2019-06-16 + */ +public class Solution242 { + + public boolean isAnagram(String s, String t) { + if (Objects.isNull(s) || Objects.isNull(t)) { + return false; + } + if (s.length() != t.length()) { + return false; + } + + char[] temp = new char[26]; + + for (int i = 0; i < s.length(); i++) { + temp[s.charAt(i) - 'a']++; + temp[t.charAt(i) - 'a']--; + } + + for (int i = 0; i < temp.length; i++) { + if (temp[i] != 0) { + return false; + } + } + return true; + } + + public boolean isAnagram1(String s, String t) { + if (Objects.isNull(s) || Objects.isNull(t)) { + return false; + } + if (s.length() != t.length()) { + return false; + } + char[] sarray = s.toCharArray(); + char[] tarray = t.toCharArray(); + Arrays.sort(sarray); + Arrays.sort(tarray); + return Arrays.equals(sarray, tarray); + } + + public boolean isAnagram2(String s, String t) { + if (Objects.isNull(s) || Objects.isNull(t)) { + return false; + } + if (s.length() != t.length()) { + return false; + } + Map maps = new HashMap<>(t.length()); + for (int i = 0; i < s.length(); i++) { + maps.compute(s.charAt(i), (k, v) -> maps.getOrDefault(k, 0) + 1); + maps.compute(t.charAt(i), (k, v) -> maps.getOrDefault(k, 0) - 1); + } + return maps.values().stream().parallel().allMatch(e -> Objects.isNull(e) | e == 0); + } +} \ No newline at end of file diff --git a/Week_02/id_9/LeetCode_98_9.java b/Week_02/id_9/LeetCode_98_9.java new file mode 100644 index 00000000..d323c83b --- /dev/null +++ b/Week_02/id_9/LeetCode_98_9.java @@ -0,0 +1,29 @@ +package com.github.lifelab.leetcode.problemset; + +/** + * 验证二叉搜索树 @see https://leetcode-cn.com/problems/validate-binary-search-tree/submissions/ + * + * @author Weichao Li (liweichao0102@gmail.com) + * @since 2019-06-16 + */ +public class Solution98 { + + long temp = Long.MIN_VALUE; + + public boolean isValidBST(TreeNode root) { + //terminator + if (root == null) { + return true; + } + + // process + if (isValidBST(root.left)) { + if (temp < root.val) { + temp = root.val; + //drill down + return isValidBST(root.right); + } + } + return false; + } +} diff --git a/Week_03/id_1/LeetCode_102_1.java b/Week_03/id_1/LeetCode_102_1.java new file mode 100644 index 00000000..739ff3b0 --- /dev/null +++ b/Week_03/id_1/LeetCode_102_1.java @@ -0,0 +1,43 @@ +package id_1; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +/** + * @创建人 luoxiang + * @创建时间 2019/6/19 12:59 + * @描述 LeetCode : 102. 二叉树的层次遍历 https://leetcode-cn.com/problems/binary-tree-level-order-traversal/ + */ +public class LeetCode_102_1 { + public static void main(String[] args) { + + } + + /** + * Method 1 : BFS 一套标准的 BFS 代码模板解决多类问题 + */ + public List> levelOrder(TreeNode root) { + List> list = new LinkedList<>(); + if(root==null) return list; + Queue queue = new LinkedList<>(); + queue.offer(root); + boolean flag=false; + while (!queue.isEmpty()){ + List linkedList = new LinkedList<>(); + int size = queue.size(); + for(int i=0;i> zigzagLevelOrder(TreeNode root) { + List> list = new LinkedList<>(); + if(root==null) return list; + Queue queue = new LinkedList<>(); + queue.offer(root); + boolean flag=false; + while (!queue.isEmpty()){ + List linkedList = new LinkedList<>(); + int size = queue.size(); + for(int i=0;i> levelOrderBottom(TreeNode root) { + List> list = new LinkedList<>(); + if(root==null) return list; + Queue queue = new LinkedList<>(); + queue.offer(root); + while (!queue.isEmpty()){ + List linkedList = new LinkedList<>(); + int size = queue.size(); + for(int i=0;i= grid.length || j >= grid[0].length || grid[i][j] == '0') return; + // dfs 当前的四个方向 + grid[i][j] = '0'; + dfs(grid, i + 1, j); + dfs(grid, i - 1, j); + dfs(grid, i, j + 1); + dfs(grid, i, j - 1); + } + + /** + * Method 2 : Union Find 合并集 + */ + public int numIslands2(char[][] grid) { + if (grid == null || grid.length == 0) return 0; + int[][] direction = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + int row = grid.length; + int col = grid[0].length; + UnionFind unionFind = new UnionFind(grid); + for (int i = 0; i < row; i++) { + for (int j = 0; j < col; j++) { + if (grid[i][j] == '1') { + for (int[] d : direction) { + int x = i + d[0]; + int y = j + d[1]; + if (x >= 0 && x < row && y >= 0 && y < col && grid[x][y] == '1') { + int current = i * col + j; + int otherDirection = x * col + y; + unionFind.union(current, otherDirection); + } + } + } + } + } + return unionFind.count; + } + + + /** + * Union find 类实现 + */ + class UnionFind { + int count = 0; + int[] father; + int row, col; + + UnionFind(char[][] grid) { + row = grid.length; + col = grid[0].length; + father = new int[row * col]; + for (int i = 0; i < row; i++) { + for (int j = 0; j < col; j++) { + if (grid[i][j] == '1') { + int temp = i * col + j; + father[temp] = temp; + count++; + } + } + } + } + + /** + * 合并方法 + */ + public void union(int node1, int node2) { + int n1 = find(node1); + int n2 = find(node2); + if (n1 != n2) { + father[n1] = n2; + count--; + } + } + + /** + * 查找方法 + */ + public int find(int node) { + if (father[node] == node) return node; + return find(father[node]); + } + } +} diff --git a/Week_03/id_1/LeetCode_429_1.java b/Week_03/id_1/LeetCode_429_1.java new file mode 100644 index 00000000..bd158c97 --- /dev/null +++ b/Week_03/id_1/LeetCode_429_1.java @@ -0,0 +1,133 @@ +package id_1; + +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +/** + * @创建人 luoxiang + * @创建时间 2019/6/19 12:25 + * @描述 LeetCode : 429. N叉树的层序遍历 https://leetcode-cn.com/problems/n-ary-tree-level-order-traversal/submissions/ + */ + +// Definition for a Node. +class Node { + public int val; + public List children; + + public Node() { + } + + public Node(int _val, List _children) { + val = _val; + children = _children; + } +}; + +public class LeetCode_429_1 { + + public static void main(String[] args) { + final Node node5 = new Node(5, null); + final Node node6 = new Node(6, null); + final LinkedList nodes = new LinkedList<>(); + nodes.add(node5); + nodes.add(node6); + final Node node3 = new Node(3, nodes); + final Node node2 = new Node(2, null); + final Node node4 = new Node(4, null); + final LinkedList nodes2 = new LinkedList<>(); + nodes2.add(node3); + nodes2.add(node2); + nodes2.add(node4); + final Node root = new Node(1, nodes2); + final List> lists = new LeetCode_429_1().levelOrder2(root); + for (List list : lists) { + for (Integer integer : list) { + System.out.print(integer + ","); + } + System.out.println(); + } + + } + + /** + * Method 1 : BFS 队列实现 + * 时间复杂度 : O(N) + * 空间复杂度 : O(N) + */ + public List> levelOrder(Node root) { + List> list = new LinkedList<>(); + if (root == null) return list; + + Queue queue = new LinkedList<>(); + List linkedList = new LinkedList<>(); + queue.offer(root); + int currentSize = 1; + while (!queue.isEmpty()) { + Node node = queue.poll(); + linkedList.add(node.val); + if (node.children != null) { + for (Node child : node.children) { + queue.offer(child); + } + } + if (--currentSize == 0) { + currentSize = queue.size(); + list.add(linkedList); + linkedList = new LinkedList<>(); + } + } + return list; + } + + /** + * Method 2 : BFS 不在外层创建 临时的 List , 在循环内部创建 + */ + public List> levelOrder2(Node root) { + List> list = new LinkedList<>(); + if (root == null) return list; + Queue queue = new LinkedList<>(); + queue.offer(root); + while (!queue.isEmpty()) { + List linkedList = new LinkedList<>(); + int size = queue.size(); + for (int i = 0; i < size; i++) { + Node node = queue.poll(); + linkedList.add(node.val); + if (node.children != null) { + for (Node child : node.children) { + queue.offer(child); + } + } + } + list.add(linkedList); + } + return list; + } + + public List> levelOrder3(Node root) { + List> ret = new LinkedList<>(); + + if (root == null) return ret; + + Queue queue = new LinkedList<>(); + + queue.offer(root); + + while (!queue.isEmpty()) { + List curLevel = new LinkedList<>(); + int len = queue.size(); + for (int i = 0; i < len; i++) { + Node curr = queue.poll(); + curLevel.add(curr.val); + for (Node c : curr.children) + queue.offer(c); + } + ret.add(curLevel); + } + + return ret; + } + +} + diff --git a/Week_03/id_1/LeetCode_547_1.java b/Week_03/id_1/LeetCode_547_1.java new file mode 100644 index 00000000..f323f677 --- /dev/null +++ b/Week_03/id_1/LeetCode_547_1.java @@ -0,0 +1,39 @@ +package id_1; + +/** + * @创建人 luoxiang + * @创建时间 2019/6/20 12:44 + * @描述 LeetCode : 547. 朋友圈 https://leetcode-cn.com/problems/friend-circles/ + */ +public class LeetCode_547_1 { + + public static void main(String[] args) { + + } + + /** + * Method 1 : DFS 深度优先 + */ + public int findCircleNum(int[][] M) { + if (M == null || M.length == 0) return 0; + int count = 0; + for (int i = 0; i < M.length; i++) { + for (int j = 0; j < M.length; j++) { + if (M[i][j] == 1) { + count++; + dfs(M, i, j); + } + } + } + return count; + } + + private void dfs(int[][] m, int i, int j) { + if (i < 0 || j < 0 || i >= m.length || j >= m.length || m[i][j] == 0) return; + m[i][j] = 0; + dfs(m, i + 1, j); + dfs(m, i - 1, j); + dfs(m, i, j + 1); + dfs(m, i, j - 1); + } +} diff --git a/Week_03/id_1/LeetCode_703_1.java b/Week_03/id_1/LeetCode_703_1.java new file mode 100644 index 00000000..c9581395 --- /dev/null +++ b/Week_03/id_1/LeetCode_703_1.java @@ -0,0 +1,99 @@ +package id_1; + +import java.util.PriorityQueue; + +/** + * @创建人 luoxiang + * @创建时间 2019/6/17 10:34 + * @描述 LeetCode : 703. 数据流中的第K大元素 https://leetcode-cn.com/problems/kth-largest-element-in-a-stream/ + */ +public class LeetCode_703_1 { + public static void main(String[] args) { +// KthLargest largest = new KthLargest(3, new int[]{4, 5, 8, 2}); +// System.out.println(largest.add(3)); +// System.out.println(largest.add(5)); +// System.out.println(largest.add(10)); +// System.out.println(largest.add(9)); +// System.out.println(largest.add(4)); + int year=20; + int money=10000; + double rate=0.05; + System.out.println("-----------------------------------------------"); + comppounding(10,10000,0.05); + comppounding(20,10000,0.05); + comppounding(30,10000,0.05); + System.out.println("-----------------------------------------------"); + comppounding(10,10000,0.08); + comppounding(20,10000,0.08); + comppounding(30,10000,0.08); + System.out.println("-----------------------------------------------"); + comppounding(10,10000,0.1); + comppounding(20,10000,0.1); + comppounding(30,10000,0.1); + System.out.println("-----------------------------------------------"); + comppounding(10,20000,0.05); + comppounding(20,20000,0.05); + comppounding(30,20000,0.05); + System.out.println("-----------------------------------------------"); + comppounding(10,20000,0.08); + comppounding(20,20000,0.08); + comppounding(30,20000,0.08); + System.out.println("-----------------------------------------------"); + comppounding(10,20000,0.1); + comppounding(20,20000,0.1); + comppounding(30,20000,0.1); + System.out.println("-----------------------------------------------"); + comppounding(10,10000,0.045); + comppounding(20,10000,0.045); + comppounding(30,10000,0.045); + System.out.println("-----------------------------------------------"); + comppounding(10,20000,0.045); + comppounding(20,20000,0.045); + comppounding(30,20000,0.045); + comppounding(40,20000,0.045); + comppounding(50,20000,0.045); + } + + /** + * 复利计算 小程序 + */ + private static void comppounding(int year,int money,double rate){ + double sum=0; + for(int i=0;i queue; + int k=0; + public KthLargest(int k, int[] nums) { + queue=new PriorityQueue(k); + this.k=k; + for (int num : nums) { + add(num); + } + } + + public int add(int val) { + if(queue.size() max){ + max = level + } + dfs(root.left, level + 1, max) + dfs(root.right, level + 1, max) +} diff --git a/Week_03/id_11/LeetCode_429_11.js b/Week_03/id_11/LeetCode_429_11.js new file mode 100644 index 00000000..ab0816b4 --- /dev/null +++ b/Week_03/id_11/LeetCode_429_11.js @@ -0,0 +1,38 @@ +/** + * // Definition for a Node. + * function Node(val,children) { + * this.val = val; + * this.children = children; + * }; + */ +/** + * @param {Node} root + * @return {number[][]} + */ +var levelOrder = function(root) { + + let list = [] + let level = 0 + + bfs(root, level, list) + + return list +}; + +var bfs = function(root, level, list){ + if(root == null) return + + if(list[level] == null){ + list[level] = [] + } + + list[level].push(root.val) + + root.children.forEach(child =>{ + bfs(child, level + 1, list) + }) +} + +let root = {"$id":"1","children":[{"$id":"2","children":[{"$id":"5","children":[],"val":5},{"$id":"6","children":[],"val":6}],"val":3},{"$id":"3","children":[],"val":2},{"$id":"4","children":[],"val":4}],"val":1} + +console.log(levelOrder(root)); diff --git a/Week_03/id_12/LeetCode_200_012.java b/Week_03/id_12/LeetCode_200_012.java new file mode 100644 index 00000000..bf08ce03 --- /dev/null +++ b/Week_03/id_12/LeetCode_200_012.java @@ -0,0 +1,55 @@ +//Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water. +// +// Example 1: +// +// +//Input: +//11110 +//11010 +//11000 +//00000 +// +//Output: 1 +// +// +// Example 2: +// +// +//Input: +//11000 +//11000 +//00100 +//00011 +// +//Output: 3 +// + + +class Solution { + + int[] x = {1, 0, -1, 0}; + int[] y = {0, -1, 0, 1}; + + public int numIslands(char[][] grid) { + int count = 0; + for (int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid[i].length; j++) { + if (grid[i][j] == '1') { + count++; + sink(grid, i, j); + } + } + } + return count; + } + + private void sink(char[][] grid, int i, int j) { + if (i < 0 || j < 0 || i > grid.length - 1 || j > grid[i].length - 1 || grid[i][j] == '0') { + return; + } + grid[i][j] = '0'; + for (int index = 0; index < 4; index++) { + sink(grid, i + x[index], j + y[index]); + } + } +} \ No newline at end of file diff --git a/Week_03/id_12/LeetCode_210_012.java b/Week_03/id_12/LeetCode_210_012.java new file mode 100644 index 00000000..33c43150 --- /dev/null +++ b/Week_03/id_12/LeetCode_210_012.java @@ -0,0 +1,42 @@ +class Solution { + + public int[] findOrder(int numCourses, int[][] prerequisites) { + List[] course = new List[numCourses]; + int[] map = new int[numCourses]; + List resultList = new ArrayList(); + for (int i = 0; i < numCourses; i++) { + course[i] = new ArrayList(); + } + for (int i = 0; i < prerequisites.length; i++) { + course[prerequisites[i][0]].add(prerequisites[i][1]); + } + for (int i = 0; i < numCourses; i++) { + if (!dfs(course, i, resultList, map)) { + return new int[0]; + } + } + int[] an = new int[resultList.size()]; + for (int i = 0; i < resultList.size(); i++) { + an[i] = resultList.get(i); + } + return an; + } + + private boolean dfs(List[] course, int req, List list, int[] map) { + if (map[req] == 0) { + map[req] = 1; + for (int i = 0; i < course[req].size(); i++) { + if (!dfs(course, (int) course[req].get(i), list, map)) { + return false; + } + } + map[req] = 2; + } else if (map[req] == 1) { + return false; + } else if (map[req] == 2) { + return true; + } + list.add(req); + return true; + } +} \ No newline at end of file diff --git a/Week_03/id_12/LeetCode_295_012.java b/Week_03/id_12/LeetCode_295_012.java new file mode 100644 index 00000000..09a6a12c --- /dev/null +++ b/Week_03/id_12/LeetCode_295_012.java @@ -0,0 +1,21 @@ +class MedianFinder { + + PriorityQueue min = new PriorityQueue(); + PriorityQueue max = new PriorityQueue(1000, Collections.reverseOrder()); + + public void addNum(int num) { + max.offer(num); + min.offer(max.poll()); + if (max.size() < min.size()) { + max.offer(min.poll()); + } + } + + public double findMedian() { + if (max.size() == min.size()) { + return (max.peek() + min.peek()) / 2.0; + } else { + return max.peek(); + } + } +}; \ No newline at end of file diff --git a/Week_03/id_12/LeetCode_703_012.java b/Week_03/id_12/LeetCode_703_012.java new file mode 100644 index 00000000..adaafd92 --- /dev/null +++ b/Week_03/id_12/LeetCode_703_012.java @@ -0,0 +1,23 @@ +class KthLargest { + + final PriorityQueue q; + final int k; + + public KthLargest(int k, int[] a) { + this.k = k; + q = new PriorityQueue<>(k); + for (int n : a) { + add(n); + } + } + + public int add(int n) { + if (q.size() < k) { + q.offer(n); + } else if (q.peek() < n) { + q.poll(); + q.offer(n); + } + return q.peek(); + } +} \ No newline at end of file diff --git a/Week_03/id_12/NOTE.md b/Week_03/id_12/NOTE.md deleted file mode 100644 index 107ea7d6..00000000 --- a/Week_03/id_12/NOTE.md +++ /dev/null @@ -1 +0,0 @@ -# 学习笔记 diff --git "a/Week_03/id_12/\345\255\246\344\271\240\346\200\273\347\273\223.md" "b/Week_03/id_12/\345\255\246\344\271\240\346\200\273\347\273\223.md" new file mode 100644 index 00000000..be6d9377 --- /dev/null +++ "b/Week_03/id_12/\345\255\246\344\271\240\346\200\273\347\273\223.md" @@ -0,0 +1,2 @@ +# 学习笔记 +首先感觉作业题目越来越难了,第200题老师上课讲过了,对小岛沉没这种解法很有印象,也安装老师要求的用两个数组来表示方向,算是一次课堂温习;第210题,刚开始题目没有看清楚,不清楚第一个参数的作业,提醒自己以后审题一定要仔细,感觉这题的数据结构很像Java中的HashMap,可以借鉴着来理解;第295题感觉用优先队列来解决太巧妙了,学到了一招;第703题算是对优先队列的又一次灵活应用。 \ No newline at end of file diff --git a/Week_03/id_14/LeetCode_104_14.py.txt b/Week_03/id_14/LeetCode_104_14.py.txt new file mode 100644 index 00000000..aabcb306 --- /dev/null +++ b/Week_03/id_14/LeetCode_104_14.py.txt @@ -0,0 +1,14 @@ +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class Solution(object): + def maxDepth(self, root): + """ + :type root: TreeNode + :rtype: int + """ + return 1 + max(map(self.maxDepth, (root.left, root.right))) if root else 0 \ No newline at end of file diff --git a/Week_03/id_14/LeetCode_429_14.py.txt b/Week_03/id_14/LeetCode_429_14.py.txt new file mode 100644 index 00000000..ddd5f589 --- /dev/null +++ b/Week_03/id_14/LeetCode_429_14.py.txt @@ -0,0 +1,27 @@ +""" +# Definition for a Node. +class Node(object): + def __init__(self, val, children): + self.val = val + self.children = children +""" +class Solution(object): + def levelOrder(self, root): + """ + :type root: Node + :rtype: List[List[int]] + """ + if not root: + return [] + res = [] + stack = [root] + while stack: + temp = [] + next_stack = [] + for node in stack: + temp.append(node.val) + for child in node.children: + next_stack.append(child) + stack = next_stack + res.append(temp) + return res \ No newline at end of file diff --git a/Week_03/id_14/LeetCode_703_14.py.txt b/Week_03/id_14/LeetCode_703_14.py.txt new file mode 100644 index 00000000..4230002e --- /dev/null +++ b/Week_03/id_14/LeetCode_703_14.py.txt @@ -0,0 +1,26 @@ +import heapq + +class KthLargest(object): + + def __init__(self, k, nums): + """ + :type k: int + :type nums: List[int] + """ + self.nums = nums + self.k = k + heapq.heapify(self.nums) + while len(self.nums) > k: + heapq.heappop(self.nums) + + + def add(self, val): + if len(self.nums) < self.k: + heapq.heappush(self.nums, val) + elif val > self.nums[0]: + heapq.heapreplace(self.nums, val) + return self.nums[0] + +# Your KthLargest object will be instantiated and called as such: +# obj = KthLargest(k, nums) +# param_1 = obj.add(val) \ No newline at end of file diff --git a/Week_03/id_15/LeetCode_200_015.py b/Week_03/id_15/LeetCode_200_015.py new file mode 100644 index 00000000..284862b6 --- /dev/null +++ b/Week_03/id_15/LeetCode_200_015.py @@ -0,0 +1,26 @@ +class Solution: + def numIslands(self, grid: List[List[str]]) -> int: + num_islands = 0 + + for row in range(len(grid)): + for column in range(len(grid[0])): + if grid[row][column] == '1': + num_islands += 1 + self.island_dfs(grid, row, column) + + return num_islands + + def island_dfs(self, grid, row, column): + min_row, max_row = 0, len(grid) - 1 + min_column, max_column = 0, len(grid[0]) - 1 + + if (not min_row <= row <= max_row) or (not min_column <= column <= max_column): + return + elif grid[row][column] != '1': + return + else: + grid[row][column] = '0' + self.island_dfs(grid, row-1, column) + self.island_dfs(grid, row+1, column) + self.island_dfs(grid, row, column-1) + self.island_dfs(grid, row, column+1) diff --git a/Week_03/id_15/LeetCode_210_015.py b/Week_03/id_15/LeetCode_210_015.py new file mode 100644 index 00000000..56b76a57 --- /dev/null +++ b/Week_03/id_15/LeetCode_210_015.py @@ -0,0 +1,33 @@ +class Solution: + def dfs(self, n, g, flags, seqs): + if flags[n] == 0: return False + if flags[n] == 1: return True + + flags[n] = 0 + for m in g[n]: + if not self.dfs(m,g,flags,seqs): return False + flags[n] = 1 + seqs.append(n) + return True + + def findOrder(self, numCourses, prerequisites): + """ + :type numCourses: int + :type prerequisites: List[List[int]] + :rtype: List[int] + """ + + g = [[] for _ in range(numCourses)] + for b,a in prerequisites: + g[a].append(b) + + # -1: not visited + # 0: visiting + # 1: visited + flags = [-1]*numCourses + seqs = [] + for i in range(numCourses): + if not self.dfs(i,g,flags,seqs): return [] + + seqs = seqs[::-1] + return seqs diff --git a/Week_03/id_15/NOTE.md b/Week_03/id_15/NOTE.md index 107ea7d6..f1e5a245 100644 --- a/Week_03/id_15/NOTE.md +++ b/Week_03/id_15/NOTE.md @@ -1 +1,19 @@ # 学习笔记 + +## 日常计划 + - 完成相对应的算法习题 + +## 心得交流 + - 本周和小组同学一起线下交流了一整个下午,大家非常认真的梳理了数据结构和算法的基本知识脉络。 + - 除了算法以外的分享外,同学们还给讲解了开发一般流程,记录如下: + - 需求沟通:产品经理与需求提出方进行需求沟通与分析,明确任务 + - 可行性分析:产品经理与程序员沟通,敲定可行性以及具体的使用语言与框架 + - 程序开发: + - 数据库人员建ER关系图 + - 开发人员进行程序开发 + - 程序测试 + - 产品交付与持续迭代 + +## 下周计划 + - 复刷之前做过的算法题和尚未完成的新题 + - 完成新一周的算法作业 diff --git a/Week_03/id_17/LeetCode_200_17.go b/Week_03/id_17/LeetCode_200_17.go new file mode 100644 index 00000000..f1dcdedd --- /dev/null +++ b/Week_03/id_17/LeetCode_200_17.go @@ -0,0 +1,32 @@ +/* + * @lc app=leetcode id=200 lang=golang + * + * [200] Number of Islands + */ +func numIslands(grid [][]byte) int { + result := 0 + for i, v1 := range grid { + for j, v2 := range v1 { + if v2 == '1' { + sink(i, j, grid) + result++ + } + } + } + return result +} + +func sink(x, y int, grid [][]byte) { + xlength := len(grid) + ylength := len(grid[0]) + if x < 0 || y < 0 || x >= xlength || y >= ylength || grid[x][y] != '1' { + return + } + grid[x][y] = '0' + sink(x-1, y, grid) + sink(x, y-1, grid) + sink(x+1, y, grid) + sink(x, y+1, grid) +} + + diff --git a/Week_03/id_17/LeetCode_547_17.go b/Week_03/id_17/LeetCode_547_17.go new file mode 100644 index 00000000..067713e6 --- /dev/null +++ b/Week_03/id_17/LeetCode_547_17.go @@ -0,0 +1,26 @@ +/* + * @lc app=leetcode id=547 lang=golang + * + * [547] Friend Circles + */ +func findCircleNum(M [][]int) int { + memo := make([]int, len(M)) + result := 0 + for i, v := range memo { + if v == 0 { + _dfs(memo, M, i) + result++ + } + } + return result +} + +func _dfs(memo []int, M [][]int, j int) { + for i := 0; i < len(M); i++ { + if memo[i] == 0 && M[i][j] == 1 { + memo[i] = 1 + _dfs(memo, M, i) + } + } +} + diff --git a/Week_03/id_18/LeetCode_102_18.java b/Week_03/id_18/LeetCode_102_18.java new file mode 100644 index 00000000..2de84cc8 --- /dev/null +++ b/Week_03/id_18/LeetCode_102_18.java @@ -0,0 +1,81 @@ +package Week_03.id_18; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; + +/** + * @author LiveForExperience + * @date 2019/6/21 13:18 + */ +public class LeetCode_102_18 { + public List> levelOrder(TreeNode root) { + List> result = new ArrayList<>(); + if (root == null) { + return result; + } + + Queue queue = new ArrayDeque<>(); + queue.offer(root); + + while (!queue.isEmpty()) { + int count = queue.size(); + List nodeLevel = new ArrayList<>(); + + while (count-- > 0) { + TreeNode node = queue.poll(); + nodeLevel.add(node.val); + + if (node.left != null) { + queue.offer(node.left); + } + + if (node.right != null) { + queue.offer(node.right); + } + } + + result.add(nodeLevel); + } + + return result; + } + + private List> levels = new ArrayList<>(); + + public List> levelOrder1(TreeNode root) { + if (root == null) { + return levels; + } + + dfs(root, 0); + return levels; + } + + private void dfs(TreeNode node, int level) { + if (levels.size() == level) { + levels.add(new ArrayList<>()); + } + + levels.get(level).add(node.val); + + if (node.left != null) { + dfs(node.left, level + 1); + } + + if (node.right != null) { + dfs(node.right, level + 1); + } + } + + private class TreeNode { + int val; + TreeNode left; + TreeNode right; + + TreeNode(int x) { + val = x; + } + } +} diff --git a/Week_03/id_18/LeetCode_104_18.java b/Week_03/id_18/LeetCode_104_18.java new file mode 100644 index 00000000..adee692f --- /dev/null +++ b/Week_03/id_18/LeetCode_104_18.java @@ -0,0 +1,88 @@ +package Week_03.id_18; + +import java.util.ArrayDeque; +import java.util.Queue; +import java.util.Stack; + +/** + * @author LiveForExperience + * @date 2019/6/17 18:03 + */ +public class LeetCode_104_18 { + public int maxDepth(TreeNode root) { + return doSearch(0, root); + } + + private int doSearch(int level, TreeNode root) { + if (root == null) { + return level; + } + + level++; + + return Math.max(doSearch(level, root.left), doSearch(level, root.right)); + } + + private Stack nodeStack = new Stack<>(); + private Stack countStack = new Stack<>(); + + public int maxDepth1(TreeNode root) { + nodeStack.push(root); + int max = 0; + + while (!nodeStack.empty()) { + TreeNode node = nodeStack.pop(); + int count = countStack.pop(); + max = Math.max(max, count); + + drillDownAndCount(node.left, count); + drillDownAndCount(node.right, count); + } + + return max; + } + + private void drillDownAndCount(TreeNode node, int count) { + if (node != null) { + nodeStack.push(node); + countStack.push(count + 1); + } + } + + public int maxDepth2(TreeNode root) { + if (root == null) { + return 0; + } + + Queue queue = new ArrayDeque<>(); + int count = 0; + queue.offer(root); + + while (!queue.isEmpty()) { + int nodeNum = queue.size(); + while (nodeNum-- > 0) { + TreeNode node = queue.poll(); + if (node.left != null) { + queue.offer(node.left); + } + + if (node.right != null) { + queue.offer(node.right); + } + } + count++; + } + + return count; + } + + private class TreeNode { + int val; + TreeNode left; + TreeNode right; + + TreeNode(int x) { + val = x; + } + } +} diff --git a/Week_03/id_18/LeetCode_111_18.java b/Week_03/id_18/LeetCode_111_18.java new file mode 100644 index 00000000..f5a735aa --- /dev/null +++ b/Week_03/id_18/LeetCode_111_18.java @@ -0,0 +1,113 @@ +package Week_03.id_18; + +import java.util.ArrayDeque; +import java.util.Queue; +import java.util.Stack; + +/** + * @author LiveForExperience + * @date 2019/6/12 21:50 + */ +public class LeetCode_111_18 { + public int minDepth(TreeNode root) { + if (root == null) { + return 0; + } + + if (root.left == null && root.right == null) { + return 1; + } + + int depth = Integer.MAX_VALUE; + if (root.left != null) { + depth = Math.min(minDepth(root.left), depth); + } + + if (root.right != null) { + depth = Math.min(minDepth(root.right), depth); + } + + return depth + 1; + } + + public int minDepth1(TreeNode root) { + if (root == null) { + return 0; + } + + if (root.left == null && root.right == null) { + return 1; + } + + Stack nodeStack = new Stack<>(); + Stack countStack = new Stack<>(); + + nodeStack.push(root); + countStack.push(1); + + int min = Integer.MAX_VALUE; + + while (!nodeStack.empty()) { + TreeNode node = nodeStack.pop(); + int count = countStack.pop(); + + if (node.left == null && node.right == null) { + min = Math.min(count, min); + } + + if (node.left != null) { + nodeStack.push(node.left); + countStack.push(count + 1); + } + + if (node.right != null) { + nodeStack.push(node.right); + countStack.push(count + 1); + } + } + + return min; + } + + public int minDepth2(TreeNode root) { + if (root == null) { + return 0; + } + + if (root.left == null && root.right == null) { + return 1; + } + + Queue queue = new ArrayDeque<>(); + int count = 0; + queue.offer(root); + while (!queue.isEmpty()) { + int nodeSize = queue.size(); + count++; + + while (nodeSize-- > 0) { + TreeNode node = queue.poll(); + if (node.right == null && node.left == null) { + return count; + } + + if (node.left != null) { + queue.offer(node.left); + } + + if (node.right != null) { + queue.offer(node.right); + } + } + } + + return count; + } + + private class TreeNode { + int val; + TreeNode left; + TreeNode right; + TreeNode(int x) { val = x; } + } +} diff --git a/Week_03/id_18/LeetCode_200_18.java b/Week_03/id_18/LeetCode_200_18.java new file mode 100644 index 00000000..d6c3b150 --- /dev/null +++ b/Week_03/id_18/LeetCode_200_18.java @@ -0,0 +1,42 @@ +package Week_03.id_18; + +/** + * @author LiveForExperience + * @date 2019/6/17 10:17 + */ +public class LeetCode_200_18 { + private int rowNum; + private int colNum; + + public int numIslands(char[][] grid) { + int count = 0; + rowNum = grid.length; + if (rowNum == 0) { + return 0; + } + colNum = grid[0].length; + + for (int row = 0; row < rowNum; row++) { + for (int col = 0; col < colNum; col++) { + if (grid[row][col] == '1') { + drown(grid, row, col); + count++; + } + } + } + + return count; + } + + private void drown(char[][] grid, int row, int col) { + if (row < 0 || row >= rowNum || col < 0 || col>= colNum || grid[row][col] != '1') { + return; + } + + grid[row][col] = '0'; + drown(grid, row + 1, col); + drown(grid, row, col + 1); + drown(grid, row - 1, col); + drown(grid, row, col - 1); + } +} diff --git a/Week_03/id_18/LeetCode_210_18.java b/Week_03/id_18/LeetCode_210_18.java new file mode 100644 index 00000000..0b8dcdba --- /dev/null +++ b/Week_03/id_18/LeetCode_210_18.java @@ -0,0 +1,51 @@ +package Week_03.id_18; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author LiveForExperience + * @date 2019/6/19 12:09 + */ +public class LeetCode_210_18 { + public static void main(String[] args) { + LeetCode_210_18 test = new LeetCode_210_18(); + test.findOrder(2, new int[][]{{1,0}}); + } + + public int[] findOrder(int numCourses, int[][] prerequisites) { + int[] result = new int[numCourses]; + int[] record = new int[numCourses]; + Map> map = new HashMap<>(); + for (int[] arr: prerequisites) { + int des = arr[0]; + int src = arr[1]; + map.computeIfAbsent(src, k -> new ArrayList<>()); + map.get(src).add(des); + + record[des]++; + } + + Queue queue = new ArrayDeque<>(); + for (int i = 0; i < record.length; i++) { + if (record[i] == 0) { + queue.offer(i); + } + } + + int i = 0; + while (!queue.isEmpty()) { + Integer lesson = queue.poll(); + result[i++] = lesson; + if (map.get(lesson) != null) { + for (Integer desLesson: map.get(lesson)) { + if (--record[desLesson] == 0) { + queue.offer(desLesson); + } + } + } + } + + return i == numCourses ? result: new int[0]; + } +} diff --git a/Week_03/id_18/LeetCode_295_18.java b/Week_03/id_18/LeetCode_295_18.java new file mode 100644 index 00000000..9317e77e --- /dev/null +++ b/Week_03/id_18/LeetCode_295_18.java @@ -0,0 +1,62 @@ +package Week_03.id_18; + +import java.util.*; + +/** + * @author LiveForExperience + * @date 2019/6/20 12:23 + */ +public class LeetCode_295_18 { + private int count; + private Queue maxHeap; + private Queue minHeap; + + public LeetCode_295_18() { + maxHeap = new PriorityQueue<>(Comparator.reverseOrder()); + minHeap = new PriorityQueue<>(); + } + + public void addNum(int num) { + count++; + maxHeap.offer(num); + minHeap.offer(maxHeap.poll()); + if ((count & 1) == 1) { + maxHeap.offer(minHeap.poll()); + } + } + + public double findMedian() { + return (count & 1) == 0 ? (new Double(maxHeap.peek()) + new Double(minHeap.peek())) / 2 : maxHeap.peek(); + } + + private List list = new ArrayList<>(); + + public void addNum1(int num) { + if (list.isEmpty()) { + list.add(num); + return; + } + + int left = 0, right = list.size() - 1; + + while (left < right) { + int mid = left + (right - left) / 2, val = list.get(mid); + if (num < val) { + right = mid; + } else { + left = mid + 1; + } + } + + if (list.get(list.size() - 1) < num) { + list.add(num); + } else { + list.add(left, num); + } + } + + public double findMedian1() { + int len = list.size(), midNum = len / 2; + return (len & 1) == 0 ? ((double) list.get(midNum - 1) + (double) list.get(midNum)) / 2 : list.get(midNum); + } +} diff --git a/Week_03/id_18/LeetCode_310_18.java b/Week_03/id_18/LeetCode_310_18.java new file mode 100644 index 00000000..e0b90688 --- /dev/null +++ b/Week_03/id_18/LeetCode_310_18.java @@ -0,0 +1,47 @@ +package Week_03.id_18; + +import java.util.*; + +/** + * @author LiveForExperience + * @date 2019/6/24 11:59 + */ +public class LeetCode_310_18 { + public List findMinHeightTrees(int n, int[][] edges) { + if (n == 1) { + return Collections.singletonList(0); + } + + List> list = new ArrayList<>(n); + for (int i = 0; i < n; i++) { + list.add(new HashSet<>()); + } + for (int[] edge: edges) { + list.get(edge[0]).add(edge[1]); + list.get(edge[1]).add(edge[0]); + } + + List leaves = new ArrayList<>(); + for (int i = 0; i < n; i++) { + if (list.get(i).size() == 1) { + leaves.add(i); + } + } + + while (n > 2) { + n -= leaves.size(); + + List newLeaves = new ArrayList<>(); + for (int leave: leaves) { + int node = list.get(leave).iterator().next(); + list.get(node).remove(leave); + if (list.get(node).size() == 1) { + newLeaves.add(node); + } + } + leaves = newLeaves; + } + + return leaves; + } +} diff --git a/Week_03/id_18/LeetCode_429_18.java b/Week_03/id_18/LeetCode_429_18.java new file mode 100644 index 00000000..435c8c30 --- /dev/null +++ b/Week_03/id_18/LeetCode_429_18.java @@ -0,0 +1,48 @@ +package Week_03.id_18; + +import java.util.*; + +/** + * @author LiveForExperience + * @date 2019/6/18 12:53 + */ +public class LeetCode_429_18 { + public List> levelOrder(Node root) { + List> result = new ArrayList<>(); + + if (root == null) { + return result; + } + + Queue queue = new ArrayDeque<>(); + queue.offer(root); + + while (!queue.isEmpty()) { + int count = queue.size(); + List levelNodeVals = new ArrayList<>(count); + while (count-- > 0) { + Node node = queue.poll(); + levelNodeVals.add(node.val); + for (Node childNode: node.children) { + queue.offer(childNode); + } + } + + result.add(levelNodeVals); + } + + return result; + } + + private class Node { + public int val; + public List children; + + public Node() {} + + public Node(int _val,List _children) { + val = _val; + children = _children; + } + }; +} diff --git a/Week_03/id_18/LeetCode_547_18.java b/Week_03/id_18/LeetCode_547_18.java new file mode 100644 index 00000000..e5505967 --- /dev/null +++ b/Week_03/id_18/LeetCode_547_18.java @@ -0,0 +1,62 @@ +package Week_03.id_18; + +/** + * @author LiveForExperience + * @date 2019/6/22 19:07 + */ +public class LeetCode_547_18 { + public int findCircleNum(int[][] M) { + UnionFind uf = new UnionFind(M.length); + for (int i = 0; i < M.length; i++) { + for (int j = 0; j < M.length; j++) { + if (M[i][j] == 1) { + uf.union(i, j); + } + } + } + return uf.count; + } + + private class UnionFind { + private int count; + private int[] parent; + private int[] rank; + + UnionFind(int n) { + this.count = n; + this.parent = new int[n]; + this.rank = new int[n]; + for (int i = 0; i < n; i++) { + parent[i] = i; + rank[i] = 1; + } + } + + int find(int n) { + while (n != this.parent[n]) { + this.parent[n] = this.parent[this.parent[n]]; + n = this.parent[n]; + } + return n; + } + + void union(int a, int b) { + int rootA = find(a); + int rootB = find(b); + if (rootA == rootB) { + return; + } + + if (rank[rootA] < rank[rootB]) { + parent[rootA] = rootB; + } else if (rank[rootA] > rank[rootB]) { + parent[rootB] = rootA; + } else { + parent[rootB] = rootA; + rank[rootA]++; + } + + count--; + } + } +} diff --git a/Week_03/id_18/LeetCode_703_18.java b/Week_03/id_18/LeetCode_703_18.java new file mode 100644 index 00000000..74e9d545 --- /dev/null +++ b/Week_03/id_18/LeetCode_703_18.java @@ -0,0 +1,34 @@ +package Week_03.id_18; + +import java.util.*; + +/** + * @author LiveForExperience + * @date 2019/6/17 12:32 + */ +public class LeetCode_703_18 { + private Queue queue; + private int k; + + public LeetCode_703_18(int k, int[] nums) { + this.k = k; + this.queue = new PriorityQueue<>(k); + for (int num: nums) { + offer(num); + } + } + + public int add(int val) { + offer(val); + return this.queue.peek(); + } + + private void offer(int num) { + if (this.queue.size() < this.k) { + this.queue.offer(num); + } else if (this.queue.peek() < num) { + this.queue.poll(); + this.queue.offer(num); + } + } +} diff --git a/Week_03/id_18/NOTE.md b/Week_03/id_18/NOTE.md index 107ea7d6..24ac365e 100644 --- a/Week_03/id_18/NOTE.md +++ b/Week_03/id_18/NOTE.md @@ -1 +1,999 @@ # 学习笔记 +## LeetCode_200 +### 题目 +给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。 + +示例 1: +``` +输入: +11110 +11010 +11000 +00000 + +输出: 1 +``` +示例 2: +``` +输入: +11000 +11000 +00100 +00011 + +输出: 3 +``` +### 解法一 +#### 思路 +使用dfs的思路,从当前方块的上下左右递归的执行逻辑。 +1. 对二维数组进行遍历,只要发现是1,就开始执行逻辑,同时计数+1 +2. 逻辑内容是: + - 从这个为1的方块开始,对它的上下左右递归检查 + - 递归下钻中只要发现仍然是1的,就把这个为1的方块设置为0,这样在最外层遍历的时候,就不会重复的进到这里执行逻辑了,也可以理解成已经检查过 + - 如果行列的坐标超出了二维数组的边界,或者遇到的是0的时候,就返回 +3. 在二维数组遍历结束以后,就返回计数值即可 +#### 代码 +```java +class Solution { + private int rowNum; + private int colNum; + + public int numIslands(char[][] grid) { + int count = 0; + rowNum = grid.length; + if (rowNum == 0) { + return 0; + } + colNum = grid[0].length; + + for (int row = 0; row < rowNum; row++) { + for (int col = 0; col < colNum; col++) { + if (grid[row][col] == '1') { + drown(grid, row, col); + count++; + } + } + } + + return count; + } + + private void drown(char[][] grid, int row, int col) { + if (row < 0 || row >= rowNum || col < 0 || col>= colNum || grid[row][col] != '1') { + return; + } + + grid[row][col] = '0'; + drown(grid, row + 1, col); + drown(grid, row, col + 1); + drown(grid, row - 1, col); + drown(grid, row, col - 1); + } +} +``` +### 收获 +这个解法是从国际站上看来的,也记得覃老师也在课上讲过,思路非常巧妙,代码也非常简洁。真的很赞。 +## LeetCode_703 +### 题目 +设计一个找到数据流中第K大元素的类(class)。注意是排序后的第K大元素,不是第K个不同的元素。 + +你的 KthLargest 类需要一个同时接收整数 k 和整数数组nums 的构造器,它包含数据流中的初始元素。每次调用 KthLargest.add,返回当前数据流中第K大的元素。 + +示例: +``` +int k = 3; +int[] arr = [4,5,8,2]; +KthLargest kthLargest = new KthLargest(3, arr); +kthLargest.add(3);   // returns 4 +kthLargest.add(5);   // returns 5 +kthLargest.add(10);  // returns 5 +kthLargest.add(9);   // returns 8 +kthLargest.add(4);   // returns 8 +说明: +你可以假设 nums 的长度≥ k-1 且k ≥ 1。 +``` +### 失败的解法 +#### 思路 +1. 将数组排序,截取最大的k个 +2. 每次add的时候都和第一个元素比较,如果比它大,就先替换 +3. 然后对数组重新排序 +4. 返回数组的第一个元素 + +这种计算的结果是超出限制时间,看了leetcode的测试用例,k非常大,因为我每次都要在add的时候对数组进行排序,所以非常耗时。 +#### 代码 +```java +class KthLargest { + int[] nums; + int k; + + public KthLargest(int k, int[] nums) { + this.k = k; + Arrays.sort(nums); + this.nums = nums.length < k ? nums : Arrays.copyOfRange(nums, nums.length - k, nums.length); + } + + public int add(int val) { + if (nums.length < k) { + nums = Arrays.copyOf(nums, nums.length + 1); + nums[nums.length - 1] = val; + } else if (nums[0] < val){ + nums[0] = val; + } + + Arrays.sort(nums); + return nums[0]; + } +} +``` +### 解法一 +#### 思路 +使用优先级队列,使用升序排序 +1. 因为是升序队列,队列顶部会是入队元素中最小的一个 +2. 在队列不足k个元素的时候随意入队 +3. 当队列个数等于k个后,队顶的那个元素就可以和之后入队的元素进行比较,比队大的就进行替换,一直保持队列中保持所有元素最大的k个 +4. 结果就直接返回队顶元素 +#### 代码 +```java +class KthLargest { + private Queue queue; + private int k; + + public KthLargest(int k, int[] nums) { + this.k = k; + this.queue = new PriorityQueue<>(k); + for (int num: nums) { + offer(num); + } + } + + public int add(int val) { + offer(val); + return this.queue.peek(); + } + + private void offer(int num) { + if (this.queue.size() < this.k) { + this.queue.offer(num); + } else if (this.queue.peek() > num) { + this.queue.poll(); + this.queue.offer(num); + } + } +} +``` +### 收获 +学习到了PriorityQueue的用法,平常不太使用。 +## LeetCode_104 +### 题目 +给定一个二叉树,找出其最大深度。 + +二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。 + +说明: 叶子节点是指没有子节点的节点。 + +示例: +``` +给定二叉树 [3,9,20,null,null,15,7], + + 3 + / \ + 9 20 + / \ + 15 7 +返回它的最大深度 3 。 +``` +### 解法一 +#### 思路 +dfs非递归 +1. 两个stack分别存当前下钻的那个节点node,及下钻时的深度count,还有一个max变量存最大值 +2. 遍历nodeStack的时候,将node和count分别出栈,计算count和max的最大值 +3. 上面一步干完后,开始准备下钻,分别走左右两边,判断是否为空 +4. 不为空就把对应一边的节点入栈,同时count+1以后也入栈,开始下一步 +5. 最后返回max +#### 代码 +```java +class Solution { + private Stack nodeStack = new Stack<>(); + private Stack countStack = new Stack<>(); + + public int maxDepth(TreeNode root) { + if (root == null) { + return 0; + } + + nodeStack.push(root); + countStack.push(1); + int max = 0; + + while (!nodeStack.empty()) { + TreeNode node = nodeStack.pop(); + int count = countStack.pop(); + max = Math.max(max, count); + + drillDownAndCount(node.left, count); + drillDownAndCount(node.right, count); + } + + return max; + } + + private void drillDownAndCount(TreeNode node, int count) { + if (node != null) { + nodeStack.push(node); + countStack.push(count + 1); + } + } +} +``` +### 解法二 +#### 思路 +dfs递归,和解法一思路差不多,但是代码简单不少 +1. 建一个函数,用来递归,有两个参数分别是上一层层数和当前层节点 +2. 如果节点为空,就把上一层的层数返回 +3. 否则就在层数上+1,标记这一层探索过,然后继续下钻 +4. 返回的时候是比左右节点的大小,取大的值 +#### 代码 +```java +public class Solution { + public int maxDepth(TreeNode root) { + return doSearch(0, root); + } + + private int doSearch(int level, TreeNode root) { + if (root == null) { + return level; + } + + level++; + + return Math.max(doSearch(level, root.left), doSearch(level, root.right)); + } +} +``` +### 解法三 +#### 思路 +使用bfs,思路和解法一、二略有不同,因为是广度优先搜索,所以不需要取比较左右子树节点返回的深度最大值,只需要一层层的扫就可以了。 +1. 一个队列存放当前层的节点 +2. 遍历队列,获得当前层节点的个数 +3. 然后分别再去判断这些节点是否有子节点,把那些子节点放入队列,作为下一层需要判断的节点。 +4. 同时在当前层对count值+1,计数 +5. 循环往复,最终返回count +#### 代码 +```java +class Solution { + public int maxDepth(TreeNode root) { + if (root == null) { + return 0; + } + + Queue queue = new ArrayDeque<>(); + int count = 0; + queue.offer(root); + + while (!queue.isEmpty()) { + int nodeNum = queue.size(); + while (nodeNum-- > 0) { + TreeNode node = queue.poll(); + if (node.left != null) { + queue.offer(node.left); + } + + if (node.right != null) { + queue.offer(node.right); + } + } + count++; + } + + return count; + } +} +``` +### 收获 +进一步熟练了dfs的2种解法,bfs的1种解法。 +## LeetCode_111 +### 题目 +给定一个二叉树,找出其最小深度。 + +最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 + +说明: 叶子节点是指没有子节点的节点。 + +示例: +``` +给定二叉树 [3,9,20,null,null,15,7], + + 3 + / \ + 9 20 + / \ + 15 7 +返回它的最小深度  2. +``` +### 解法一 +#### 思路 +和104题的思路是一样的,使用dfs的非递归方法,递归方法在第2周的时候写过 +1. 把root为空,root左右子树为空的情况先去掉 +2. 用nodeStack栈来保存dfs深度搜索使用的节点,维护顺序 +3. 用countStack栈来保存层数,维护顺序,和nodeStack顺序一致就可以 +4. 每次循环都把两个栈的第一个元素弹出,因为顺序一致,这两个出栈元素其实就代表了探索到的这个node和它所在的层数 +5. 当左右子树不为空的时候,分别把左右子树压入nodeStack栈,同时把count+1分别压入countStack栈 +6. 当nodeStack出栈的这个节点的左右子树都为空的时候,把count和min作比较,取小的那个 +7. 循环往复,最后返回min作为结果 +#### 代码 +```java +class Solution { + public int minDepth(TreeNode root) { + if (root == null) { + return 0; + } + + if (root.left == null && root.right == null) { + return 1; + } + + Stack nodeStack = new Stack<>(); + Stack countStack = new Stack<>(); + + nodeStack.push(root); + countStack.push(1); + + int min = Integer.MAX_VALUE; + + while (!nodeStack.empty()) { + TreeNode node = nodeStack.pop(); + int count = countStack.pop(); + + if (node.left == null && node.right == null) { + min = Math.min(count, min); + } + + if (node.left != null) { + nodeStack.push(node.left); + countStack.push(count + 1); + } + + if (node.right != null) { + nodeStack.push(node.right); + countStack.push(count + 1); + } + } + + return min; + } +} +``` +### 解法二 +#### 思路 +使用bfs来解这个题,遇到的第一个叶子节点,就把count返回,过程和104题的bfs解法类似,只不过不用走到最后 +#### 代码 +```java +class Solution { + public int minDepth(TreeNode root) { + if (root == null) { + return 0; + } + + if (root.left == null && root.right == null) { + return 1; + } + + Queue queue = new ArrayDeque<>(); + int count = 0; + queue.offer(root); + + while (!queue.isEmpty()) { + int nodeSize = queue.size(); + count++; + while (nodeSize-- > 0) { + TreeNode node = queue.poll(); + if (node.right == null && node.left == null) { + return count; + } + + if (node.left != null) { + queue.offer(node.left); + } + + if (node.right != null) { + queue.offer(node.right); + } + } + } + + return count; + } +} +``` +### 收获 +再一次的熟悉了dfs和bfs,做类似题有点快了。 +## LeetCode_429 +### 题目 +给定一个 N 叉树,返回其节点值的层序遍历。 (即从左到右,逐层遍历)。 + +例如,给定一个3叉树,返回其层序遍历: +``` +[ + [1], + [3,2,4], + [5,6] +] +``` + +说明: +``` +树的深度不会超过 1000。 +树的节点总数不会超过 5000。 +``` +### 解法一 +#### 思路 +使用bfs来解决这道题 +1. 使用队列,开始bfs +2. 每一层干两件事: + - 遍历当前层节点,并往队列里入下一层的节点 + - 把当前层的val放入当前层的list,再在当前层节点遍历完以后,放入整个结果的list +3. 循环结束,返回result +#### 代码 +```java +class Solution { + public List> levelOrder(Node root) { + List> result = new ArrayList<>(); + if (root == null) { + return result; + } + + Queue queue = new ArrayDeque<>(); + queue.offer(root); + + while (!queue.isEmpty()) { + int count = queue.size(); + List levelNodeVals = new ArrayList<>(count); + while (count-- > 0) { + Node node = queue.poll(); + levelNodeVals.add(node.val); + for (Node childNode: node.children) { + queue.offer(childNode); + } + } + + result.add(levelNodeVals); + } + + return result; + } +} +``` +### 收获 +又对bfs有了进一步的练习加深 +## LeetCode_210 +### 题目 +现在你总共有 n 门课需要选,记为 0 到 n-1。 + +在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1] + +给定课程总量以及它们的先决条件,返回你为了学完所有课程所安排的学习顺序。 + +可能会有多个正确的顺序,你只要返回一种就可以了。如果不可能完成所有课程,返回一个空数组。 + +示例 1: +``` +输入: 2, [[1,0]] +输出: [0,1] +解释: 总共有 2 门课程。要学习课程 1,你需要先完成课程 0。因此,正确的课程顺序为 [0,1] 。 +``` +示例 2: +``` +输入: 4, [[1,0],[2,0],[3,1],[3,2]] +输出: [0,1,2,3] or [0,2,1,3] +解释: 总共有 4 门课程。要学习课程 3,你应该先完成课程 1 和课程 2。并且课程 1 和课程 2 都应该排在课程 0 之后。 +  因此,一个正确的课程顺序是 [0,1,2,3] 。另一个正确的排序是 [0,2,1,3] 。 +``` +说明: +``` +输入的先决条件是由边缘列表表示的图形,而不是邻接矩阵。详情请参见图的表示法。 +你可以假定输入的先决条件中没有重复的边。 +``` +### 解法一 +#### 思路 +1. 使用bfs的方式。首先需要确定第一层节点 +2. 使用一个map,维护课程关系,**后修课程的节点**和**需要先修的课程节点们**的映射关系 +3. 在维护map的同时,也要维护一个**课程**和**需要先修课程数**的映射关系,因为这种要很多先修课程的课肯定是最后几个才能修的课,维护的课程数作为是否已学了先修课程的统计变量进行递减,直到为0,意味着已经可以直接修这门课了 +4. 把那个先修课程数为0的课程全部入队,这些就是**第一层的节点,那些不需要先修课程的课程**,开始进行bfs的while循环 +5. 在while语句种按老规矩出队第一层节点,把他们依次记录在result数组里 +6. 使用循环里出队的节点查询map种的下一层节点,把这些节点的先修课程数-1,因为当前课程在这次循环中相当于学完了 +7. 判断先修课程数是否为0,如果是,就可以入队,在下个循环中出队(**被学习**),同时也放到result数组里 +8. 最后判断result数组放满了没有,如果没有,就说明课程安排没法全部学完,否则就返回这个result +#### 代码 +```java +class Solution { + public int[] findOrder(int numCourses, int[][] prerequisites) { + int[] result = new int[numCourses]; + int[] record = new int[numCourses]; + Map> map = new HashMap<>(); + for (int[] arr: prerequisites) { + int des = arr[0]; + int src = arr[1]; + map.computeIfAbsent(src, k -> new ArrayList<>()); + map.get(src).add(des); + + record[des]++; + } + + Queue queue = new ArrayDeque<>(); + for (int i = 0; i < record.length; i++) { + if (record[i] == 0) { + queue.offer(i); + } + } + + int i = 0; + while (!queue.isEmpty()) { + Integer lesson = queue.poll(); + result[i++] = lesson; + if (map.get(lesson) != null) { + for (Integer desLesson: map.get(lesson)) { + if (--record[desLesson] == 0) { + queue.offer(desLesson); + } + } + } + } + + return i == numCourses ? result: new int[0]; + } +} +``` +### 收获 +这题上来看第一遍,是懵的 +1. 开始找脑中有没有对应的解法,或以前类似做过的,没有 +2. 然后开始自己想办法解,只有一点模糊的概念 +3. 在看了国际站的sol以后才有了具体的思路 + +但发现这个过程其实对我自己有很大的帮助,想过以后再看别人的解法,尤其是和自己脑中的大概思路类似的解法,理解起来就非常快,记忆也更深刻。 +## LeetCode_295 +### 题目 +中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。 + +例如, + +[2,3,4] 的中位数是 3 + +[2,3] 的中位数是 (2 + 3) / 2 = 2.5 + +设计一个支持以下两种操作的数据结构: +``` +void addNum(int num) - 从数据流中添加一个整数到数据结构中。 +double findMedian() - 返回目前所有元素的中位数。 +``` +示例: +``` +addNum(1) +addNum(2) +findMedian() -> 1.5 +addNum(3) +findMedian() -> 2 +``` +### 解法一 +#### 思路 +参考国内站的解法,使用两个堆来解决,反别是大顶堆和小顶堆 +1. 对两个堆设定2个前提: + - 大顶堆的堆顶元素永远小于或等于小顶堆的堆顶元素 + - 大顶堆的元素个数: + - 在总个数为奇数的时候比小顶堆多1个 + - 在总个数为偶数的时候和小顶堆一样 +2. 先将元素放入大顶堆排序,获得大顶堆中的最大值 +3. 再将这个最大值放入小顶堆中,获得小顶堆的最小值 +4. 如果这个时候总个数是奇数,就把小顶堆的那个堆顶元素还给大顶堆 +5. 通过以上3步就可以使得计算只围绕两个堆顶元素来进行 + - 奇数的时候,大顶堆的那个最大值就是中位数 + - 偶数的时候,两个堆的堆顶元素平均值就是中位数 +#### 代码 +```java +class MedianFinder { + private int count; + private Queue maxHeap; + private Queue minHeap; + /** initialize your data structure here. */ + public MedianFinder() { + maxHeap = new PriorityQueue<>(Comparator.reverseOrder()); + minHeap = new PriorityQueue<>(); + } + + public void addNum(int num) { + count++; + maxHeap.offer(num); + minHeap.offer(maxHeap.poll()); + if ((count & 1) == 1) { + maxHeap.offer(minHeap.poll()); + } + } + + public double findMedian() { + return (count & 1) == 0 ? (new Double(maxHeap.peek()) + new Double(minHeap.peek())) / 2 : maxHeap.peek(); + } +} +``` +### 失败解法 +#### 思路 +每次都进行排序,然后返回中位数,暴力简单。但是耗时超出了测试要求。 +#### 代码 +```java +class MedianFinder { + private List list; + + public MedianFinder() { + list = new ArrayList(); + } + + public void addNum(int num) { + list.add(num); + } + + public double findMedian() { + Collections.sort(list); + int midNum = list.size() / 2; + return (list.size() & 1) == 0 ? (new Double(list.get(midNum - 1)) + new Double(list.get(midNum))) / 2 : list.get(midNum); + } +} +``` +### 解法二 +#### 思路 +在失败解法的基础上发现,整个算法最耗时的部分就是排序,提升效率的方式就是加快排序。参考了国际站的解法。在**插入的时候对数组进行二分法排序找到需要插入的位置**。 +1. 确定left和right游标,设定一个循环条件left list; + + public MedianFinder() { + list = new ArrayList(); + } + + public void addNum(int num) { + if (list.isEmpty()) { + list.add(num); + return; + } + + int left = 0, right = list.size() - 1; + + while (left < right) { + int mid = left + (right - left) / 2, val = list.get(mid); + if (num < val) { + right = mid; + } else { + left = mid + 1; + } + } + + if (list.get(list.size() - 1) < num) { + list.add(num); + } else { + list.add(left, num); + } + } + + public double findMedian() { + int len = list.size(), midNum = len / 2; + return (len & 1) == 0 ? ((double) list.get(midNum - 1) + (double) list.get(midNum)) / 2 : list.get(midNum); + } +} +``` +### 收获 +1. 学到了使用两个堆来解这类确定中位数的方式,思路非常巧妙。 +2. 之后尝试的暴力解法,通过某一个部分的优化,也解出了问题,整个过程很有收获: + 1. 找到瓶颈 + 2. 尝试优化的方法 + 3. 如果失败,循环往复 +## LeetCode_102 +### 题目 +给定一个二叉树,返回其按层次遍历的节点值。 (即逐层地,从左到右访问所有节点)。 + +例如: +``` +给定二叉树: [3,9,20,null,null,15,7], + + 3 + / \ + 9 20 + / \ + 15 7 +``` +返回其层次遍历结果: +``` +[ + [3], + [9,20], + [15,7] +] +``` +### 解法一 +#### 思路 +这题和429题很相似,使用bfs方式,使用记录层数节点个数的count变量就可以了。 +#### 代码 +```java +class Solution { + public List> levelOrder(TreeNode root) { + List> result = new ArrayList<>(); + if (root == null) { + return result; + } + + Queue queue = new ArrayDeque<>(); + queue.offer(root); + + while (!queue.isEmpty()) { + int count = queue.size(); + List nodeLevel = new ArrayList<>(); + + while (count-- > 0) { + TreeNode node = queue.poll(); + nodeLevel.add(node.val); + + if (node.left != null) { + queue.offer(node.left); + } + + if (node.right != null) { + queue.offer(node.right); + } + } + + result.add(nodeLevel); + } + + return result; + } +} +``` +### 解法二 +#### 思路 +使用dfs递归方式,同时通过层级和数组下标的对应,在深度搜索过程中对指定的list里增加节点值 +#### 代码 +```java +class Solution { + private List> levels = new ArrayList<>(); + + public List> levelOrder(TreeNode root) { + if (root == null) { + return levels; + } + + dfs(root, 0); + return levels; + } + + private void dfs(TreeNode node, int level) { + if (levels.size() == level) { + levels.add(new ArrayList<>()); + } + + levels.get(level).add(node.val); + + if (node.left != null) { + dfs(node.left, level + 1); + } + + if (node.right != null) { + dfs(node.right, level + 1); + } + } +} +``` +### 收获 +在做这题的时候,真的觉得轻松了很多,思路一下子就有了,刻意练习很有效果。 +## LeetCode_547 +### 题目 +班上有 N 名学生。其中有些人是朋友,有些则不是。他们的友谊具有是传递性。如果已知 A 是 B 的朋友,B 是 C 的朋友,那么我们可以认为 A 也是 C 的朋友。所谓的朋友圈,是指所有朋友的集合。 + +给定一个 N * N 的矩阵 M,表示班级中学生之间的朋友关系。如果M[i][j] = 1,表示已知第 i 个和 j 个学生互为朋友关系,否则为不知道。你必须输出所有学生中的已知的朋友圈总数。 + +示例 1: +``` +输入: +[[1,1,0], + [1,1,0], + [0,0,1]] +输出: 2 +说明:已知学生0和学生1互为朋友,他们在一个朋友圈。 +第2个学生自己在一个朋友圈。所以返回2。 +``` +示例 2: +``` +输入: +[[1,1,0], + [1,1,1], + [0,1,1]] +输出: 1 +说明:已知学生0和学生1互为朋友,学生1和学生2互为朋友,所以学生0和学生2也是朋友,所以他们三个在一个朋友圈,返回1。 +``` +注意: +``` +N 在[1,200]的范围内。 +对于所有学生,有M[i][i] = 1。 +如果有M[i][j] = 1,则有M[j][i] = 1。 +``` +### 解法一 +#### 思路 +通过寻找共同的根节点来确定圈子,可以使用并查集的思路,在国内站找到了UnionFind解法 +1. 有一个数组保存当前元素的所属根元素的坐标**int[] parent** +2. 因为只需要知道最终共同认识的那个人,所以储存的是根节点,也因此需要进行**路径压缩**。 +```java +class Solution { + public void pathCompression(int[] parent, int p) { + while (p != parent[p]) { + //将压缩路径 + parent[p] = parent[parent[p]]; + //为了while条件时进行比较 + p = parent[p]; + } + } +} +``` +3. 还有一个数组用来保存每一个以它为根节点的这个朋友圈的等级,谁合并别人的次数多,谁更牛b,以后就继续合并别人(**int[] rank**),当出现有人需要联合的时候,通过比较rank等级来决定谁做圈子的根节点。 +4. 另有一个就是变量count,count用来记录朋友圈的个数,初始为总人数,也就是默认每个人是单独的一个圈子。当两个人中的一个准备进另一个圈子(**union**)的时候,count就需要-1 +5. 然后就是遍历整个二维数组,对互为朋友(=1)的两个元素进行是否需要联合的判断: + - 根节点不同就进行联合 + - 圈子数-1 +6. 循环结束,返回count +#### 代码 +```java +class Solution { + public int findCircleNum(int[][] M) { + UnionFind uf = new UnionFind(M.length); + for (int i = 0; i < M.length; i++) { + for (int j = 0; j < M.length; j++) { + if (M[i][j] == 1) { + uf.union(i, j); + } + } + } + return uf.count; + } + + private class UnionFind { + private int count; + private int[] parent; + private int[] rank; + + UnionFind(int n) { + this.count = n; + this.parent = new int[n]; + this.rank = new int[n]; + for (int i = 0; i < n; i++) { + parent[i] = i; + rank[i] = 1; + } + } + + int find(int n) { + while (n != this.parent[n]) { + this.parent[n] = this.parent[this.parent[n]]; + n = this.parent[n]; + } + return n; + } + + void union(int a, int b) { + int rootA = find(a); + int rootB = find(b); + if (rootA == rootB) { + return; + } + + if (rank[rootA] < rank[rootB]) { + parent[rootA] = rootB; + } else if (rank[rootA] > rank[rootB]) { + parent[rootB] = rootA; + } else { + parent[rootB] = rootA; + rank[rootA]++; + } + + count--; + } + } +} +``` +### 收获 +熟悉和练习了并查集的解法,同时了解了如何进行路径压缩。 +## LeetCode_310 +### 题目 +对于一个具有树特征的无向图,我们可选择任何一个节点作为根。图因此可以成为树,在所有可能的树中,具有最小高度的树被称为最小高度树。给出这样的一个图,写出一个函数找到所有的最小高度树并返回他们的根节点。 + +格式 + +该图包含 n 个节点,标记为 0 到 n - 1。给定数字 n 和一个无向边 edges 列表(每一个边都是一对标签)。 + +你可以假设没有重复的边会出现在 edges 中。由于所有的边都是无向边, [0, 1]和 [1, 0] 是相同的,因此不会同时出现在 edges 里。 + +示例 1: +``` +输入: n = 4, edges = [[1, 0], [1, 2], [1, 3]] + + 0 + | + 1 + / \ + 2 3 + +输出: [1] +``` +示例 2: +``` +输入: n = 6, edges = [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]] + + 0 1 2 + \ | / + 3 + | + 4 + | + 5 + +输出: [3, 4] +``` +说明: +``` + 根据树的定义,树是一个无向图,其中任何两个顶点只通过一条路径连接。 换句话说,一个任何没有简单环路的连通图都是一棵树。 +树的高度是指根节点和叶子节点之间最长向下路径上边的数量。 +``` +### 解法一 +#### 思路 +参考了国际站的解法,使用bfs拓扑排序,也就是每一次将叶子节点找到并从这个无向图中去掉,循环往复,一层层的摘掉这些叶子,直到找到最后1个或2个节点。 +1. 用一个**List> list**维护edges中每个节点与其他与之直接关联的节点们的关系(从我这个节点出发,走一步就到的节点) +2. 用一个**List leaves**来保存当前要摘的这层叶子节点们 +3. 如果当前节点只有一个与之直接关联的节点,说明它就是要摘的叶子,把他放到leaves里(bfs起始的一层) +4. 然后开始bfs,条件是while(n > 2),只要摘到小于等于2的时候,就说明摘完了 +5. 通过遍历leaves,在循环体里: + 1. 摘叶子 + 2. 放下一层要摘的叶子 +6. 留到最后的叶子节点就是结果 +#### 代码 +```java +class Solution { + public List findMinHeightTrees(int n, int[][] edges) { + if (n == 1) { + return Collections.singletonList(0); + } + + List> list = new ArrayList<>(n); + for (int i = 0; i < n; i++) { + list.add(new HashSet<>()); + } + for (int[] edge: edges) { + list.get(edge[0]).add(edge[1]); + list.get(edge[1]).add(edge[0]); + } + + List leaves = new ArrayList<>(); + for (int i = 0; i < n; i++) { + if (list.get(i).size() == 1) { + leaves.add(i); + } + } + + while (n > 2) { + n -= leaves.size(); + + List newLeaves = new ArrayList<>(); + for (int leave: leaves) { + int node = list.get(leave).iterator().next(); + list.get(node).remove(leave); + if (list.get(node).size() == 1) { + newLeaves.add(node); + } + } + leaves = newLeaves; + } + + return leaves; + } +} +``` +### 收获 +了解和练习了bfs拓扑排序 \ No newline at end of file diff --git a/Week_03/id_2/LeetCode_103_2.java b/Week_03/id_2/LeetCode_103_2.java new file mode 100644 index 00000000..2f29cc3f --- /dev/null +++ b/Week_03/id_2/LeetCode_103_2.java @@ -0,0 +1,73 @@ +//Given a binary tree, return the zigzag level order traversal of its nodes' values. +// (ie, from left to right, then right to left for the next level and alternate between). +// +// +//For example: +//Given binary tree [3,9,20,null,null,15,7], +// +// 3 +// / \ +// 9 20 +// / \ +// 15 7 +// +// +// +//return its zigzag level order traversal as: +// +//[ +// [3], +// [20,9], +// [15,7] +//] +// +// + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ + +package com.llz.algorithm.algorithm2019.thirdweek; + +import com.llz.algorithm.algorithm2019.firstweek.TreeNode; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; + +public class LeetCode_103_2 { + public List> zigzagLevelOrder(TreeNode root) { + List> list = new ArrayList<>(); + if (root == null) return list; + Queue queue = new ArrayDeque<>(); + queue.add(root); + boolean isLeftToRight = true; + int size = 0; + while (!queue.isEmpty()) { + size = queue.size(); + List innerList = new ArrayList<>(); + for (int i = 0; i < innerList.size(); i++) { + TreeNode cur = queue.remove(); + if (isLeftToRight) { + innerList.add(cur.val); + } else { + innerList.add(0, cur.val); + } + if (cur.left != null) + queue.add(cur.left); + if (cur.right != null) + queue.add(cur.right); + } + list.add(innerList); + isLeftToRight = !isLeftToRight; + } + return list; + } +} diff --git a/Week_03/id_2/LeetCode_111_2.java b/Week_03/id_2/LeetCode_111_2.java new file mode 100644 index 00000000..3508e103 --- /dev/null +++ b/Week_03/id_2/LeetCode_111_2.java @@ -0,0 +1,90 @@ +//Given a binary tree, find its minimum depth. +// +// The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node. +// +// Note: A leaf is a node with no children. +// +// Example: +// +// Given binary tree [3,9,20,null,null,15,7], +// +// +// 3 +// / \ +// 9 20 +// / \ +// 15 7 +// +// return its minimum depth = 2. +// + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ + +package com.llz.algorithm.algorithm2019.thirdweek; + +import apple.laf.JRSUIUtils; +import com.llz.algorithm.algorithm2019.firstweek.TreeNode; + +import java.util.ArrayDeque; +import java.util.Queue; + +public class LeetCode_111_2 { + + /** + * Time complexity O(n), space complexity O(n) (worst case) + * If the given tree is balanced, the time complexity of both time and space is O(logn). + * + * @param root + * @return + */ + public int minDepth(TreeNode root) { + if (root == null) return 0; + int left = minDepth(root.left); + int right = minDepth(root.right); + if (root.left == null) + return right + 1; + if (root.right == null) + return left + 1; + return Math.min(left, right) + 1; + } + + + /** + * Time complexity O(n), space complexity O(n) (worst case) + * If the given tree is balanced, the time complexity of both time and space is O(logn). + * + * @param root + * @return + */ + + public int minDepthByIteration(TreeNode root) { + if (root == null) return 0; + Queue queue = new ArrayDeque<>(); + queue.add(root); + int depth = 0; + while (!queue.isEmpty()) { + int size = queue.size(); + for (int i = 0; i < size; i++) { + TreeNode cur = queue.remove(); + if (cur.left == null && cur.right == null) { + depth++; + return depth; + } + if (cur.left != null) + queue.add(cur.left); + if (cur.right != null) + queue.add(cur.right); + } + depth++; + } + return depth; + } +} diff --git a/Week_03/id_2/LeetCode_200_2.java b/Week_03/id_2/LeetCode_200_2.java new file mode 100644 index 00000000..fb8a25e2 --- /dev/null +++ b/Week_03/id_2/LeetCode_200_2.java @@ -0,0 +1,64 @@ +//Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water. +// +// Example 1: +// +// +//Input: +//11110 +//11010 +//11000 +//00000 +// +//Output: 1 +// +// +// Example 2: +// +// +//Input: +//11000 +//11000 +//00100 +//00011 +// +//Output: 3 +// + +package com.llz.algorithm.algorithm2019.thirdweek; + +public class LeetCode_200_2 { + public int numIslands(char[][] grid) { + if (grid.length == 0) return 0; + int count = 0; + boolean[][] visited = new boolean[grid.length][grid[0].length]; + for (int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid[i].length; j++) { + if (visited[i][j] == false && grid[i][j] == '1') { + dfs(grid, visited, i, j); + count++; + } + } + } + return count; + } + + public void dfs(char[][] grid, boolean[][] visited, int i, int j) { + if (i < 0 || j < 0) return; + if (i == grid.length) return; + if (j == grid[i].length)return; + if (visited[i][j] == true || grid[i][j] == '0') + return; + visited[i][j] = true; + dfs(grid, visited, i - 1, j); + dfs(grid, visited, i, j - 1); + dfs(grid, visited, i + 1, j); + dfs(grid, visited, i, j + 1); + } + + public static void main(String[] args) { + // char[][] grid = {{'1', '1', '0', '0', '0'}, {'1', '1', '0', '0', '0'}, {'0', '0', '1', '0', '0'}, {'0', '0', '0', '1', '1'}}; + char[][] grid = {{'1', '1', '1'}, {'0', '1', '0'}, {'1', '1', '1'}}; + LeetCode_200_2 l = new LeetCode_200_2(); + System.out.println(l.numIslands(grid)); + } +} diff --git a/Week_03/id_2/LeetCode_310_2.java b/Week_03/id_2/LeetCode_310_2.java new file mode 100644 index 00000000..ee9ad017 --- /dev/null +++ b/Week_03/id_2/LeetCode_310_2.java @@ -0,0 +1,88 @@ +//For an undirected graph with tree characteristics, we can choose any node as the root. The result graph is then a rooted tree. Among all possible rooted trees, those with minimum height are called minimum height trees (MHTs). Given such a graph, write a function to find all the MHTs and return a list of their root labels. +// +// Format +//The graph contains n nodes which are labeled from 0 to n - 1. You will be given the number n and a list of undirected edges (each edge is a pair of labels). +// +// You can assume that no duplicate edges will appear in edges. Since all edges are undirected, [0, 1] is the same as [1, 0] and thus will not appear together in edges. +// +// Example 1 : +// +// +//Input: n = 4, edges = [[1, 0], [1, 2], [1, 3]] +// +// 0 +// | +// 1 +// / \ +// 2 3 +// +//Output: [1] +// +// +// Example 2 : +// +// +//Input: n = 6, edges = [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]] +// +// 0 1 2 +// \ | / +// 3 +// | +// 4 +// | +// 5 +// +//Output: [3, 4] +// +// Note: +// +// +// According to the definition of tree on Wikipedia: “a tree is an undirected graph in which any two vertices are connected by exactly one path. In other words, any connected graph without simple cycles is a tree.” +// The height of a rooted tree is the number of edges on the longest downward path between the root and a leaf. +// +// + +package com.llz.algorithm.algorithm2019.thirdweek; + +import java.util.*; + +public class LeetCode_310_2 { + /** + * Referenced from discussion by using topological sort. + * + * @param n + * @param edges + * @return + */ + public List findMinHeightTrees(int n, int[][] edges) { + List ans = new ArrayList<>(); + if (n == 0) return ans; + if (n == 1) { + ans.add(0); + return ans; + } + List> adj = new ArrayList<>(); + for (int i = 0; i < n; i++) { + adj.add(new HashSet<>()); + } + for (int i = 0; i < edges.length; i++) { + adj.get(edges[i][0]).add(edges[i][1]); + adj.get(edges[i][1]).add(edges[i][0]); + } + for (int i = 0; i < n; i++) { + if (adj.get(i).size() == 1) + ans.add(i); + } + while (n > 2) { + n -= ans.size(); + List newAns = new ArrayList<>(); + for (int i : ans) { + int j = adj.get(i).iterator().next(); + adj.get(j).remove(i); + if (adj.get(j).size() == 1) newAns.add(j); + } + ans = newAns; + } + return ans; + } +} \ No newline at end of file diff --git a/Week_03/id_2/LeetCode_429_2.java b/Week_03/id_2/LeetCode_429_2.java new file mode 100644 index 00000000..23dd3c2b --- /dev/null +++ b/Week_03/id_2/LeetCode_429_2.java @@ -0,0 +1,123 @@ +//Given an n-ary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level). +// +// For example, given a 3-ary tree: +// +// +// +// +// +// +// +// We should return its level order traversal: +// +// +//[ +// [1], +// [3,2,4], +// [5,6] +//] +// +// +// +// +// Note: +// +// +// The depth of the tree is at most 1000. +// The total number of nodes is at most 5000. +// +// + +/* +// Definition for a Node. +class Node { + public int val; + public List children; + + public Node() {} + + public Node(int _val,List _children) { + val = _val; + children = _children; + } +}; +*/ + +package com.llz.algorithm.algorithm2019.thirdweek; + +import java.util.*; + + +class Node { + public int val; + public List children; + + public Node() { + } + + public Node(int _val, List _children) { + val = _val; + children = _children; + } +} + +public class LeetCode_429_2 { + + /** + * Time Complexity is O(n) and space complexity isO(n).(worst case) + * if the tree is balanced, time and space complexity are both O(log3n). + * + * @param root + * @return + */ + public List> levelOrderByBFS(Node root) { + List> outterList = new ArrayList<>(); + if (root == null) return outterList; + Queue queue = new ArrayDeque<>(); + queue.add(root); + int size = 0; + while (!queue.isEmpty()) { + size = queue.size(); + List innerList = new ArrayList(); + for (int i = 0; i < size; i++) { + Node cur = queue.remove(); + innerList.add(cur.val); + List children = cur.children; + for (int j = 0; j < children.size(); j++) { + queue.add(children.get(j)); + } + } + outterList.add(innerList); + } + return outterList; + } + + public List> levelOrderByDFS(Node root) { + List> list = new ArrayList<>(); + dfs(root, list, 0); + return list; + } + + public void dfs(Node cur, List> list, int level) { + if (cur == null) return; + List innerList = new ArrayList<>(); + if (list.size() > level) + innerList = list.get(level); + innerList.add(cur.val); + if (list.size() <= level) + list.add(innerList); + for (Node node : cur.children) { + dfs(node, list, level + 1); + } + } + + public static void main(String[] args) { + List children1 = new ArrayList(Arrays.asList(new Node(5, new ArrayList<>()), new Node(6, new ArrayList<>()))); + Node c1 = new Node(2, children1); + List children0 = new ArrayList(Arrays.asList(c1, new Node(3, new ArrayList<>()), new Node(4, new ArrayList<>()))); + Node root = new Node(1, children0); + LeetCode_429_2 l = new LeetCode_429_2(); + List> list=l.levelOrderByDFS(root); + System.out.println(list); + } +} diff --git a/Week_03/id_2/LeetCode_547_2.java b/Week_03/id_2/LeetCode_547_2.java new file mode 100644 index 00000000..ff150a56 --- /dev/null +++ b/Week_03/id_2/LeetCode_547_2.java @@ -0,0 +1,78 @@ +// +//There are N students in a class. Some of them are friends, while some are not. Their friendship is transitive in nature. For example, if A is a direct friend of B, and B is a direct friend of C, then A is an indirect friend of C. And we defined a friend circle is a group of students who are direct or indirect friends. +// +// +// +//Given a N*N matrix M representing the friend relationship between students in the class. If M[i][j] = 1, then the ith and jth students are direct friends with each other, otherwise not. And you have to output the total number of friend circles among all the students. +// +// +// Example 1: +// +//Input: +//[[1,1,0], +// [1,1,0], +// [0,0,1]] +//Output: 2 +//Explanation:The 0th and 1st students are direct friends, so they are in a friend circle. The 2nd student himself is in a friend circle. So return 2. +// +// +// +// Example 2: +// +//Input: +//[[1,1,0], +// [1,1,1], +// [0,1,1]] +//Output: 1 +//Explanation:The 0th and 1st students are direct friends, the 1st and 2nd students are direct friends, so the 0th and 2nd students are indirect friends. All of them are in the same friend circle, so return 1. +// +// +// +// +// Note: +// +// N is in range [1,200]. +// M[i][i] = 1 for all students. +// If M[i][j] = 1, then M[j][i] = 1. +// +// + +package com.llz.algorithm.algorithm2019.thirdweek; + + +public class LeetCode_547_2 { + + /** + * Time complexity is O(n^2), space complexity is O(n^2). + * + * @param M + * @return + */ + public int findCircleNum(int[][] M) { + int count = 0; + boolean[] visited = new boolean[M.length]; + for (int i = 0; i < M.length; i++) { + if (visited[i] == false) { + dfs(M, i, visited); + count++; + } + } + return count; + } + + public void dfs(int[][] M, int i, boolean[] visited) { + for (int j = 0; j < M.length; j++) { + if (visited[j] == false && M[i][j] == 1) { + visited[j] = true; + dfs(M, j, visited); + } + } + } + + + public static void main(String[] args) { + LeetCode_547_2 l = new LeetCode_547_2(); + int[][] M = {{1, 1, 0}, {1, 1, 0}, {0, 0, 1}}; + System.out.println(l.findCircleNum(M)); + } +} diff --git a/Week_03/id_2/LeetCode_703_2.java b/Week_03/id_2/LeetCode_703_2.java new file mode 100644 index 00000000..76578bed --- /dev/null +++ b/Week_03/id_2/LeetCode_703_2.java @@ -0,0 +1,50 @@ +package com.llz.algorithm.algorithm2019.thirdweek; + +import java.util.PriorityQueue; + +public class LeetCode_703_2 { + + /** + * Time complexity is O(nlogn) for building a min heap. + * Space complexity is O(n). + */ + class KthLargest { + + private int k; + private int[] nums; + private PriorityQueue pq; + + public KthLargest(int k, int[] nums) { + this.k = k; + this.nums = nums; + pq = new PriorityQueue(k); + for (int i = 0; i < nums.length; i++) { + add(nums[i]); + } + } + + public int add(int val) { + if (pq.size() < k) + pq.add(val); + else { + if (val > pq.peek()) { + pq.poll(); + pq.add(val); + } + } + return pq.peek(); + } + } + + public static void main(String[] args) { + int[] nums = {4,5,8,2}; + //[[1,[]],[-3],[-2],[-4],[0],[4]] + //[[3,[4,5,8,2]],[3],[5],[10],[9],[4]] + LeetCode_703_2.KthLargest k = new LeetCode_703_2().new KthLargest(3, nums); + System.out.println(k.add(3)); + System.out.println(k.add(5)); + System.out.println(k.add(10)); + System.out.println(k.add(9)); + System.out.println(k.add(4)); + } +} \ No newline at end of file diff --git a/Week_03/id_2/LeetCode_802_2.java b/Week_03/id_2/LeetCode_802_2.java new file mode 100644 index 00000000..3b6a636d --- /dev/null +++ b/Week_03/id_2/LeetCode_802_2.java @@ -0,0 +1,125 @@ +//In a directed graph, we start at some node and every turn, walk along a directed edge of the graph. If we reach a node that is terminal (that is, it has no outgoing directed edges), we stop. +// +// Now, say our starting node is eventually safe if and only if we must eventually walk to a terminal node. More specifically, there exists a natural number K so that for any choice of where to walk, we must have stopped at a terminal node in less than K steps. +// +// Which nodes are eventually safe? Return them as an array in sorted order. +// +// The directed graph has N nodes with labels 0, 1, ..., N-1, where N is the length of graph. The graph is given in the following form: graph[i] is a list of labels j such that (i, j) is a directed edge of the graph. +// +// +//Example: +//Input: graph = [[1,2],[2,3],[5],[0],[5],[],[]] +//Output: [2,4,5,6] +//Here is a diagram of the above graph. +// +// +// +// +// +// Note: +// +// +// graph will have length at most 10000. +// The number of edges in the graph will not exceed 32000. +// Each graph[i] will be a sorted list of different integers, chosen within the range [0, graph.length - 1]. +// +// + +package com.llz.algorithm.algorithm2019.thirdweek; + +import java.util.*; + +public class LeetCode_802_2 { + + private List[] linkList; + + /** + * My original version by using topological sort. + *

+ * Time complexity is O(N+E) and space complexity is O(N+E) either. + * + * @param graph + * @return + */ + public List eventualSafeNodesByKahn(int[][] graph) { + int[] degrees = new int[graph.length]; //out-degree + linkList = new LinkedList[graph.length]; + for (int i = 0; i < graph.length; i++) { + linkList[i] = new LinkedList<>(); + } + Queue queue = new ArrayDeque<>(); + List list = new ArrayList<>(); + for (int i = 0; i < graph.length; i++) { + degrees[i] = graph[i].length; + if (graph[i].length == 0) { + queue.add(i); + } else { + for (int j = 0; j < graph[i].length; j++) { + linkList[graph[i][j]].add(i); + } + } + } + while (!queue.isEmpty()) { + int node = queue.remove(); + list.add(node); + for (int i = 0; i < linkList[node].size(); i++) { + int lastNode = linkList[node].get(i); + if (--degrees[lastNode] == 0) + queue.add(lastNode); + } + } + list.sort(new Comparator() { + public int compare(Integer o1, Integer o2) { + return o1.compareTo(o2); + } + }); + return list; + } + + /** + * Referenced from discussion by using white-grey-black dfs method. + * @param graph + * @return + */ + public List eventualSafeNodesByDFS(int[][] graph) { + int N = graph.length; + int[] color = new int[N]; + List ans = new ArrayList(); + + for (int i = 0; i < N; ++i) + if (dfs(i, color, graph)) + ans.add(i); + return ans; + } + + // colors: WHITE 0, GRAY 1, BLACK 2; + public boolean dfs(int node, int[] color, int[][] graph) { + if (color[node] > 0) + return color[node] == 2; + + color[node] = 1; + for (int nei : graph[node]) { + if (color[node] == 2) + continue; + if (color[nei] == 1 || !dfs(nei, color, graph)) + return false; + } + + color[node] = 2; + return true; + } + + public static void main(String[] args) { + // Input: graph = [[1,2],[2,3],[5],[0],[5],[],[]] + int[] g0 = {1, 2}; + int[] g1 = {2, 3}; + int[] g2 = {5}; + int[] g3 = {0}; + int[] g4 = {5}; + int[] g5 = {}; + int[] g6 = {}; + int[][] graph = {g0, g1, g2, g3, g4, g5, g6}; + LeetCode_802_2 l = new LeetCode_802_2(); + System.out.println(l.eventualSafeNodesByDFS(graph)); + } +} diff --git a/Week_03/id_2/Summary.md b/Week_03/id_2/Summary.md new file mode 100644 index 00000000..ba443414 --- /dev/null +++ b/Week_03/id_2/Summary.md @@ -0,0 +1,13 @@ + +第三周总结 +这周有比较多的图的题目,之前听说图的题目在面试里面出题的概率比较小,所以基本是忽略图的学习了。 +但是其实tree也是一种连通无环图,所以类似图的解题技巧也会在树里面考察。那么进一步要求我也要好好学习下图的概念和相关题型。 +包括topological sort,union find,bfs,dfs等。 +703:使用BST获得第k大的数的解法没有明白。 +802:如果不是看题解white-gray-black的dfs方法解题,我是不会想到这个dfs的方法的。浪费了很多时间在这道题如何用dfs解。 +310:开始我返回的list用的是linkedList实现,结果立马超时了,换成了arrayList通过。这个结果告诉我,尽量要选最优的数据结构解题。这个解法不是最优的解法。我还要继续reference下,看看如何优化。 +103:上周做过,这周很快做出来。 +111:上周做过,这周很快使用递归和迭代两种方法做出来。 +200:自己做的,虽然是beat 100%,但是答案这种泛洪的方式比我要在空间上少用一个记录访问节点的数组,更加优化。 +429:迭代的方式很快做出来,dfs的方式还是参考了答案。这个dfs我觉得是个套路,虽然一般层序遍历都会考虑用bfs求解,但是dfs求解效率更快,而且代码更简洁。值得学习。 +547:参考了答案,自己解题陷入了死胡同,我先做的547我觉得547和岛屿数量这道题解题思路很相似。 diff --git a/Week_03/id_23/LeetCode_104.1_23 b/Week_03/id_23/LeetCode_104.1_23 new file mode 100644 index 00000000..7b1e1c94 --- /dev/null +++ b/Week_03/id_23/LeetCode_104.1_23 @@ -0,0 +1,38 @@ +//给定一个二叉树,找出其最大深度。 +// +// 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。 +// +// 说明: 叶子节点是指没有子节点的节点。 +// +// 示例: +//给定二叉树 [3,9,20,null,null,15,7], +// +// 3 +// / \ +// 9 20 +// / \ +// 15 7 +// +// 返回它的最大深度 3 。 +// + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +class Solution { + public int maxDepth(TreeNode root) { + if (root == null) { + return 0; + } else { + int left_height = maxDepth(root.left); + int right_height = maxDepth(root.right); + return java.lang.Math.max(left_height, right_height) + 1; + } + } +} \ No newline at end of file diff --git a/Week_03/id_23/LeetCode_104.2_23 b/Week_03/id_23/LeetCode_104.2_23 new file mode 100644 index 00000000..e244f219 --- /dev/null +++ b/Week_03/id_23/LeetCode_104.2_23 @@ -0,0 +1,14 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +class Solution { + public int maxDepth(TreeNode root) { + return root == null ? 0 : Math.max(maxDepth(root.left), maxDepth(root.right)) + 1; + } +} diff --git a/Week_03/id_23/NOTE.md b/Week_03/id_23/NOTE.md index 107ea7d6..eb800f80 100644 --- a/Week_03/id_23/NOTE.md +++ b/Week_03/id_23/NOTE.md @@ -1 +1,13 @@ -# 学习笔记 +# 学习笔记 +###本周总结 +#### 关于图的定义 +图的表示: 邻接表 和 邻接矩阵 +图可以分为 有向图 和无向图 +无向图是一种特殊的有向图 +有权图 和 无权图 + +#### 关于图相关的算法与问题 +图的遍历: DFS BFS 常见可以解决的问题有: 联通分量 Flood Fill 寻路 走迷宫 迷宫生成 无权图的最短路径 环的判断 +最小生成树问题(Minimum Spanning Tree) Prim Kruskal +最短路径问题(Shortest Path) Dijkstra Bellman-Ford +拓扑排序(Topological sorting) diff --git a/Week_03/id_24/LeetCode_104_024.py b/Week_03/id_24/LeetCode_104_024.py new file mode 100644 index 00000000..87482d01 --- /dev/null +++ b/Week_03/id_24/LeetCode_104_024.py @@ -0,0 +1,12 @@ +# Definition for a binary tree node. +class TreeNode: + def __init__(self, x): + self.val = x + self.left = None + self.right = None + +class Solution: + def maxDepth(self, root: TreeNode) -> int: + if not root: + return 0 + return 1 + max(self.maxDepth(root.left), self.maxDepth(root.right)) \ No newline at end of file diff --git a/Week_03/id_24/LeetCode_111_024.py b/Week_03/id_24/LeetCode_111_024.py new file mode 100644 index 00000000..020e79ce --- /dev/null +++ b/Week_03/id_24/LeetCode_111_024.py @@ -0,0 +1,23 @@ +# Definition for a binary tree node. +class TreeNode(object): + def __init__(self, x): + self.val = x + self.left = None + self.right = None + +class Solution(object): + def minDepth(self, root): + """ + :type root: TreeNode + :rtype: int + """ + if not root: + return 0 + if not root.left and not root.right: + return 1 + elif not root.left: + return 1 + self.minDepth(root.right) + elif not root.right: + return 1 + self.minDepth(root.left) + return 1 + min(self.minDepth(root.left), self.minDepth(root.right)) + \ No newline at end of file diff --git a/Week_03/id_24/LeetCode_200_024.py b/Week_03/id_24/LeetCode_200_024.py new file mode 100644 index 00000000..7e69c838 --- /dev/null +++ b/Week_03/id_24/LeetCode_200_024.py @@ -0,0 +1,39 @@ +class Solution(object): + def numIslands(self, grid): + if not grid or not grid[0]: + return 0 + self.grid = grid + self.max_x = len(grid) + self.max_y = len(grid[0]) + self.visited = set() + result = [self._dfs(i, j) for i in range(self.max_x) for j in range(self.max_y)] + # print(result) + return sum(result) + + def _dfs(self, x, y): + if not self._check_valid(x, y): + return 0 + # print("self.grid[x][y]: ", self.grid[x][y]) + self.visited.add((x, y)) + self._dfs(x-1, y) + self._dfs(x+1, y) + self._dfs(x, y-1) + self._dfs(x, y+1) + return 1 + + def _check_valid(self, x, y): + # print((x, y)) + if x < 0 or y < 0 or x >= self.max_x or y >= self.max_y: + return False + elif self.grid[x][y] == '0' or (x, y) in self.visited: + return False + else: + return True + + +grid = [["1","1","1","1","0"],["1","1","0","1","0"],["1","1","0","0","0"],["0","0","0","0","0"]] + +sol = Solution() +print(sol.numIslands(grid)) + + \ No newline at end of file diff --git a/Week_03/id_24/LeetCode_703_024.py b/Week_03/id_24/LeetCode_703_024.py new file mode 100644 index 00000000..28c059a3 --- /dev/null +++ b/Week_03/id_24/LeetCode_703_024.py @@ -0,0 +1,33 @@ +class KthLargest(object): + + def __init__(self, k, nums): + """ + :type k: int + :type nums: List[int] + """ + self.k = k + self.nums = nums + self.nums.sort() + self.nums_len = len(self.nums) + self.kNums = self.nums[:] if self.nums_len < self.k else self.nums[self.nums_len - self.k : self.nums_len : 1] + + + def add(self, val): + """ + :type val: int + :rtype: int + """ + self.kNums.append(val) + self.kNums.sort() + if len(self.kNums) > self.k: + self.kNums.pop(0) + return self.kNums[0] + + + +# Your KthLargest object will be instantiated and called as such: +k = 3 +nums = [5,-1] +val = 2 + +print(KthLargest(k, nums).add(val)) \ No newline at end of file diff --git a/Week_03/id_24/LeetCode_703_024_v2.py b/Week_03/id_24/LeetCode_703_024_v2.py new file mode 100644 index 00000000..3be809ca --- /dev/null +++ b/Week_03/id_24/LeetCode_703_024_v2.py @@ -0,0 +1,36 @@ +import heapq + +class KthLargest(object): + + def __init__(self, k, nums): + """ + :type k: int + :type nums: List[int] + """ + self.k = k + self.heap = [] + for i in range(len(nums)): + if i <= k - 1: + heapq.heappush(self.heap, nums[i]) + else: + heapq.heappushpop(self.heap, nums[i]) + + def add(self, val): + """ + :type val: int + :rtype: int + """ + if len(self.heap) < self.k: + heapq.heappush(self.heap, val) + else: + heapq.heappushpop(self.heap, val) + return self.heap[0] + + + +# Your KthLargest object will be instantiated and called as such: +k = 3 +nums = [5,-1] +val = 2 + +print(KthLargest(k, nums).add(val)) \ No newline at end of file diff --git a/Week_03/id_25/LeetCode_200_025.java b/Week_03/id_25/LeetCode_200_025.java new file mode 100644 index 00000000..fc4018aa --- /dev/null +++ b/Week_03/id_25/LeetCode_200_025.java @@ -0,0 +1,122 @@ +package com.mootal.algo.day15_37; + +import java.util.LinkedList; + +/** + * Medium + * (注解文档查看快捷键 选中类名或方法名 按ctrl + Q) + *

+ * 思维全过程记录方案:

+ * 1 背基础结构和算法 | 记录在课程笔记

+ * 2 看题 -> 悟题 思考过程 | 记录在wiki

+ * 3 悟题 -> 写题 实现难点 | 记录在代码注解

+ * 4 写题 -> 优化 多种解法 | 记录在leetcode提交 + *

+ * 问题: + * Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. + * An island is surrounded by water and is formed by connecting adjacent lands horizontally + * or vertically. You may assume all four edges of the grid are all surrounded by water. + *

+ * 题解方案topics: + * DFS、BFS、Union Find + *

+ * https://www.cnblogs.com/grandyang/p/4402656.html + * https://github.com/awangdev/LintCode/blob/master/Java/Number%20of%20Islands.java + * http://wykvictor.github.io/2016/06/01/BFS-1.html + * + * @author li tong + * @date 2019/6/17 18:28 + * @see Object + * @since 1.0 + */ +public class LeetCode_200_025 { + + public static void main(String[] args) { + char[][] grid = new char[5][5]; + for (int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid.length; j++) { + grid[i][j] = '0'; + } + } + init(grid); + for (int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid.length; j++) { + System.out.print(grid[i][j]); + } + System.out.println(); + } + System.out.println(numIslands(grid)); + } + + /** + * [ + * [1, 1, 0, 0, 0], + * [0, 1, 0, 0, 1], + * [0, 0, 0, 1, 1], + * [0, 0, 0, 0, 0], + * [0, 0, 0, 0, 1] + * ] + * return 3. + */ + public static int numIslands(char[][] grid) { + if (grid == null || grid.length == 0 || grid[0].length == 0) { + return 0; + } + int m = grid.length, n = grid[0].length, res = 0; + boolean[][] visited = new boolean[m][n]; + int[] dx = {1, -1, 0, 0}; + int[] dy = {0, 0, 1, -1}; + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + if (grid[i][j] == '0' || visited[i][j]) + continue; + ++res; + LinkedList q = new LinkedList<>(); + q.push(i * n + j); + bfs(q, grid, visited, m, n, dx, dy); + } + } + return res; + } + + private static void bfs(LinkedList q, char[][] grid, boolean[][] visited, int m, int n, int[] dx, int[] dy) { + while (!q.isEmpty()) { + int t = q.peekFirst(); + q.pop(); + for (int k = 0; k < 4; ++k) { + int x = t / n + dx[k], y = t % n + dy[k]; + if (x < 0 || x >= m || y < 0 || y >= n || grid[x][y] == '0' || visited[x][y]) continue; + visited[x][y] = true; + q.push(x * n + y); + } + } + } + + private static void dfs(char[][] grid, boolean[][] visited, int x, int y) { + if (x < 0 || y < 0 + || x >= grid.length || y >= grid[0].length + || grid[x][y] == '0' || visited[x][y]) { + return; + } + visited[x][y] = true; + // 上 + dfs(grid, visited, x - 1, y); + // 下 + dfs(grid, visited, x + 1, y); + // 左 + dfs(grid, visited, x, y - 1); + // 右 + dfs(grid, visited, x, y + 1); + } + + private static void init(char[][] board) { + board[0][0] = '1'; + board[0][1] = '1'; + board[1][1] = '1'; + board[1][4] = '1'; + board[2][3] = '1'; + board[2][4] = '1'; + board[4][4] = '1'; + } + +} diff --git a/Week_03/id_25/LeetCode_322_025.java b/Week_03/id_25/LeetCode_322_025.java new file mode 100644 index 00000000..bc430ef3 --- /dev/null +++ b/Week_03/id_25/LeetCode_322_025.java @@ -0,0 +1,125 @@ +package com.mootal.algo.day_16; + +/** + * Medium + *

+ * 属于背包问题 BackPack

+ * https://www.cnblogs.com/Christal-R/p/Dynamic_programming.html

+ * http://www.cs.ust.hk/mjg_lib/Classes/COMP3711H_Fall16/lectures/19_DPII.pdf

+ * https://www.jianshu.com/p/f38f4af13177

+ * https://www.cnblogs.com/xym4869/p/8513801.html

+ * https://www.cnblogs.com/fengziwei/p/7750849.html

+ * 一、问题描述:有n 个物品,它们有各自的重量和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和? + *

+ * 二、总体思路:根据动态规划解题步骤(问题抽象化、建立模型、寻找约束条件、判断是否满足最优性原理、 + * 找大问题与小问题的递推关系式、填表、寻找解组成)找出01背包问题的最优解以及解组成,然后编写代码实现; + *

+ * 三、动态规划的原理及过程: + *

+ *   eg:number=4,capacity=8 + * 1、原理 + *

+ *   动态规划与分治法类似,都是把大问题拆分成小问题,通过寻找大问题与小问题的递推关系, + * 解决一个个小问题,最终达到解决原问题的效果。但不同的是,分治法在子问题和子子问题等上被重复计算了很多次, + * 而动态规划则具有记忆性,通过填写表把所有已经解决的子问题答案纪录下来,在新问题里需要用到的子问题可以直接提取, + * 避免了重复计算,从而节约了时间,所以在问题满足最优性原理之后,用动态规划解决问题的核心就在于填表,表填写完毕,最优解也就找到。 + * 2、过程 + * 3、空间优化 + *

+ * 四、蛮力法检验: + *

+ *   1) 蛮力法是解决01背包问题最简单最容易的方法,但是效率很低 + *

+ *   2) (X1,X2,…,Xn)其中Xi=0或1表示第i件商品选或不选,共有n(n-1)/2种可能; + *

+ *   3) 最简单的方式就是把所有拿商品的方式都列出来,最后再做判断此方法是否满足装包条件, + * 并且通过比较和记录找出最优解和解组成(如果满足则记录此时的价值和装的方式,当下一次的装法优于这次, + * 则更新记录,如此下去到最后便会找到最优解,同时解组成也找到); + *

+ *   4) n件商品,共有n(n-1)/2种可能,故蛮力法的效率是指数级别的,可见效率很低; + *

+ *   5) 蛮力法效率低不建议采取,但可以用于检验小规模的动态规划解背包问题的正确性和可行性, + *

+ * 五、总结: + *

+ *   对于01背包问题,用蛮力法与用动态规划解决得到的最优解和解组成是一致的,所以动态规划解决此类问题是可行的。 + * 动态规划效率为线性,蛮力法效率为指数型,结合以上内容和理论知识可以得出,解决此问题用动态规划比用蛮力法适合得多。 + * 对于动态规划不足的是空间开销大,数据的存储得用到二维数组;好的是,当前问题的解只与上一层的子问题的解相关, + * 所以,可以把动态规划的空间进行优化,使得空间效率从O(n*c)转化为O(c), + * 遗憾的是,虽然优化了空间,但优化后只能求出最优解,解组成的探索方式在该方法运行的时候已经被破坏掉; + * 总之动态规划和优化后的动态规划各有优缺点,可以根据实际问题的需求选择不同的方式。 + *

+ * 六、引申: + *

+ *   动态规划可以解决哪些类型的问题? + *

+ *   待解决的原问题较难,但此问题可以被不断拆分成一个个小问题,而小问题的解是非常容易获得的; + * 如果单单只是利用递归的方法来解决原问题,那么采用的是分治法的思想, + * 动态规划具有记忆性,将子问题的解都记录下来,以免在递归的过程中重复计算,从而减少了计算量。 + *

+ * (注解文档查看快捷键 选中类名或方法名 按ctrl + Q) + *

+ * 思维全过程记录方案:

+ * 1 背基础结构和算法 | 记录在课程笔记

+ * 2 看题 -> 悟题 思考过程 | 记录在wiki

+ * 3 悟题 -> 写题 实现难点 | 记录在代码注解

+ * 4 写题 -> 优化 多种解法 | 记录在leetcode提交 + *

+ * 问题: + * You are given coins of different denominations and a total amount of money amount. + * Write a function to compute the fewest number of coins that you need to make up that amount. + * If that amount of money cannot be made up by any combination of the coins, return -1. + *

+ * 题解方案topics: + * dp + * + * @author li tong + * @date 2019/6/17 18:19 + * @see Object + * @since 1.0 + */ +public class LeetCode_322_025 { + + public static void main(String[] args) { + int[] coins = new int[]{1, 2, 5}; + int amount = 11; + System.out.println(coinChange2(coins, amount)); + } + + public static int coinChange2(int[] coins, int amount) { + if (coins == null || coins.length == 0) { + return 0; + } + int[] dp = new int[amount + 1]; + dp[0] = 0; + for (int i = 1; i < dp.length; i++) { + dp[i] = amount + 1; + } + for (int coin : coins) { + for (int i = coin; i <= amount; i++) { + dp[i] = Math.min(dp[i], dp[i - coin] + 1); + } + } + return dp[amount] > amount ? -1 : dp[amount]; + } + + public static int coinChange1(int[] coins, int amount) { + if (coins == null || coins.length == 0) { + return 0; + } + int[] dp = new int[amount + 1]; + dp[0] = 0; + for (int i = 1; i < dp.length; i++) { + dp[i] = amount + 1; + } + for (int i = 1; i <= amount; i++) { + for (int j = 0; j < coins.length; j++) { + if (coins[j] <= i) { + dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1); + } + } + } + return dp[amount] > amount ? -1 : dp[amount]; + } + +} diff --git a/Week_03/id_26/LeetCode_102_26.py b/Week_03/id_26/LeetCode_102_26.py new file mode 100644 index 00000000..f665cc69 --- /dev/null +++ b/Week_03/id_26/LeetCode_102_26.py @@ -0,0 +1,64 @@ +# +# @lc app=leetcode.cn id=102 lang=python +# +# [102] 二叉树的层次遍历 +# +# https://leetcode-cn.com/problems/binary-tree-level-order-traversal/description/ +# +# algorithms +# Medium (56.47%) +# Likes: 213 +# Dislikes: 0 +# Total Accepted: 28.4K +# Total Submissions: 50.2K +# Testcase Example: '[3,9,20,null,null,15,7]' +# +# 给定一个二叉树,返回其按层次遍历的节点值。 (即逐层地,从左到右访问所有节点)。 +# +# 例如: +# 给定二叉树: [3,9,20,null,null,15,7], +# +# ⁠ 3 +# ⁠ / \ +# ⁠ 9 20 +# ⁠ / \ +# ⁠ 15 7 +# +# +# 返回其层次遍历结果: +# +# [ +# ⁠ [3], +# ⁠ [9,20], +# ⁠ [15,7] +# ] +# +# +# +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + + +class Solution(object): + def levelOrder(self, root): + """ + :type root: TreeNode + :rtype: List[List[int]] + """ + if not root: + return [] + layer, ans = [root], [] + while layer: + next_layer, vals = [], [] + for node in layer: + vals.append(node.val) + if node.left: + next_layer.append(node.left) + if node.right: + next_layer.append(node.right) + layer, ans = next_layer, ans + [vals] + return ans diff --git a/Week_03/id_26/LeetCode_104_26.py b/Week_03/id_26/LeetCode_104_26.py new file mode 100644 index 00000000..b7f88f05 --- /dev/null +++ b/Week_03/id_26/LeetCode_104_26.py @@ -0,0 +1,50 @@ +# +# @lc app=leetcode.cn id=104 lang=python +# +# [104] 二叉树的最大深度 +# +# https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/description/ +# +# algorithms +# Easy (69.23%) +# Likes: 297 +# Dislikes: 0 +# Total Accepted: 51.2K +# Total Submissions: 73.9K +# Testcase Example: '[3,9,20,null,null,15,7]' +# +# 给定一个二叉树,找出其最大深度。 +# +# 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。 +# +# 说明: 叶子节点是指没有子节点的节点。 +# +# 示例: +# 给定二叉树 [3,9,20,null,null,15,7], +# +# ⁠ 3 +# ⁠ / \ +# ⁠ 9 20 +# ⁠ / \ +# ⁠ 15 7 +# +# 返回它的最大深度 3 。 +# +# +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + + +class Solution(object): + def maxDepth(self, root): + """ + :type root: TreeNode + :rtype: int + """ + if not root: + return 0 + return 1 + max(self.maxDepth(root.left), self.maxDepth(root.right)) diff --git a/Week_03/id_26/LeetCode_107_26.py b/Week_03/id_26/LeetCode_107_26.py new file mode 100644 index 00000000..50583c6c --- /dev/null +++ b/Week_03/id_26/LeetCode_107_26.py @@ -0,0 +1,63 @@ +# +# @lc app=leetcode.cn id=107 lang=python +# +# [107] 二叉树的层次遍历 II +# +# https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii/description/ +# +# algorithms +# Easy (60.77%) +# Likes: 108 +# Dislikes: 0 +# Total Accepted: 17.6K +# Total Submissions: 28.8K +# Testcase Example: '[3,9,20,null,null,15,7]' +# +# 给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历) +# +# 例如: +# 给定二叉树 [3,9,20,null,null,15,7], +# +# ⁠ 3 +# ⁠ / \ +# ⁠ 9 20 +# ⁠ / \ +# ⁠ 15 7 +# +# +# 返回其自底向上的层次遍历为: +# +# [ +# ⁠ [15,7], +# ⁠ [9,20], +# ⁠ [3] +# ] +# +# +# +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +import collections + + +class Solution(object): + def levelOrderBottom(self, root): + """ + :type root: TreeNode + :rtype: List[List[int]] + """ + queue, ans = collections.deque([(root, 0)]), [] + while queue: + node, level = queue.popleft() + if node: + if len(ans) < level+1: + ans.insert(0, []) + ans[-level-1] += [node.val] + queue.append((node.left, level+1)) + queue.append((node.right, level+1)) + return ans diff --git a/Week_03/id_26/LeetCode_111_26.py b/Week_03/id_26/LeetCode_111_26.py new file mode 100644 index 00000000..396edc39 --- /dev/null +++ b/Week_03/id_26/LeetCode_111_26.py @@ -0,0 +1,55 @@ +# +# @lc app=leetcode.cn id=111 lang=python +# +# [111] 二叉树的最小深度 +# +# https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/description/ +# +# algorithms +# Easy (38.70%) +# Likes: 125 +# Dislikes: 0 +# Total Accepted: 19K +# Total Submissions: 49K +# Testcase Example: '[3,9,20,null,null,15,7]' +# +# 给定一个二叉树,找出其最小深度。 +# +# 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 +# +# 说明: 叶子节点是指没有子节点的节点。 +# +# 示例: +# +# 给定二叉树 [3,9,20,null,null,15,7], +# +# ⁠ 3 +# ⁠ / \ +# ⁠ 9 20 +# ⁠ / \ +# ⁠ 15 7 +# +# 返回它的最小深度  2. +# +# +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + + +class Solution(object): + def minDepth(self, root): + """ + :type root: TreeNode + :rtype: int + """ + if not root: + return 0 + left = self.minDepth(root.left) + right = self.minDepth(root.right) + if not left or not right: + return 1 + left + right + return 1 + min(left, right) diff --git a/Week_03/id_26/LeetCode_200_26.py b/Week_03/id_26/LeetCode_200_26.py new file mode 100644 index 00000000..5c612da5 --- /dev/null +++ b/Week_03/id_26/LeetCode_200_26.py @@ -0,0 +1,74 @@ +# +# @lc app=leetcode.cn id=200 lang=python +# +# [200] 岛屿数量 +# +# https://leetcode-cn.com/problems/number-of-islands/description/ +# +# algorithms +# Medium (43.81%) +# Likes: 167 +# Dislikes: 0 +# Total Accepted: 16K +# Total Submissions: 36.5K +# Testcase Example: '[["1","1","1","1","0"],["1","1","0","1","0"],["1","1","0","0","0"],["0","0","0","0","0"]]' +# +# 给定一个由 '1'(陆地)和 +# '0'(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。 +# +# 示例 1: +# +# 输入: +# 11110 +# 11010 +# 11000 +# 00000 +# +# 输出: 1 +# +# +# 示例 2: +# +# 输入: +# 11000 +# 11000 +# 00100 +# 00011 +# +# 输出: 3 +# +# +# + + +class Solution(object): + def numIslands(self, grid): + """ + :type grid: List[List[str]] + :rtype: int + """ + + dx, dy = [1, -1, 0, 0], [0, 0, 1, -1] + + def sink(i, j): + if i < 0 or i == len(grid) or j < 0 or j == len( + grid[i]) or grid[i][j] == '0': + return 0 + grid[i][j] = '0' + for k in range(4): + sink(i + dx[k], j + dy[k]) + return 1 + + ans = 0 + for i in range(len(grid)): + for j in range(len(grid[i])): + ans += sink(i, j) + return ans + + +# print(Solution().numIslands([["1", "1", "1", "1", "0"], +# ["1", "1", "0", "1", "0"], +# ["1", "1", "0", "0", "0"], +# ["0", "0", "0", "0", "0"]])) + +# print(Solution().numIslands([])) diff --git a/Week_03/id_26/LeetCode_295_26.py b/Week_03/id_26/LeetCode_295_26.py new file mode 100644 index 00000000..03a5f132 --- /dev/null +++ b/Week_03/id_26/LeetCode_295_26.py @@ -0,0 +1,83 @@ +# +# @lc app=leetcode.cn id=295 lang=python +# +# [295] 数据流的中位数 +# +# https://leetcode-cn.com/problems/find-median-from-data-stream/description/ +# +# algorithms +# Hard (35.43%) +# Likes: 46 +# Dislikes: 0 +# Total Accepted: 3.3K +# Total Submissions: 9.2K +# Testcase Example: '["MedianFinder","addNum","addNum","findMedian","addNum","findMedian"]\n[[],[1],[2],[],[3],[]]' +# +# 中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。 +# +# 例如, +# +# [2,3,4] 的中位数是 3 +# +# [2,3] 的中位数是 (2 + 3) / 2 = 2.5 +# +# 设计一个支持以下两种操作的数据结构: +# +# +# void addNum(int num) - 从数据流中添加一个整数到数据结构中。 +# double findMedian() - 返回目前所有元素的中位数。 +# +# +# 示例: +# +# addNum(1) +# addNum(2) +# findMedian() -> 1.5 +# addNum(3) +# findMedian() -> 2 +# +# 进阶: +# +# +# 如果数据流中所有整数都在 0 到 100 范围内,你将如何优化你的算法? +# 如果数据流中 99% 的整数都在 0 到 100 范围内,你将如何优化你的算法? +# +# +# +""" +维护大顶堆、小顶堆,满足以下条件: + +大顶堆中数字的个数 - 小顶堆数字的个数 = 0 or 1 +大顶堆的最大值 <= 小顶堆的最小值 +当长度为偶数时,中位数为大小顶堆的平均数 当长度为奇数时,中位数为大顶堆的最大值 + +注:python的heapq中只有小顶堆,所以存入时取负数则为大顶堆 +""" +import heapq + + +class MedianFinder(object): + def __init__(self): + """ + initialize your data structure here. + """ + self.len = 0 + self.max_heap, self.min_heap = [], [] + + def addNum(self, num): + """ + :type num: int + :rtype: None + """ + self.len += 1 + heapq.heappush(self.min_heap, -heapq.heappushpop(self.max_heap, num)) + if len(self.min_heap) > len(self.max_heap): + heapq.heappush(self.max_heap, -heapq.heappop(self.min_heap)) + + def findMedian(self): + """ + :rtype: float + """ + if self.len & 1 == 0: + return (self.max_heap[0] - self.min_heap[0]) / 2.0 + return self.max_heap[0] diff --git a/Week_03/id_26/LeetCode_329_26.py b/Week_03/id_26/LeetCode_329_26.py new file mode 100644 index 00000000..34927ea5 --- /dev/null +++ b/Week_03/id_26/LeetCode_329_26.py @@ -0,0 +1,98 @@ +# +# @lc app=leetcode.cn id=329 lang=python +# +# [329] 矩阵中的最长递增路径 +# +# https://leetcode-cn.com/problems/longest-increasing-path-in-a-matrix/description/ +# +# algorithms +# Hard (37.94%) +# Likes: 53 +# Dislikes: 0 +# Total Accepted: 2.8K +# Total Submissions: 7.2K +# Testcase Example: '[[9,9,4],[6,6,8],[2,1,1]]' +# +# 给定一个整数矩阵,找出最长递增路径的长度。 +# +# 对于每个单元格,你可以往上,下,左,右四个方向移动。 你不能在对角线方向上移动或移动到边界外(即不允许环绕)。 +# +# 示例 1: +# +# 输入: nums = +# [ +# ⁠ [9,9,4], +# ⁠ [6,6,8], +# ⁠ [2,1,1] +# ] +# 输出: 4 +# 解释: 最长递增路径为 [1, 2, 6, 9]。 +# +# 示例 2: +# +# 输入: nums = +# [ +# ⁠ [3,4,5], +# ⁠ [3,2,6], +# ⁠ [2,2,1] +# ] +# 输出: 4 +# 解释: 最长递增路径是 [3, 4, 5, 6]。注意不允许在对角线方向上移动。 +# +# +# + + +class Solution(object): + def longestIncreasingPath(self, matrix): + """ + :type matrix: List[List[int]] + :rtype: int + 解法1:时间复杂度O(n^2) + """ + if not matrix or not matrix[0]: + return 0 + m, n = len(matrix), len(matrix[0]) + sm = [] + for i in range(m): + for j in range(n): + sm.append((matrix[i][j], i, j,)) + sm.sort() + + dxy = [0, 1, 0, -1, 0] + dp = [[1] * n for i in range(m)] + for v, i, j in sm: + for k in range(4): + di, dj = i + dxy[k], j + dxy[k+1] + if 0 <= di < m and 0 <= dj < n and matrix[i][j] > matrix[di][dj]: + dp[i][j] = max(dp[i][j], dp[di][dj]+1) + return max(dp[i][j] for j in range(n) for i in range(m)) + + def longestIncreasingPath2(self, matrix): + """ + :type matrix: List[List[int]] + :rtype: int + 解法2:时间复杂度O(n^3) 会超时 + """ + if not matrix: + return 0 + self.ret = 0 + dxy = [0, 1, 0, -1, 0] + + def dfs(i, j, path=[], cache=cache): + if i < 0 or j < 0 or i == m or j == n or (path and matrix[i][j] <= path[-1]): + self.ret = max(self.ret, len(path)) + return + for n in range(4): + dfs(i + dxy[n], j + dxy[n+1], path + [matrix[i][j]], cache) + for i in range(len(matrix)): + for j in range(len(matrix[i])): + dfs(i, j, []) + return self.ret + + +print(Solution().longestIncreasingPath([[1]])) +print(Solution().longestIncreasingPath([])) +print(Solution().longestIncreasingPath([[9, 9, 4], [6, 6, 8], [2, 1, 1]])) +print(Solution().longestIncreasingPath([[3, 4, 5], [3, 2, 6], [2, 2, 1]])) +# print(Solution().longestIncreasingPath([[75,26,75,88,8,6,38,34,20,80,91,96,44,86,65,81,84,73,72,17,50,92,80,31,23,75,85,86,46,65,57,42,58,20,64,1,79,46,75,8,28,74,81,40,4,45,86,90,34,4,73,99,84,11,41,30,85,18,76,28,3,36,45,29,80,24,32,56,84,37,96,57,37,23,33,12,38,56,25,31,71,18,85,33,93,58,44,46,54,5,76,47,17,24,20,38,47,9,58,59,95,86,58,74,70,38,21,68,25,34,21,62,65,91,6,45,8,61,14,20,41,62,65,81,64,97,94,46,6,92,47,25,33,17,49,46,21,56,48,9,78,56,27],[32,45,77,3,58,22,53,66,52,80,71,75,32,81,23,81,20,44,33,77,10,38,82,0,74,25,90,62,97,79,80,98,55,83,46,52,40,37,89,78,52,93,5,78,30,36,3,39,13,54,32,78,45,20,78,0,53,57,73,59,13,40,48,92,15,22,71,85,91,61,86,47,59,38,68,14,90,59,0,0,81,21,93,60,92,49,16,21,96,62,80,8,25,4,84,39,99,96,92,94,66,53,62,56,59,1,7,12,4,64,7,26,47,75,67,93,70,77,45,50,50,5,33,99,97,55,14,27,24,12,21,92,39,25,19,19,29,87,11,34,75,47,70],[50,16,69,59,20,11,95,83,0,20,96,29,30,18,98,24,26,65,85,90,41,69,22,1,61,84,28,4,46,81,7,59,47,71,27,33,34,75,31,36,11,41,0,68,60,58,44,9,37,7,45,78,27,92,23,62,57,32,93,70,31,45,64,74,75,24,53,9,81,38,22,95,86,42,65,90,1,98,37,45,7,18,22,82,13,64,68,64,52,98,39,93,33,83,31,17,67,44,19,22,34,60,87,9,14,14,19,63,77,47,14,9,78,65,77,74,67,97,58,70,18,58,93,24,68,35,79,38,83,95,64,25,90,9,75,36,79,22,70,30,13,71,15],[20,75,8,50,93,93,79,20,24,51,71,70,48,33,5,40,0,6,48,34,90,72,61,41,78,8,74,97,24,55,68,22,78,46,12,97,33,32,34,3,71,38,94,42,53,2,73,67,79,61,0,3,65,88,84,33,35,58,81,42,17,73,96,66,24,82,53,14,4,42,94,46,30,7,90,32,23,21,47,96,68,79,26,53,26,62,70,84,89,29,63,19,93,21,49,92,96,52,46,89,47,85,32,66,85,84,60,62,46,25,23,13,58,66,83,2,80,90,43,9,38,36,69,2,23,1,93,38,16,3,7,74,74,16,98,74,49,51,23,14,53,14,53],[29,5,75,94,7,80,21,63,85,13,84,75,77,92,33,50,51,4,32,93,21,56,35,69,50,28,89,16,61,5,8,89,5,53,5,88,89,62,89,59,3,23,68,48,93,40,11,26,44,38,27,68,57,86,2,53,63,68,45,7,64,74,95,79,75,79,14,17,18,18,48,65,27,90,33,49,15,55,92,11,36,48,12,3,88,96,50,54,44,9,20,63,13,20,68,31,94,78,43,80,83,87,49,58,70,92,83,33,25,12,9,0,0,29,90,15,40,50,21,37,93,49,90,32,61,6,58,53,63,94,87,81,75,70,60,35,68,5,66,61,24,53,97],[96,87,58,22,11,71,20,45,12,51,98,34,83,40,61,44,33,33,48,71,33,84,83,41,34,67,99,61,40,83,68,71,1,57,86,95,92,87,21,89,24,10,8,61,16,25,41,68,64,85,71,3,4,65,10,1,56,89,52,45,35,60,98,70,54,35,65,98,61,57,7,13,38,16,61,87,18,22,22,29,0,50,67,39,93,41,59,66,82,34,35,41,57,42,78,67,83,68,11,23,79,53,28,85,0,36,91,47,49,10,56,76,6,96,89,6,80,10,25,42,70,45,36,58,67,12,50,79,43,77,1,25,41,71,56,45,0,11,97,46,74,60,90],[27,55,4,59,37,30,66,85,56,78,6,16,24,20,0,72,43,32,93,53,17,88,43,13,45,28,3,43,99,9,2,73,52,89,65,27,39,15,67,71,72,56,78,70,47,13,52,85,61,17,32,46,7,92,72,29,34,22,52,2,36,85,10,61,14,5,8,37,53,70,35,55,30,94,44,98,10,13,74,57,91,14,79,17,83,71,96,41,59,80,24,97,47,67,13,2,81,0,60,83,83,96,63,77,34,62,88,81,17,77,12,35,48,71,41,48,36,52,6,21,64,72,10,72,28,38,8,35,57,20,85,19,0,40,11,36,61,6,7,46,70,13,47],[21,0,36,59,86,34,85,65,61,21,80,11,63,81,83,77,69,66,47,52,52,5,47,99,13,22,16,96,53,67,36,75,81,20,5,0,47,83,3,34,72,42,10,41,99,99,57,93,60,12,67,25,54,82,64,39,60,16,22,0,66,61,55,52,28,42,98,48,7,77,69,22,92,19,61,16,59,33,41,11,84,48,46,42,6,70,32,70,76,45,7,10,2,95,1,74,58,64,99,84,23,0,83,11,59,17,96,35,3,57,66,5,1,16,66,21,79,90,78,34,51,48,30,87,4,22,18,85,82,60,88,60,94,26,94,26,53,66,33,22,12,40,9],[26,6,90,85,90,97,14,83,94,83,14,89,78,40,66,99,48,33,44,93,6,97,37,10,79,40,84,75,61,92,18,86,74,0,5,54,48,57,9,15,97,81,53,91,59,98,62,64,13,11,75,66,40,26,65,18,46,82,90,70,21,10,2,12,32,19,21,40,7,26,72,29,96,29,67,92,27,79,3,40,30,92,38,44,18,91,8,71,79,21,76,6,46,75,57,75,57,87,87,1,68,64,79,33,40,86,94,64,65,6,93,44,25,0,99,21,59,80,44,0,45,98,7,90,67,45,10,60,58,87,85,12,62,63,85,84,79,6,80,82,94,67,15],[7,20,74,84,26,87,67,89,66,14,72,97,60,44,99,70,7,93,57,77,21,37,12,31,30,14,87,28,28,65,35,22,6,0,99,7,87,51,6,0,32,93,70,84,27,30,29,89,95,87,95,70,67,58,34,8,78,25,86,86,61,86,21,18,85,93,43,90,17,30,56,17,27,41,67,27,99,44,35,86,28,60,94,52,52,48,41,26,97,64,78,59,25,30,89,22,82,35,90,44,26,0,33,48,31,19,24,86,92,82,54,51,95,60,29,35,47,56,22,31,54,31,17,37,52,32,79,83,52,10,0,5,71,66,22,52,34,12,33,49,78,5,89],[13,68,67,90,63,32,93,35,51,53,93,37,42,62,20,72,56,81,50,4,14,17,59,82,10,95,46,85,20,53,76,57,3,46,69,51,0,39,68,86,63,64,56,27,53,11,79,71,95,69,90,23,57,78,64,77,50,12,78,2,67,1,44,12,71,66,81,89,7,72,88,79,51,84,74,27,50,79,13,68,58,85,28,25,0,8,88,68,39,77,24,58,39,34,92,28,34,23,97,48,63,15,77,76,39,16,65,0,25,7,13,40,65,97,7,61,94,21,28,1,6,15,64,98,11,13,53,40,59,58,39,83,68,44,64,51,50,97,47,32,18,25,51],[66,85,72,46,85,47,43,67,10,74,54,85,42,78,64,58,17,51,38,89,75,6,63,92,83,65,74,53,5,26,42,76,82,14,10,22,95,47,92,25,91,8,61,1,61,27,12,47,30,30,80,61,68,17,36,17,13,35,25,11,92,75,50,3,56,36,41,52,28,94,82,99,62,36,81,59,77,83,5,17,63,79,44,56,46,37,7,36,80,53,94,78,36,83,61,60,1,18,94,66,56,8,44,84,13,42,29,18,0,7,75,71,12,63,29,74,81,19,64,25,64,75,66,83,51,13,56,32,48,61,7,5,94,86,45,53,31,13,38,40,54,60,27],[13,70,78,47,31,92,33,27,90,33,5,40,41,83,29,57,22,21,8,32,49,64,55,71,57,69,22,19,7,1,64,51,8,16,19,39,7,77,21,49,62,64,30,21,79,77,51,17,27,25,65,0,94,56,35,25,96,94,68,5,88,80,37,48,0,26,75,9,90,66,86,32,50,39,7,41,1,85,44,89,74,15,93,72,51,67,2,34,43,22,32,31,31,6,74,3,76,96,50,72,96,83,72,5,48,65,75,39,46,83,70,51,55,95,47,39,34,68,0,44,53,33,66,38,76,48,91,6,40,87,99,68,92,98,36,16,48,3,91,52,40,26,23],[21,83,41,41,42,34,9,13,26,19,36,25,53,19,42,32,71,4,74,59,18,92,61,44,42,96,99,55,39,5,19,14,69,9,70,64,5,22,44,78,88,16,89,46,13,96,91,30,56,81,77,30,14,14,9,42,9,79,92,10,12,90,74,3,69,46,1,67,47,84,98,66,14,88,87,29,1,3,20,71,3,51,93,99,3,48,78,24,31,22,94,77,85,20,23,34,15,45,86,7,28,62,67,52,48,76,63,77,30,48,34,89,22,52,53,27,98,28,0,32,54,47,50,68,43,25,37,51,57,51,94,48,53,1,34,98,30,43,75,36,92,82,50],[87,43,11,41,13,74,47,50,5,75,74,90,30,76,18,82,75,49,99,71,85,58,33,93,72,80,22,42,7,90,71,99,49,24,5,25,39,16,1,86,60,79,30,65,24,36,19,88,16,93,85,51,79,62,30,66,44,90,88,48,29,8,37,12,35,71,4,22,87,79,70,34,67,60,19,68,22,51,24,59,48,11,42,74,82,61,96,50,63,12,81,41,84,59,45,52,6,99,24,95,61,56,50,11,15,56,85,69,51,63,12,93,50,97,17,82,14,20,15,44,50,58,66,54,44,95,63,36,36,75,64,4,78,70,53,48,73,46,94,43,56,95,9],[88,30,70,34,65,58,63,91,54,32,32,90,34,39,27,7,32,7,57,56,50,26,58,23,6,20,49,43,30,53,1,33,62,69,58,34,11,6,13,7,42,41,94,70,30,23,48,69,11,90,28,44,80,49,76,63,38,44,75,18,26,49,29,50,65,21,68,5,42,32,31,13,85,9,32,33,32,32,5,77,63,1,68,89,30,70,23,19,82,57,87,46,20,61,60,54,45,8,86,45,96,58,8,39,43,64,42,92,82,43,35,35,34,56,9,87,68,62,59,45,22,71,72,20,91,93,42,11,16,64,99,21,52,12,37,83,28,26,1,17,40,12,93],[47,13,95,58,17,3,20,53,54,64,91,48,55,88,20,30,35,16,19,83,94,18,52,65,19,35,76,47,47,4,15,60,29,91,51,25,3,62,85,73,19,34,16,10,23,57,79,92,67,78,32,74,98,75,4,65,52,25,89,5,39,52,79,67,32,82,38,13,26,41,21,98,94,97,21,6,21,40,58,93,43,46,27,84,88,6,16,16,22,70,60,75,64,75,65,63,37,96,46,10,13,61,20,48,48,41,44,19,53,29,0,81,11,32,65,69,45,63,66,95,1,42,59,10,43,93,73,63,33,38,94,96,44,84,45,57,9,26,80,79,17,58,54],[47,86,47,68,97,88,94,31,41,9,32,46,52,78,59,66,8,70,72,38,3,4,77,28,18,69,15,58,57,39,9,91,16,10,5,38,32,50,12,82,95,66,98,27,75,8,84,13,38,65,74,50,31,64,89,59,97,23,9,16,65,27,45,73,27,98,92,70,14,62,88,73,69,48,34,39,9,90,20,53,52,58,31,35,84,45,54,36,86,29,68,56,31,4,62,14,65,33,32,24,35,48,70,57,22,2,49,7,56,31,56,64,90,93,72,27,46,94,6,48,92,42,28,0,15,66,13,18,17,49,15,12,91,89,39,46,90,2,94,78,50,44,58],[19,61,30,37,84,81,76,52,82,68,41,8,26,29,86,53,14,0,28,43,30,14,28,78,7,42,58,47,84,29,32,92,45,81,89,86,45,30,18,21,3,14,87,78,1,25,31,10,38,97,11,13,83,68,58,35,97,26,32,62,85,63,7,38,8,9,38,94,90,23,88,79,3,88,93,44,2,39,58,80,82,65,34,33,45,10,42,58,27,57,94,56,89,62,22,22,17,90,40,83,71,97,27,49,81,33,89,51,67,7,98,32,49,67,85,83,54,30,85,4,23,16,49,81,93,68,68,58,87,63,61,43,81,68,86,55,2,99,84,66,61,45,71],[97,0,4,28,82,45,61,65,32,14,94,37,24,11,63,37,37,32,56,31,95,10,25,97,42,14,98,2,59,57,94,62,24,22,36,47,72,86,55,29,22,19,68,6,31,77,62,2,52,13,7,59,74,80,50,57,81,8,55,15,28,18,68,46,15,52,98,10,59,13,81,90,31,52,61,80,28,66,80,19,50,77,61,22,34,65,44,46,76,89,18,71,26,16,84,88,68,34,10,49,8,7,45,98,1,46,10,23,60,6,75,87,23,82,9,90,97,55,64,51,60,29,98,86,5,95,90,7,2,15,21,75,94,22,81,65,87,16,66,54,22,65,22],[78,39,65,97,68,32,74,48,36,23,87,43,63,96,27,79,91,6,68,7,38,31,96,55,90,18,68,70,83,8,0,53,88,43,69,61,96,83,72,86,13,95,68,58,60,45,89,77,25,58,41,51,76,29,84,56,61,76,79,45,60,60,9,88,50,1,43,14,62,69,70,56,3,8,88,91,23,58,55,49,8,8,98,74,30,81,2,41,63,72,88,64,11,75,94,83,64,88,99,79,49,52,9,52,6,48,22,25,97,48,15,20,41,44,70,99,77,10,6,52,35,26,41,99,6,17,2,5,37,93,56,33,27,90,12,48,0,17,31,1,79,10,84],[96,99,20,65,23,19,10,80,19,53,50,55,33,34,45,93,96,65,22,23,60,6,44,47,86,16,2,58,14,99,6,2,75,82,26,33,5,25,51,57,65,66,37,5,54,23,33,99,91,41,26,92,99,48,9,18,8,79,24,97,21,10,26,25,39,47,97,32,78,7,58,99,41,86,50,40,63,21,99,44,38,68,69,2,10,83,87,93,60,83,93,42,57,48,3,14,50,61,78,98,77,40,19,60,29,3,14,48,72,72,60,1,17,62,31,62,26,29,0,56,85,72,75,49,59,37,85,39,14,89,87,89,79,90,22,7,72,95,71,4,52,92,59],[16,72,48,45,12,83,84,85,56,50,57,98,95,58,81,72,58,57,66,66,51,19,64,58,28,57,18,67,61,83,41,86,83,84,81,18,23,80,97,82,75,53,50,88,80,79,7,15,58,73,36,38,28,10,29,60,48,94,75,69,55,99,14,71,13,39,38,31,52,22,92,58,51,13,79,51,84,50,21,19,99,24,80,56,50,51,63,4,25,38,34,14,33,29,17,7,62,22,74,34,27,88,37,75,3,94,66,10,78,26,25,8,93,13,21,3,83,27,48,50,13,61,72,69,36,47,44,78,58,33,33,69,31,31,88,19,31,71,24,1,71,23,61],[18,76,19,56,31,95,2,13,46,42,10,56,2,92,61,65,72,94,36,56,32,29,58,28,67,8,2,3,49,14,10,51,64,29,52,12,68,16,55,79,55,34,23,7,89,16,3,54,28,44,80,11,5,93,42,15,30,84,70,66,97,60,19,68,55,54,99,98,83,60,58,28,38,72,83,60,94,45,15,28,75,18,87,40,54,6,10,95,94,69,75,38,57,65,1,0,56,49,28,69,95,91,49,89,7,4,62,95,34,51,96,83,25,39,98,21,22,77,7,58,97,86,85,78,26,85,68,52,40,9,3,25,40,74,37,54,62,11,80,13,65,97,80],[23,82,91,5,50,89,38,60,22,32,23,96,14,71,35,74,81,42,70,7,91,15,89,64,2,2,99,33,93,49,84,75,56,53,62,97,82,96,80,90,44,15,64,96,27,24,80,16,38,36,0,62,74,90,40,2,95,56,62,93,88,52,24,94,22,8,40,96,97,70,52,89,29,50,49,1,25,89,3,96,14,44,24,55,98,95,42,38,48,56,19,28,97,25,8,48,97,61,18,64,36,63,29,88,99,80,30,79,10,35,33,46,65,92,40,94,24,38,88,13,68,98,62,46,92,88,57,6,64,97,82,87,30,4,36,99,11,78,40,90,16,81,14],[1,42,48,78,15,92,17,89,90,61,82,43,51,58,86,18,0,77,7,38,31,79,47,21,47,61,64,26,98,67,7,89,62,83,38,41,70,44,42,63,74,53,15,58,28,26,21,85,29,78,85,49,94,24,2,52,56,40,82,75,20,50,33,59,81,74,4,45,7,30,52,79,24,49,58,84,43,57,72,11,10,61,21,3,50,93,53,76,53,22,44,21,34,81,16,28,44,16,59,50,34,86,12,60,49,85,31,3,73,30,24,15,78,52,64,29,9,13,38,66,66,78,17,48,73,69,95,91,42,74,95,69,35,51,81,96,57,25,94,29,38,49,47],[15,85,64,74,1,21,40,11,49,33,71,6,90,37,81,83,93,13,50,64,80,55,1,7,88,87,13,66,73,75,59,40,48,57,89,2,69,85,54,87,50,51,2,67,73,47,98,86,70,33,25,25,69,4,21,38,43,47,49,12,67,18,15,7,98,67,39,9,67,0,24,11,57,58,0,55,79,33,18,34,41,99,11,71,71,63,10,11,75,18,81,52,75,0,70,12,68,14,6,96,93,92,82,22,42,46,95,72,98,96,76,78,59,23,3,2,90,12,45,0,97,92,77,94,50,86,71,60,39,83,2,96,34,56,70,8,16,83,72,36,65,17,34],[43,0,92,75,54,30,80,1,12,52,0,4,54,90,10,62,10,30,13,58,12,34,40,51,77,48,47,51,4,24,34,36,72,7,90,6,3,83,85,26,20,10,86,84,39,45,49,0,15,58,69,84,31,38,43,94,82,41,17,8,20,91,13,10,5,37,78,39,20,89,24,21,50,0,83,71,14,62,56,85,85,87,2,10,60,64,99,61,61,44,47,27,59,87,0,61,6,98,88,0,82,73,42,61,21,85,99,42,31,25,69,91,86,8,14,50,12,94,35,72,85,65,29,80,55,54,1,21,11,97,15,83,61,62,81,43,17,46,41,10,50,10,86],[16,18,58,17,42,63,55,99,29,11,63,36,86,62,66,50,85,9,23,56,37,13,64,6,22,71,15,42,61,27,1,17,92,55,81,96,19,80,23,79,23,53,7,19,19,69,66,9,57,55,96,54,79,61,19,18,46,33,31,9,4,21,47,52,42,95,13,71,97,56,46,31,83,10,49,27,21,31,38,44,33,82,3,14,15,26,91,51,20,50,79,83,95,89,22,50,70,97,25,1,48,52,60,55,11,42,20,24,82,6,14,53,46,61,85,75,78,88,72,31,91,23,99,35,29,47,64,94,97,89,25,86,48,34,18,19,19,29,33,89,16,64,7],[51,88,76,29,42,19,63,39,88,72,86,46,98,56,10,92,38,98,72,79,87,41,38,6,43,54,12,32,19,44,98,47,61,54,83,60,38,84,3,39,96,86,62,69,99,7,60,74,33,77,13,81,64,91,70,34,39,12,22,12,29,2,16,32,73,60,50,70,48,72,99,75,22,38,19,12,87,49,71,99,71,79,24,8,84,54,68,1,23,90,88,14,59,82,69,13,94,34,58,59,52,35,36,33,81,86,33,62,86,60,92,73,63,68,14,7,76,25,85,95,24,47,36,90,3,96,23,82,72,30,26,78,85,80,74,93,75,57,45,20,15,10,75],[98,11,18,5,71,75,70,9,60,4,27,68,15,50,40,52,19,22,53,27,4,43,84,33,65,23,28,50,50,74,36,47,56,82,16,7,56,22,67,99,5,12,59,32,46,39,74,49,44,62,37,63,28,75,72,81,14,72,9,57,67,52,11,94,21,20,19,40,25,12,41,29,72,4,66,58,31,59,45,98,90,47,61,56,99,1,62,41,9,16,20,28,44,45,97,78,52,9,29,2,51,42,64,81,51,13,93,16,41,9,35,86,55,25,58,98,49,24,67,26,17,82,36,25,12,92,75,80,33,33,74,67,69,47,85,48,5,13,95,61,73,63,42],[70,61,44,91,83,74,25,79,28,10,70,29,92,33,41,16,67,73,76,40,98,61,52,82,6,90,41,61,49,10,29,56,22,71,20,60,89,77,51,34,94,12,76,16,99,53,10,10,25,70,18,42,52,81,9,95,62,34,78,74,25,22,40,91,50,57,1,14,31,95,82,24,6,99,60,8,20,88,44,84,36,66,35,69,99,9,28,38,94,57,54,74,44,55,11,28,22,35,15,5,81,27,84,93,86,84,45,70,18,51,6,2,9,60,31,63,89,15,44,74,20,16,54,2,22,61,39,19,77,62,94,3,60,22,46,80,71,73,69,68,21,82,69],[87,4,40,74,12,78,20,67,75,40,26,15,89,44,45,80,84,68,76,86,90,79,12,71,91,53,52,47,5,46,41,48,61,20,46,32,18,88,39,45,8,32,50,75,39,16,7,97,43,91,15,99,18,14,24,24,52,47,68,67,11,16,11,16,94,19,94,41,36,57,18,92,7,82,90,96,53,52,43,6,12,10,34,74,58,82,87,44,81,10,37,81,42,43,37,80,47,99,85,29,3,52,50,13,82,20,25,57,43,52,68,29,6,61,21,97,46,49,37,65,12,55,71,66,34,27,46,78,0,89,65,36,89,66,35,94,66,48,8,21,79,90,91],[99,7,47,0,93,79,34,57,7,30,51,98,8,0,33,51,42,45,68,32,19,18,93,20,35,27,90,53,50,59,72,47,26,69,77,7,98,56,98,52,15,87,81,79,84,96,40,28,77,42,94,85,16,16,87,38,19,45,92,98,6,19,93,93,62,58,31,63,25,26,34,82,68,11,28,64,22,80,9,85,58,59,45,76,96,74,88,8,99,52,72,41,79,90,18,81,22,68,21,15,40,20,35,70,51,50,67,27,70,87,70,93,50,68,86,1,12,1,34,63,18,48,39,8,4,52,46,39,11,28,90,70,4,86,13,57,24,96,99,7,28,82,1],[25,81,64,17,93,30,11,55,71,41,89,9,98,65,62,17,74,8,83,87,26,70,37,54,51,18,69,12,72,97,67,45,44,2,21,81,10,47,4,82,24,19,11,82,0,33,47,55,2,50,63,0,3,28,64,16,63,37,68,25,95,39,74,79,3,46,78,68,14,44,63,99,97,21,25,69,44,78,64,25,89,77,77,9,91,75,83,14,34,71,23,79,42,7,25,93,98,68,46,32,4,43,20,63,11,98,85,96,28,51,72,57,49,71,48,85,59,76,55,4,4,13,84,7,35,34,59,41,20,44,34,78,92,66,60,9,53,59,29,21,22,0,39],[74,31,71,82,22,72,97,64,43,84,1,37,74,8,82,81,67,82,95,42,42,26,63,10,77,72,84,22,68,0,53,78,73,10,59,98,62,57,36,89,14,31,59,76,43,59,25,93,37,28,65,79,75,54,32,22,76,80,88,25,59,49,50,0,88,51,43,67,10,90,24,30,57,21,54,58,85,95,17,67,37,13,81,43,22,97,76,73,61,4,95,96,44,49,67,34,30,98,4,23,69,91,56,23,80,17,67,31,39,41,99,73,82,34,28,26,60,45,66,27,12,25,2,72,9,0,56,3,67,54,82,0,37,12,34,13,84,92,69,23,70,83,60],[66,1,67,26,94,70,36,44,46,17,95,77,57,19,47,77,36,95,76,36,55,80,57,93,8,32,49,61,62,6,3,7,67,4,56,49,70,83,89,12,36,1,57,39,18,81,21,30,75,27,36,94,33,35,99,16,59,68,38,31,68,38,99,11,10,53,67,96,58,53,20,0,69,71,88,5,21,10,57,3,71,82,93,18,92,14,96,85,6,25,28,5,17,36,5,66,87,35,43,69,69,50,78,79,92,95,76,62,69,45,1,48,69,1,4,61,45,41,86,95,94,13,26,34,52,54,36,94,45,63,54,0,25,24,37,17,89,65,4,2,5,83,32],[41,95,50,21,1,40,23,28,82,30,15,38,16,31,25,88,93,44,40,21,66,84,63,95,98,5,74,1,7,51,60,15,54,69,55,99,46,60,13,2,57,86,8,97,3,56,44,18,22,57,22,36,35,31,13,98,57,67,41,39,26,45,43,36,72,78,28,71,91,87,67,25,42,99,82,18,0,52,69,76,77,95,21,30,74,38,12,32,48,84,86,57,98,4,78,57,69,66,67,93,21,52,65,67,68,76,0,27,39,80,30,52,97,58,98,24,83,98,25,36,62,99,18,96,88,5,39,60,22,2,2,8,32,18,98,34,35,90,6,9,3,26,72],[1,76,67,24,42,31,77,84,42,91,52,72,40,59,90,95,55,56,41,68,25,46,91,79,97,71,24,48,91,17,59,51,67,1,85,11,75,30,31,65,39,87,96,40,64,41,12,70,77,49,31,65,27,42,69,93,3,60,66,79,47,4,35,63,82,32,45,24,24,51,54,27,77,18,42,26,17,58,87,75,2,74,13,2,28,30,25,25,19,18,57,14,10,96,42,83,78,25,74,1,49,87,29,43,58,60,43,79,83,7,94,75,43,28,47,74,65,82,59,58,98,81,69,58,39,51,19,28,15,84,49,4,37,5,20,93,65,5,50,58,33,8,31],[90,26,61,51,29,49,83,52,58,53,53,48,45,31,50,32,82,70,25,69,93,65,38,58,89,90,89,31,16,28,44,53,20,49,15,19,68,90,13,77,3,41,14,4,93,34,80,84,1,90,52,10,66,72,73,76,71,21,88,43,71,80,11,91,9,99,4,39,65,37,99,77,99,1,20,85,37,51,2,46,77,74,85,21,77,39,35,87,30,98,99,13,9,24,2,55,40,68,54,34,6,34,73,35,18,4,91,66,58,63,63,51,21,96,32,29,73,18,51,97,59,54,52,42,1,17,1,31,59,88,51,72,19,48,28,59,62,8,72,71,43,26,77],[64,82,24,45,91,7,77,70,35,26,11,12,53,59,34,63,92,24,35,17,94,22,16,84,76,9,85,77,53,56,43,68,91,4,16,60,10,10,83,67,1,67,55,67,62,68,80,65,10,47,33,14,99,93,53,48,88,60,77,35,23,21,63,69,25,30,70,85,50,6,69,47,83,21,33,65,2,99,11,22,53,70,55,36,4,23,92,49,13,11,5,94,14,27,46,79,38,14,8,24,8,79,74,26,1,18,21,7,8,40,27,42,13,47,32,6,24,5,21,6,61,66,94,19,53,1,64,55,54,50,48,89,23,30,67,23,51,60,63,63,77,24,11],[43,94,47,64,16,7,66,11,68,50,48,31,24,32,75,67,25,13,19,25,53,27,85,56,38,52,67,24,14,52,14,52,42,40,94,79,97,46,14,48,98,37,30,76,43,28,13,34,0,75,69,79,38,9,55,60,12,26,9,78,9,13,78,53,34,43,32,9,47,96,45,37,21,50,20,33,62,4,0,75,73,7,39,70,53,57,29,49,45,75,44,59,94,93,96,79,65,54,36,90,5,78,60,69,16,81,18,74,66,32,91,51,43,67,31,3,63,94,25,12,48,65,6,30,55,20,89,38,15,47,32,47,39,23,33,74,68,90,84,84,84,49,98],[10,90,21,19,44,34,32,94,12,86,82,89,83,50,60,68,50,25,40,22,6,17,55,67,64,33,5,9,93,50,63,14,3,19,50,60,3,55,59,48,19,14,55,45,50,89,43,85,6,14,54,14,33,55,79,3,21,90,41,66,51,26,57,26,91,10,91,50,75,59,96,68,73,21,16,12,95,2,13,37,18,15,86,18,43,40,90,63,35,19,20,59,69,11,95,30,86,82,74,8,32,52,7,25,80,34,41,56,71,15,69,14,40,76,74,88,0,78,41,34,71,17,52,32,11,84,25,22,63,16,44,75,26,36,99,23,78,94,62,62,96,55,99],[22,38,56,15,69,81,20,43,8,96,76,67,16,61,99,72,39,55,43,17,47,42,9,0,74,64,64,99,22,12,21,44,77,53,19,93,65,28,66,64,57,83,63,11,4,20,18,36,40,65,36,85,92,26,65,15,39,53,29,8,68,50,31,91,89,80,23,40,48,75,5,61,30,76,58,41,16,54,79,88,29,3,75,4,86,88,22,59,33,18,28,1,67,74,76,57,20,8,69,11,25,45,47,61,2,70,2,45,64,53,13,64,59,99,99,57,64,43,98,80,16,71,54,29,64,57,19,16,58,29,31,16,78,82,85,29,86,26,83,43,28,88,52],[1,89,41,64,86,43,95,76,83,4,7,70,10,63,97,82,95,45,42,5,82,85,66,39,76,52,36,92,63,3,51,75,26,27,86,3,81,11,72,99,31,38,47,37,78,24,48,88,68,59,40,82,84,23,37,97,19,18,7,86,77,54,22,84,95,65,46,51,28,84,26,25,17,89,42,67,14,42,76,89,31,35,43,3,19,99,19,27,69,24,32,84,29,37,29,10,73,4,97,97,41,93,54,89,20,86,78,83,38,7,83,49,12,65,54,23,88,75,5,26,70,44,58,99,34,20,85,13,15,59,18,13,17,20,26,39,45,55,97,65,62,69,4],[68,20,78,66,15,13,57,25,20,79,92,87,98,74,38,8,93,50,30,93,34,12,75,88,30,26,90,55,39,38,53,19,98,75,33,87,74,83,74,93,30,75,39,25,38,63,97,84,62,57,46,4,61,71,23,19,92,34,91,61,2,50,82,9,11,15,70,28,85,66,97,32,77,34,93,80,31,6,83,96,76,80,93,29,13,15,43,63,96,38,72,91,12,90,78,36,11,19,53,58,60,54,20,71,35,21,91,97,48,24,57,12,63,20,54,81,54,67,97,21,94,9,3,89,85,98,95,62,82,20,75,48,50,35,93,24,57,87,40,36,45,87,38],[32,27,41,74,11,66,62,79,55,30,52,7,98,68,25,22,70,0,4,11,60,51,32,13,48,24,57,24,49,67,92,28,37,40,37,67,96,86,88,66,15,96,17,96,15,78,13,11,8,25,95,33,20,92,83,28,28,22,50,80,91,46,19,1,5,18,62,76,88,21,88,61,75,32,31,59,40,6,48,29,72,89,7,70,20,41,30,94,31,1,7,66,79,53,76,22,86,69,36,57,90,52,72,26,89,50,23,95,36,49,28,46,34,48,79,13,21,49,3,70,5,99,99,96,48,60,55,10,27,89,54,66,76,14,90,19,0,62,16,4,44,86,55],[28,71,50,84,54,31,52,4,57,82,14,18,46,0,12,55,71,12,83,0,80,3,25,75,5,88,44,55,46,3,50,98,24,29,71,72,37,26,3,98,11,82,68,41,42,76,33,50,99,65,9,7,66,26,85,56,96,50,84,63,42,22,41,17,70,50,40,71,7,49,78,2,28,82,91,95,46,11,62,70,71,98,40,10,32,67,95,7,40,24,26,20,71,21,30,16,17,29,11,40,59,17,60,22,72,60,46,49,9,91,76,45,39,88,60,50,23,74,54,93,92,72,46,35,58,3,57,63,94,82,73,87,1,37,86,99,82,26,44,70,20,77,30],[37,43,94,34,22,62,49,15,58,58,57,29,31,81,70,27,30,25,49,15,0,70,39,19,40,15,75,95,42,42,68,41,7,22,39,32,34,73,34,50,85,92,15,65,65,90,39,80,96,46,91,83,89,73,4,64,27,7,15,70,14,67,53,36,59,9,57,68,43,53,9,26,20,30,22,7,40,16,33,79,83,33,6,30,75,86,87,24,95,74,30,45,97,79,12,96,73,72,95,28,56,32,76,52,42,82,82,7,68,80,6,16,49,5,56,13,12,45,14,56,35,99,12,80,88,79,53,20,65,27,14,33,21,68,80,15,34,90,36,42,46,40,87],[80,60,15,72,42,43,99,22,48,85,47,34,62,62,53,43,73,27,54,64,84,71,49,28,3,78,67,22,18,77,58,31,55,74,39,90,11,45,51,90,46,35,98,27,37,75,36,46,54,55,88,63,31,58,5,90,22,84,45,66,97,2,38,59,12,48,29,82,86,61,29,95,41,15,88,11,52,84,89,32,20,9,62,78,0,41,58,7,29,33,48,23,21,84,74,31,52,74,0,36,37,47,81,73,95,47,5,34,99,96,78,47,99,0,72,68,9,20,59,63,22,26,75,45,7,43,44,38,82,12,30,97,6,48,48,87,20,44,40,56,58,56,86],[15,22,18,98,52,80,71,13,77,13,97,16,8,16,0,55,1,83,70,53,15,39,4,69,30,61,66,94,33,37,87,89,94,65,77,35,99,60,71,58,30,14,95,25,61,62,22,20,12,78,28,50,92,87,37,61,54,6,61,43,17,80,13,99,14,78,10,48,18,96,32,64,2,99,79,10,22,67,26,53,90,88,6,4,83,33,50,30,95,74,29,63,49,51,27,21,11,78,85,77,78,34,21,3,48,63,19,17,13,54,19,96,0,80,80,33,60,39,72,54,36,78,13,97,48,2,52,42,63,47,7,70,1,49,30,65,89,44,22,88,45,14,77],[48,58,55,85,99,19,4,73,8,1,9,67,3,66,61,89,67,8,45,50,7,5,17,64,72,84,70,56,85,70,45,89,38,63,89,74,87,1,60,88,49,44,36,98,35,39,45,61,34,58,51,26,3,69,57,90,75,14,42,0,49,0,37,87,53,20,49,12,73,12,14,54,48,3,94,81,94,95,4,96,61,15,94,33,83,85,19,68,43,11,51,63,99,43,96,53,53,73,19,65,0,58,44,94,81,30,40,70,23,2,51,59,84,13,97,78,35,98,42,59,42,91,46,46,34,52,49,57,42,41,56,94,85,6,73,85,68,23,21,39,36,89,94],[6,69,72,29,97,11,22,66,42,66,73,67,31,21,33,52,27,29,77,96,31,13,96,13,62,22,56,38,61,7,43,22,3,22,78,53,97,74,95,95,70,38,66,77,31,81,80,81,82,93,1,94,8,33,68,24,97,45,49,10,8,17,40,97,76,22,24,78,88,10,72,73,34,67,93,81,14,66,68,99,22,82,64,22,81,8,47,2,39,36,36,86,12,73,48,88,49,97,25,39,28,49,32,32,58,48,67,70,16,40,57,44,72,81,11,38,38,13,19,87,3,80,26,1,33,89,7,68,29,24,39,41,82,64,58,12,75,37,20,17,41,30,23],[19,67,52,93,11,67,19,14,75,78,31,74,92,63,87,41,51,84,82,35,96,34,10,47,89,57,90,23,97,57,5,95,4,11,45,99,44,3,15,19,26,43,48,54,51,53,92,95,95,7,63,37,43,48,93,8,3,70,16,69,42,27,69,51,27,73,84,77,18,44,33,2,24,2,31,47,77,13,80,51,90,69,52,20,86,52,95,2,6,32,94,38,50,29,66,49,8,53,67,71,4,76,56,19,65,56,81,57,90,94,3,63,65,35,47,65,70,62,65,91,62,3,12,30,99,53,11,4,51,29,0,8,95,77,17,86,9,64,64,55,79,87,92],[38,29,40,66,23,35,30,11,9,43,66,22,80,85,13,98,40,80,92,98,49,50,41,49,76,21,99,59,74,52,9,48,20,85,24,41,63,48,36,32,23,14,93,1,40,57,11,5,53,43,95,2,89,11,69,21,75,99,8,3,77,92,13,3,33,16,68,70,69,70,99,73,70,37,61,36,40,78,80,41,87,84,96,75,14,30,77,8,81,56,95,58,38,52,5,25,10,16,99,63,73,44,25,86,84,69,53,76,70,81,36,1,35,83,22,69,57,72,81,65,53,60,21,71,10,51,22,98,93,67,5,47,98,27,96,15,62,90,86,91,90,98,23],[35,44,41,10,16,29,32,49,99,95,36,33,22,96,82,52,81,84,79,27,19,13,82,73,68,1,9,47,15,14,47,57,45,37,64,31,85,32,67,61,3,7,94,92,19,90,92,55,63,22,19,61,94,73,70,5,44,20,12,72,23,16,83,6,0,60,61,46,11,43,93,12,65,54,95,29,83,65,86,34,20,7,7,26,12,11,58,94,29,83,88,78,68,56,96,42,64,33,72,86,14,53,13,16,60,62,0,89,5,48,63,71,88,35,46,6,9,59,67,9,85,38,82,28,33,52,91,8,0,58,90,63,54,51,95,83,6,33,79,54,50,21,16],[41,94,15,22,53,94,20,36,38,80,89,44,75,46,38,67,58,90,76,53,10,0,77,81,71,9,26,18,71,44,73,56,43,31,65,42,0,85,43,38,49,8,21,4,62,75,90,52,26,16,96,66,50,39,14,48,58,70,21,43,29,13,35,72,83,47,35,74,59,65,20,96,57,35,32,24,57,68,89,72,10,27,25,10,92,71,15,10,77,29,90,36,14,61,89,47,91,94,56,58,61,75,91,11,8,98,76,50,13,30,91,44,20,62,31,43,63,29,96,63,20,21,9,51,70,62,36,10,64,80,20,86,38,45,91,91,1,73,68,76,89,92,32],[23,77,95,58,39,11,8,69,10,31,19,63,54,48,62,35,53,38,68,83,14,54,58,88,83,43,56,28,4,10,27,59,66,97,96,62,68,89,28,61,4,34,47,50,3,60,60,27,35,73,7,49,62,11,46,16,19,35,54,80,41,27,42,81,8,12,22,63,16,29,21,96,4,17,69,40,12,39,72,16,93,85,33,31,14,58,25,33,56,90,89,41,10,76,25,90,90,38,13,58,33,65,24,36,47,12,1,12,76,16,27,61,38,30,62,83,22,97,12,15,26,82,15,41,21,94,36,21,7,15,16,45,97,83,60,11,49,50,54,10,31,56,76],[23,70,88,17,31,18,67,78,96,84,28,96,98,45,8,15,67,17,51,73,82,30,51,33,29,1,49,41,14,60,94,51,42,70,50,72,42,70,77,32,78,31,8,58,83,2,51,11,87,96,49,30,28,38,60,99,28,59,43,82,53,61,46,33,97,66,2,41,68,46,30,92,77,66,2,79,16,51,54,31,26,89,71,68,40,68,34,11,73,84,66,45,9,25,73,52,21,5,18,88,29,15,38,96,71,10,86,25,61,94,53,36,64,76,91,51,88,63,66,76,91,51,72,10,20,56,58,86,74,88,88,87,98,75,34,36,14,26,19,5,38,82,73],[76,41,36,42,82,85,61,35,43,16,82,54,16,89,90,37,3,75,30,74,32,93,59,9,82,34,7,63,50,68,31,37,77,96,5,37,6,36,13,9,10,41,42,12,16,64,47,47,9,73,92,81,69,72,7,64,0,88,92,41,83,21,1,90,3,2,4,46,39,40,71,69,59,82,49,54,82,49,54,88,18,32,86,69,64,26,36,86,37,36,74,0,15,23,76,59,12,98,13,50,17,73,39,62,54,18,63,0,98,29,81,78,93,27,6,22,41,79,4,20,5,82,28,1,11,17,8,73,66,25,27,45,20,71,68,37,57,94,79,78,27,62,3],[44,67,63,91,68,34,39,92,85,41,33,71,53,39,95,9,58,68,7,51,63,83,46,64,65,94,58,94,72,58,62,80,47,6,88,31,99,73,98,25,85,4,94,7,90,26,69,67,17,38,71,32,3,91,94,94,19,0,69,43,1,59,24,8,89,76,37,42,35,91,97,89,49,14,93,83,93,34,80,2,11,49,59,23,95,8,36,74,6,27,60,47,59,34,92,48,18,17,75,77,55,44,18,78,80,60,69,11,30,29,78,50,43,76,16,35,46,58,67,56,18,96,98,81,76,75,46,58,40,15,97,32,9,64,67,54,26,4,39,80,73,88,49],[27,26,11,13,25,75,57,27,44,60,38,68,66,58,13,98,59,14,28,69,54,7,94,63,47,60,24,58,26,29,51,20,41,14,59,40,24,99,64,20,62,3,41,78,65,83,37,77,79,21,75,84,55,18,19,26,67,94,20,43,68,8,93,47,69,74,63,65,93,43,16,22,42,35,41,64,55,84,79,65,90,79,65,29,25,27,43,81,12,82,38,54,78,61,7,90,17,55,91,38,75,89,9,81,32,69,63,13,15,29,35,28,49,48,84,78,65,80,42,34,37,71,40,3,34,23,50,65,90,4,55,37,23,30,19,50,49,41,94,66,86,38,56],[41,30,99,94,16,17,86,60,99,49,86,93,81,41,68,95,93,8,90,60,78,69,94,77,71,23,90,35,62,88,71,72,60,46,44,15,63,49,29,16,18,2,13,74,1,54,6,69,65,84,56,64,63,84,61,80,38,27,60,60,50,60,67,29,49,85,84,85,22,68,57,11,45,31,28,6,58,50,14,14,8,12,42,62,82,68,75,40,62,1,79,7,42,70,84,3,37,72,94,58,82,59,6,13,71,95,97,93,57,68,88,4,76,13,41,15,11,70,40,49,7,13,36,91,81,91,65,60,82,25,10,53,30,93,87,61,65,88,95,39,66,89,88],[89,68,36,48,85,16,66,51,7,94,4,55,85,21,39,21,6,38,86,73,71,83,19,62,65,57,65,47,77,72,76,66,81,49,23,80,75,95,43,74,21,13,76,30,27,95,33,54,95,96,57,38,94,21,61,29,35,24,54,15,17,76,79,10,22,33,76,20,9,36,45,3,36,58,78,20,91,58,78,50,84,40,60,42,16,99,18,10,28,39,7,87,6,90,22,0,98,22,25,72,8,61,46,7,8,67,67,78,45,64,1,10,92,6,33,76,48,98,94,31,0,53,96,85,77,5,82,7,38,3,36,53,27,68,99,79,81,90,13,58,67,77,18],[86,14,2,74,89,95,62,54,9,15,58,69,48,88,34,71,73,90,3,75,98,90,37,87,49,34,58,58,64,87,7,15,82,57,73,73,15,76,75,58,44,52,18,66,17,38,13,28,12,6,16,84,0,1,69,3,66,68,76,76,47,56,72,34,50,74,17,0,5,7,68,1,96,92,85,11,46,27,82,69,62,41,62,26,58,97,88,14,86,75,34,25,19,83,65,47,22,49,80,34,24,28,73,47,93,23,96,32,87,43,76,83,5,65,83,56,56,61,78,69,77,15,22,91,16,38,13,39,90,74,77,30,55,96,56,21,95,45,81,73,63,27,27],[42,18,32,81,44,15,41,86,31,43,80,18,4,60,47,57,45,37,40,72,2,63,58,39,43,58,93,70,98,50,50,13,53,29,71,18,65,66,50,13,54,47,93,36,19,36,81,73,26,53,4,49,77,70,6,7,60,61,44,10,67,37,33,36,37,14,81,76,30,94,23,2,46,15,83,51,51,10,41,68,97,4,46,77,7,47,64,59,25,62,66,25,96,79,46,48,33,73,47,34,93,66,88,39,68,37,58,19,6,13,54,59,35,36,82,70,27,99,89,92,37,75,31,36,77,40,3,78,89,98,10,80,57,10,9,41,60,51,62,85,23,22,88],[25,88,87,59,10,15,85,72,10,9,86,19,25,46,41,20,94,27,5,52,15,82,39,91,95,69,15,94,79,85,44,99,60,63,82,83,40,22,22,37,96,8,21,9,61,60,81,35,12,93,17,57,29,20,36,5,7,47,66,12,11,58,63,0,26,84,77,60,24,32,21,61,95,71,25,90,29,17,65,38,43,79,20,59,24,39,66,15,34,99,80,22,91,61,84,30,15,8,52,19,42,37,74,19,98,41,34,62,44,82,60,60,88,38,0,28,66,55,56,45,27,9,50,29,57,90,27,81,24,63,39,11,91,29,50,63,63,27,88,61,90,64,51],[9,83,65,15,49,9,0,7,92,23,0,69,64,81,69,34,66,73,52,54,82,17,76,48,34,64,96,71,71,7,93,44,94,63,13,51,30,20,54,65,59,78,37,96,73,13,1,27,79,90,80,69,62,18,46,81,74,33,73,71,67,60,58,46,26,1,97,5,59,80,25,33,59,64,19,58,30,74,48,26,10,90,38,31,0,57,35,84,21,96,30,24,94,39,84,99,5,16,14,57,39,71,9,88,78,92,39,95,8,41,57,46,3,26,15,74,56,14,67,73,15,78,86,77,56,94,61,95,48,90,0,15,11,39,26,33,14,14,56,38,99,0,72],[39,64,26,18,72,69,97,74,33,94,14,45,72,20,28,43,94,41,8,66,59,71,2,8,61,18,52,75,33,54,73,89,54,11,97,72,2,13,74,88,83,24,78,44,27,76,92,72,81,34,17,25,37,27,38,87,14,67,84,95,94,42,55,44,66,75,40,16,77,66,90,49,96,80,71,27,68,30,81,30,51,19,59,68,84,74,50,3,75,80,79,61,10,43,11,50,68,49,62,95,47,13,79,10,75,47,77,53,49,95,84,20,9,38,55,59,34,34,79,21,85,77,32,76,14,81,95,57,95,28,88,41,81,9,79,13,52,11,11,67,3,51,38],[13,34,33,28,31,94,61,79,35,27,90,52,33,20,4,80,26,67,56,94,45,51,48,45,47,36,54,62,44,62,85,32,99,67,71,28,76,75,56,51,10,38,76,87,48,33,67,15,13,45,61,88,75,53,12,89,69,70,55,13,17,94,15,13,69,7,65,32,5,34,38,0,59,93,30,64,68,89,88,19,18,64,92,37,36,34,42,99,89,63,47,1,17,39,3,97,78,26,22,67,99,67,41,5,92,0,80,68,13,63,77,24,5,93,96,73,71,48,98,72,96,66,25,66,93,1,34,36,88,61,22,39,85,63,15,70,10,52,14,75,24,25,26],[54,75,43,9,86,50,78,20,14,27,12,5,36,12,75,95,70,18,99,93,37,36,64,37,59,26,96,81,32,69,78,73,45,14,74,71,14,58,75,39,79,84,80,35,46,11,95,72,15,52,53,12,12,12,31,99,48,62,37,32,36,99,41,88,6,95,11,55,26,81,25,44,2,49,98,72,1,45,63,75,12,94,94,45,57,20,23,32,98,0,14,51,70,7,8,68,11,11,21,88,69,15,74,95,83,32,70,91,64,3,57,13,11,23,94,15,28,64,26,81,11,94,35,47,24,84,73,9,50,96,17,70,48,83,35,80,70,87,22,68,44,41,47],[82,98,49,2,15,4,69,39,7,73,22,53,95,28,46,49,51,2,40,58,38,91,50,60,30,71,0,71,8,65,34,62,93,68,35,17,39,54,26,77,67,83,34,3,23,82,39,81,78,99,89,64,71,49,51,17,91,43,89,55,65,66,82,66,32,1,41,40,74,22,96,74,60,5,8,66,79,31,56,35,45,49,88,12,61,15,55,74,25,40,40,37,41,52,98,63,97,10,59,94,48,35,7,84,81,23,15,5,0,91,88,92,29,25,62,13,60,77,21,7,29,48,95,82,60,67,46,33,73,57,61,96,29,30,54,17,29,62,90,72,17,26,53],[67,42,61,86,24,45,14,2,12,54,70,77,93,68,62,97,88,24,56,27,72,6,43,26,91,53,44,23,96,90,23,67,74,63,27,91,72,95,59,37,68,66,58,73,11,75,58,59,60,41,5,65,53,6,17,10,91,33,43,37,32,64,23,55,24,42,2,67,33,70,40,79,85,51,44,53,11,53,67,78,57,97,34,20,24,34,89,70,85,84,10,87,41,78,89,84,13,21,34,96,64,27,64,84,53,46,53,32,89,24,40,7,54,0,98,62,63,68,79,16,37,32,33,79,86,40,83,7,56,73,35,36,28,28,32,63,78,42,87,90,18,42,18],[72,5,10,78,52,58,18,58,45,2,87,36,60,63,38,34,4,94,65,29,26,2,75,68,64,78,53,80,27,97,18,89,29,76,67,68,26,92,84,31,68,98,42,7,10,45,89,73,10,12,35,29,2,45,44,95,64,98,81,23,62,2,8,24,18,68,14,6,56,37,92,38,58,56,20,67,61,43,72,38,73,16,37,97,35,74,13,82,67,6,31,4,93,86,9,52,85,53,80,98,7,70,16,22,42,67,7,10,89,62,23,66,10,79,8,23,71,40,8,33,96,42,79,35,79,53,84,25,21,88,29,50,37,62,83,20,2,53,69,90,6,53,95],[44,33,49,8,10,1,3,9,39,71,98,81,37,88,38,33,14,88,63,53,65,11,13,13,72,34,12,55,34,12,5,27,45,69,22,69,70,65,24,38,37,86,22,96,96,80,93,12,92,98,62,24,67,62,28,3,77,3,57,97,46,63,56,91,89,75,70,70,3,23,98,25,10,74,69,50,2,91,86,18,67,44,75,9,53,48,95,76,12,64,89,39,30,87,81,3,68,70,97,76,70,27,53,33,20,13,61,1,2,49,74,62,26,21,41,37,73,19,28,80,68,82,86,56,67,56,89,84,5,71,94,55,45,61,38,6,12,87,21,5,12,14,5],[8,2,54,16,68,1,29,89,24,46,1,93,9,55,34,7,61,88,5,19,55,78,9,37,53,57,59,56,40,28,31,58,5,35,27,87,29,48,64,22,26,94,32,29,2,8,57,80,14,71,61,34,51,72,15,56,41,33,82,59,8,34,46,41,88,8,87,23,98,98,90,34,81,72,83,48,47,5,93,50,99,52,74,53,65,75,27,5,58,57,56,75,22,95,20,30,57,50,91,1,45,83,1,29,78,39,3,93,95,14,46,44,85,36,53,14,3,43,37,44,64,36,11,70,2,57,77,42,88,80,50,43,35,63,15,80,78,4,72,31,96,51,33],[63,99,98,33,2,58,5,5,52,0,72,14,5,60,38,5,97,26,35,16,14,32,67,22,74,10,90,5,32,36,28,44,98,9,55,83,97,89,3,83,57,21,6,31,0,60,29,57,10,38,47,35,6,59,9,37,84,10,78,51,46,28,82,44,22,44,27,23,23,62,3,55,60,52,93,58,35,33,58,31,29,28,84,20,27,74,7,47,45,92,56,9,15,79,27,46,10,95,41,0,76,63,4,49,4,23,11,88,5,4,93,64,43,89,9,18,49,35,96,30,97,2,4,40,57,99,69,24,66,34,18,94,96,29,22,6,22,16,93,65,64,1,59],[65,39,72,39,62,40,39,88,45,13,15,17,35,93,54,11,15,47,50,10,46,27,52,93,8,17,38,46,84,71,79,66,84,81,97,81,87,72,57,15,44,12,3,36,87,43,89,41,40,24,81,32,52,60,87,85,96,9,70,91,33,65,40,76,91,94,84,20,94,52,35,25,90,23,47,12,27,79,12,8,61,10,97,61,7,73,12,70,11,71,30,8,78,63,42,76,92,13,18,16,6,30,79,35,65,85,29,58,0,17,86,70,40,68,6,57,72,4,9,25,39,94,68,72,92,66,34,90,45,23,26,25,69,28,34,88,24,38,68,62,14,49,5],[93,99,86,18,11,34,15,63,89,45,31,72,64,69,96,11,86,64,95,12,18,15,63,32,99,23,15,73,71,64,46,95,67,44,21,43,72,5,88,41,30,86,9,52,24,97,46,91,28,83,98,40,75,69,20,12,82,78,3,50,42,58,46,65,18,45,24,24,39,59,68,69,92,24,88,6,12,91,48,32,97,92,91,23,34,87,21,12,93,37,31,78,11,45,87,98,45,76,40,74,34,29,47,1,43,65,85,29,31,16,30,3,59,97,66,52,45,28,7,86,54,0,10,29,25,41,99,16,53,16,64,35,94,42,21,38,43,11,91,34,53,3,52],[4,44,56,12,56,5,84,10,47,66,39,0,72,57,81,52,45,96,36,88,5,2,24,98,84,85,72,91,55,44,45,66,35,59,59,20,37,33,96,37,22,38,74,90,49,23,45,11,62,40,38,69,72,16,63,42,91,84,86,52,6,98,14,39,67,40,21,74,25,26,44,42,93,89,49,91,10,74,23,56,35,71,1,54,22,5,88,13,22,40,27,51,38,39,77,49,13,83,2,83,31,60,87,8,18,43,56,56,11,59,52,95,39,15,76,44,13,25,42,18,26,33,46,58,32,9,6,2,1,77,37,78,8,18,70,70,30,88,67,52,99,2,38],[52,28,79,17,34,52,99,6,95,79,91,2,40,3,70,82,64,43,68,48,24,51,73,60,66,77,24,19,68,93,42,5,43,20,83,23,48,60,56,20,86,13,26,89,94,43,70,28,21,51,50,10,84,20,73,38,46,87,27,34,59,48,60,80,24,52,60,94,91,31,47,87,92,35,82,46,3,12,50,9,42,68,18,15,7,55,13,39,19,11,94,17,49,33,48,40,86,88,64,42,74,71,33,27,90,43,48,56,84,79,70,45,43,83,44,71,8,97,94,52,86,6,24,88,7,74,73,17,23,43,41,55,10,95,58,45,90,39,87,37,7,59,26],[91,76,8,32,6,79,56,52,88,69,44,64,16,76,6,84,57,33,78,93,33,42,0,29,9,97,83,31,24,91,36,89,0,37,43,27,20,37,95,58,88,5,53,97,59,36,33,4,79,50,85,82,12,75,33,40,26,95,89,40,33,85,11,88,19,50,55,71,13,5,51,73,40,82,88,36,62,72,96,39,37,64,68,47,12,56,54,4,69,24,63,70,76,28,62,55,97,54,45,54,37,92,86,52,74,63,43,18,46,11,46,95,55,68,7,77,89,49,35,68,57,51,51,26,49,29,83,17,69,31,29,7,16,25,51,89,93,6,24,68,97,74,43],[68,90,38,49,62,95,67,57,50,7,74,3,46,28,38,90,7,40,91,95,94,86,16,94,46,51,18,84,28,29,4,0,19,74,98,7,60,30,81,35,55,42,68,11,44,33,42,53,72,9,28,95,11,11,10,96,7,32,70,2,36,12,46,39,28,90,64,33,33,42,59,89,2,3,4,17,67,12,31,54,33,33,40,4,10,3,70,67,45,34,36,32,15,92,7,7,63,70,68,79,79,35,66,76,96,97,91,27,23,21,9,5,62,95,96,3,84,90,49,6,52,38,78,96,41,71,71,57,27,47,77,53,25,81,41,18,5,69,18,70,64,36,76],[48,3,96,29,40,51,77,90,34,12,42,41,47,54,87,43,78,1,41,77,6,87,49,13,25,24,70,11,94,98,81,33,77,7,55,37,23,21,94,29,25,20,82,61,29,75,47,42,7,40,79,98,55,26,77,53,61,54,9,15,63,6,44,32,75,23,41,81,71,69,62,59,46,77,49,42,85,62,46,93,8,41,94,74,8,80,78,42,32,19,46,18,36,19,97,27,78,82,62,68,61,55,69,48,37,78,20,72,0,5,70,83,59,36,49,27,56,87,20,27,0,38,4,16,58,76,41,1,67,57,69,40,81,83,88,86,14,37,70,99,23,67,66],[96,18,37,9,90,73,74,44,72,44,88,39,69,85,87,46,67,61,60,86,96,75,10,89,71,98,87,0,7,47,32,41,57,12,63,9,67,77,61,72,22,13,93,84,28,41,59,85,39,64,7,58,15,99,58,42,63,84,95,41,36,19,24,41,93,69,42,86,2,17,64,34,40,58,8,31,79,50,41,42,65,4,29,1,23,60,61,33,9,69,75,90,9,86,40,53,65,90,4,23,63,13,11,36,71,67,30,47,49,71,87,34,39,66,46,94,10,83,14,51,9,83,28,50,72,87,74,85,52,93,67,25,82,48,19,68,74,96,75,85,17,73,27],[95,52,25,52,58,78,88,69,97,12,20,85,62,91,91,16,25,30,49,84,24,91,96,22,28,29,21,22,64,52,60,60,18,5,81,33,36,1,71,22,1,53,80,63,62,67,2,81,25,88,3,2,79,82,47,74,42,25,95,64,57,59,72,1,32,72,35,18,12,60,72,57,89,16,49,34,89,41,35,49,9,73,33,2,26,14,50,38,12,97,45,88,47,76,12,65,11,21,6,18,16,51,54,27,84,58,53,57,43,35,60,8,9,10,74,88,86,25,56,54,52,22,8,72,83,64,30,33,33,34,62,26,29,46,30,26,9,18,99,73,1,26,79],[6,37,70,10,15,39,9,7,98,52,99,51,66,4,27,76,66,68,42,87,82,82,49,88,84,38,25,23,54,15,94,25,92,17,21,70,24,36,99,41,26,22,32,50,42,75,65,90,17,66,42,98,61,37,99,19,64,82,86,6,28,16,35,25,16,9,92,16,43,21,48,55,95,29,22,85,21,79,90,94,56,78,96,94,20,18,58,93,2,84,50,59,94,81,16,41,84,97,42,38,63,19,78,45,60,57,80,48,23,73,49,98,17,59,12,87,99,42,9,36,14,2,68,2,80,69,43,3,19,69,12,0,81,14,34,31,89,57,27,80,92,12,16],[43,63,83,93,46,57,20,75,5,57,83,88,68,32,80,63,64,5,5,81,89,1,37,92,36,10,79,94,48,91,69,85,5,54,60,79,1,55,29,73,68,81,95,79,23,36,60,83,44,66,57,49,44,22,13,71,77,43,30,65,77,29,80,54,12,87,44,55,2,97,93,56,28,48,46,44,81,36,82,36,99,11,54,29,36,29,57,69,74,76,74,41,93,57,88,33,84,8,22,48,9,74,91,58,11,17,39,72,90,34,17,39,76,10,74,5,46,2,34,81,19,9,63,57,50,0,65,7,0,75,94,50,88,19,35,44,27,48,8,65,84,76,54],[58,4,13,94,63,12,8,55,42,99,43,45,2,56,34,28,80,21,47,51,18,9,51,46,70,13,93,0,18,45,30,68,38,43,19,42,89,1,44,9,78,51,93,12,35,61,27,73,0,87,80,79,99,32,8,24,32,0,89,39,5,56,94,93,47,5,88,31,67,49,5,8,51,59,51,28,89,39,18,75,91,89,98,65,54,43,43,56,22,6,30,25,38,10,93,25,21,13,88,59,20,13,25,30,74,31,9,45,47,97,99,39,5,53,69,25,34,84,15,79,59,45,70,74,29,34,22,61,8,29,59,20,48,88,77,86,79,23,95,35,85,87,8],[68,70,85,49,3,96,42,6,64,37,22,80,58,63,44,7,85,11,75,94,36,88,62,52,10,86,94,66,30,84,2,39,99,30,14,51,15,19,73,69,60,94,57,84,41,24,32,73,52,92,31,27,24,91,12,92,38,87,49,0,30,35,61,93,79,20,60,54,77,3,22,4,82,52,61,26,55,95,74,88,82,5,23,68,53,74,24,54,11,94,76,15,91,94,48,45,85,26,22,14,81,49,48,62,67,17,68,42,33,64,27,91,40,64,66,92,86,60,17,38,13,19,59,30,53,70,24,80,16,90,86,47,99,76,99,0,6,22,20,12,73,31,86],[19,70,71,27,27,98,33,20,75,79,90,46,93,56,38,36,22,77,97,34,73,47,45,19,33,48,64,34,81,56,94,48,59,75,35,83,50,39,6,70,6,2,6,32,76,77,23,36,58,15,16,15,80,53,95,13,50,41,21,45,52,14,14,19,41,0,9,45,83,87,98,16,94,93,61,6,51,50,96,96,17,11,41,28,89,53,18,12,31,87,46,27,57,80,85,89,74,12,55,71,88,72,1,18,40,97,57,60,63,40,66,73,51,81,29,23,62,4,7,73,24,25,14,82,80,40,70,42,9,75,82,63,75,29,84,38,44,73,52,2,26,19,20]])) diff --git a/Week_03/id_26/LeetCode_429_26.py b/Week_03/id_26/LeetCode_429_26.py new file mode 100644 index 00000000..600f9504 --- /dev/null +++ b/Week_03/id_26/LeetCode_429_26.py @@ -0,0 +1,71 @@ +# +# @lc app=leetcode.cn id=429 lang=python +# +# [429] N叉树的层序遍历 +# +# https://leetcode-cn.com/problems/n-ary-tree-level-order-traversal/description/ +# +# algorithms +# Easy (61.76%) +# Likes: 36 +# Dislikes: 0 +# Total Accepted: 6.5K +# Total Submissions: 10.6K +# Testcase Example: '{"$id":"1","children":[{"$id":"2","children":[{"$id":"5","children":[],"val":5},{"$id":"6","children":[],"val":6}],"val":3},{"$id":"3","children":[],"val":2},{"$id":"4","children":[],"val":4}],"val":1}' +# +# 给定一个 N 叉树,返回其节点值的层序遍历。 (即从左到右,逐层遍历)。 +# +# 例如,给定一个 3叉树 : +# +# +# +# +# +# +# +# 返回其层序遍历: +# +# [ +# ⁠ [1], +# ⁠ [3,2,4], +# ⁠ [5,6] +# ] +# +# +# +# +# 说明: +# +# +# 树的深度不会超过 1000。 +# 树的节点总数不会超过 5000。 +# +# +""" +# Definition for a Node. +class Node(object): + def __init__(self, val, children): + self.val = val + self.children = children +""" + + +class Solution(object): + def levelOrder(self, root): + """ + :type root: Node + :rtype: List[List[int]] + 时间复杂度:O(N) + 空间复杂度:O(N) + """ + if not root: + return [] + layer, ans = [root], [] + while layer: + next_layer, vals = [], [] + for node in layer: + vals.append(node.val) + next_layer += node.children + layer = next_layer + ans.append(vals) + return ans diff --git a/Week_03/id_26/LeetCode_547_26.py b/Week_03/id_26/LeetCode_547_26.py new file mode 100644 index 00000000..262870bc --- /dev/null +++ b/Week_03/id_26/LeetCode_547_26.py @@ -0,0 +1,122 @@ +# +# @lc app=leetcode.cn id=547 lang=python +# +# [547] 朋友圈 +# +# https://leetcode-cn.com/problems/friend-circles/description/ +# +# algorithms +# Medium (50.43%) +# Likes: 100 +# Dislikes: 0 +# Total Accepted: 6.5K +# Total Submissions: 12.9K +# Testcase Example: '[[1,1,0],[1,1,0],[0,0,1]]' +# +# 班上有 N 名学生。其中有些人是朋友,有些则不是。他们的友谊具有是传递性。如果已知 A 是 B 的朋友,B 是 C 的朋友,那么我们可以认为 A 也是 C +# 的朋友。所谓的朋友圈,是指所有朋友的集合。 +# +# 给定一个 N * N 的矩阵 M,表示班级中学生之间的朋友关系。如果M[i][j] = 1,表示已知第 i 个和 j +# 个学生互为朋友关系,否则为不知道。你必须输出所有学生中的已知的朋友圈总数。 +# +# 示例 1: +# +# +# 输入: +# [[1,1,0], +# ⁠[1,1,0], +# ⁠[0,0,1]] +# 输出: 2 +# 说明:已知学生0和学生1互为朋友,他们在一个朋友圈。 +# 第2个学生自己在一个朋友圈。所以返回2。 +# +# +# 示例 2: +# +# +# 输入: +# [[1,1,0], +# ⁠[1,1,1], +# ⁠[0,1,1]] +# 输出: 1 +# 说明:已知学生0和学生1互为朋友,学生1和学生2互为朋友,所以学生0和学生2也是朋友,所以他们三个在一个朋友圈,返回1。 +# +# +# 注意: +# +# +# N 在[1,200]的范围内。 +# 对于所有学生,有M[i][i] = 1。 +# 如果有M[i][j] = 1,则有M[j][i] = 1。 +# +# +# + + +class Solution(object): + + def findCircleNum(self, M): + """ + :type M: List[List[int]] + :rtype: int + 解法1:dfs + 深度遍历,用集合存储已经访问过的节点,如果访问过则跳过,否则朋友圈+1 + """ + visited, ans = set(), 0 + + def dfs(i): + for j in range(len(M[i])): + if M[i][j] and j not in visited: + visited.add(j) + dfs(j) + + for i in range(len(M)): + if i not in visited: + dfs(i) + ans += 1 + return ans + + def findCircleNum2(self, M): + """ + :type M: List[List[int]] + :rtype: int + 解法2:并查集 + 首先每个人都是自己的朋友圈,所以先建立一个对应关系指向自己 + 如果i和j是朋友,则i的朋友圈合并j的朋友圈,即j所在圈的根节点指向i所在圈的根节点 + 最后数一下指向自己的节点有几个,即根节点的数量,即朋友圈的数量 + """ + n = len(M) + circles = {i: i for i in range(n)} + + def find(i): + if i == circles[i]: + return i + circles[i] = find(circles[i]) + return circles[i] + + for i in range(n): + for j in range(i + 1, n): + if M[i][j] == 1: + circles[find(i)] = find(j) + + return sum([1 for k, v in circles.items() if k == v]) + + +print(Solution().findCircleNum2([[1, 0, 0], [0, 1, 0], [0, 0, 1]])) +print(Solution().findCircleNum2([[1, 1, 0], [1, 1, 0], [0, 0, 1]])) +print(Solution().findCircleNum2([[1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], + [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0], + [0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0], + [0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0], + [1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0], + [0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1], + [0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]] + )) diff --git a/Week_03/id_26/LeetCode_703_26.py b/Week_03/id_26/LeetCode_703_26.py new file mode 100644 index 00000000..d5f93fdb --- /dev/null +++ b/Week_03/id_26/LeetCode_703_26.py @@ -0,0 +1,66 @@ +# +# @lc app=leetcode.cn id=703 lang=python +# +# [703] 数据流中的第K大元素 +# +# https://leetcode-cn.com/problems/kth-largest-element-in-a-stream/description/ +# +# algorithms +# Easy (38.59%) +# Likes: 56 +# Dislikes: 0 +# Total Accepted: 5.1K +# Total Submissions: 13.1K +# Testcase Example: '["KthLargest","add","add","add","add","add"]\n[[3,[4,5,8,2]],[3],[5],[10],[9],[4]]' +# +# 设计一个找到数据流中第K大元素的类(class)。注意是排序后的第K大元素,不是第K个不同的元素。 +# +# 你的 KthLargest 类需要一个同时接收整数 k 和整数数组nums 的构造器,它包含数据流中的初始元素。每次调用 +# KthLargest.add,返回当前数据流中第K大的元素。 +# +# 示例: +# +# +# int k = 3; +# int[] arr = [4,5,8,2]; +# KthLargest kthLargest = new KthLargest(3, arr); +# kthLargest.add(3);   // returns 4 +# kthLargest.add(5);   // returns 5 +# kthLargest.add(10);  // returns 5 +# kthLargest.add(9);   // returns 8 +# kthLargest.add(4);   // returns 8 +# +# +# 说明: +# 你可以假设 nums 的长度≥ k-1 且k ≥ 1。 +# +# + +import heapq + + +class KthLargest(object): + def __init__(self, k, nums): + """ + :type k: int + :type nums: List[int] + """ + self.heap = [] + self.k = k + map(self.add, nums) + + def add(self, val): + """ + :type val: int + :rtype: int + """ + if len(self.heap) < self.k: + heapq.heappush(self.heap, val) + elif val > self.heap[0]: + heapq.heapreplace(self.heap, val) + return self.heap[0] + + +# Your KthLargest object will be instantiated and called as such: +# obj = KthLargest(k, nums) +# param_1 = obj.add(val) diff --git a/Week_03/id_26/LeetCode_802_26.py b/Week_03/id_26/LeetCode_802_26.py new file mode 100644 index 00000000..a686876c --- /dev/null +++ b/Week_03/id_26/LeetCode_802_26.py @@ -0,0 +1,107 @@ +# +# @lc app=leetcode.cn id=802 lang=python +# +# [802] 找到最终的安全状态 +# +# https://leetcode-cn.com/problems/find-eventual-safe-states/description/ +# +# algorithms +# Medium (37.58%) +# Likes: 14 +# Dislikes: 0 +# Total Accepted: 543 +# Total Submissions: 1.5K +# Testcase Example: '[[1,2],[2,3],[5],[0],[5],[],[]]' +# +# 在有向图中, 我们从某个节点和每个转向处开始, 沿着图的有向边走。 如果我们到达的节点是终点 (即它没有连出的有向边), 我们停止。 +# +# 现在, 如果我们最后能走到终点,那么我们的起始节点是最终安全的。 更具体地说, 存在一个自然数 K,  无论选择从哪里开始行走, 我们走了不到 K +# 步后必能停止在一个终点。 +# +# 哪些节点最终是安全的? 结果返回一个有序的数组。 +# +# 该有向图有 N 个节点,标签为 0, 1, ..., N-1, 其中 N 是 graph 的节点数.  图以以下的形式给出: graph[i] 是节点 j +# 的一个列表,满足 (i, j) 是图的一条有向边。 +# +# +# 示例: +# 输入:graph = [[1,2],[2,3],[5],[0],[5],[],[]] +# 输出:[2,4,5,6] +# 这里是上图的示意图。 +# +# +# +# +# +# 提示: +# +# +# graph 节点数不超过 10000. +# 图的边数不会超过 32000. +# 每个 graph[i] 被排序为不同的整数列表, 在区间 [0, graph.length - 1] 中选取。 +# +# +# + +import collections + + +class Solution(object): + def eventualSafeNodes1(self, graph): + """ + :type graph: List[List[int]] + :rtype: List[int] + This is equal to find nodes which doesn't lead to a circle in any path. + We can solve it by walking along the path reversely. + + Find nodes with out degree 0, they are terminal nodes, + we remove them from graph and they are added to result + For nodes who are connected terminal nodes, + since terminal nodes are removed, + we decrease in-nodes' out degree by 1 and if its out degree equals to 0, + it become new terminal nodes + Repeat 2 until no terminal nodes can be found. + """ + n = len(graph) + out_degree = collections.defaultdict(int) + in_nodes = collections.defaultdict(list) + + queue = [] + ret = [] + for i in range(n): + out_degree[i] = len(graph[i]) + if out_degree[i] == 0: + queue.append(i) + for j in graph[i]: + in_nodes[j].append(i) + + while queue: + term_node = queue.pop(0) + ret.append(term_node) + for in_node in in_nodes[term_node]: + out_degree[in_node] -= 1 + if out_degree[in_node] == 0: + queue.append(in_node) + return sorted(ret) + + def eventualSafeNodes(self, graph): + n = len(graph) + out_degree, in_nodes = [],[[] for i in range(n)] + queue, ans= [], set() + + for i in range(len(graph)): + out_degree.append(len(graph[i])) + if not graph[i]: + queue.append(i) + for j in graph[i]: + in_nodes[j].append(i) + + while queue: + i = queue.pop() + ans.add(i) + for j in in_nodes[i]: + out_degree[j] -= 1 + if out_degree[j] == 0: + queue.append(j) + return sorted(ans) + diff --git a/Week_03/id_28/src/LeetCode_200_28.java b/Week_03/id_28/src/LeetCode_200_28.java new file mode 100644 index 00000000..ade15512 --- /dev/null +++ b/Week_03/id_28/src/LeetCode_200_28.java @@ -0,0 +1,46 @@ +package NumberOfIslands200; + +public class Solution { + int count=0; + public int numIslands(char[][] grid) { + for (int i=0;i=grid.length||i<0||j>=grid[0].length||j<0||grid[i][j]=='0'){ + return false; + } + + grid[i][j]='0'; + boolean down=dfs(i+1,j,grid); + boolean right=dfs(i,j+1,grid); + boolean left=dfs(i,j-1,grid); + boolean up=dfs(i-1,j,grid); + return left&&right&&down&&up; + + } + + public static void main(String[] args) { + //char[][] grid={{'1','1','0','0','0'}, {'1','1','0','0','0'},{'0','0','1','0','0'},{'0','0','0','1','1'}}; + //char[][] grid={{'1'},{'1'}}; + //char[][] grid={{'1','1','1'},{'0','1','0'},{'1','1','1'}}; + char[][] grid={{'1','0','1','1','1'},{'1','0','1','0','1'},{'1','1','1','0','1'}}; + /* + new LeetCode_174_28().dfs(0,0,grid); + for (int i=0;i> levelOrder(Node root) { + LinkedList queue=new LinkedList(); + queue.add(root); + queue.add(null); + List> ret=new LinkedList>(); + List list=new LinkedList(); + while (queue.size()>0){ + Node e=queue.pop(); + + if(e!=null){ + list.add(e.val); + if(e.children!=null&&e.children.size()>0){ + for (Node chi:e.children){ + if(chi!=null){ + queue.addAll(e.children); + } + } + + } + + }else { + + ret.add(list); + list=new LinkedList(); + + } + } + return ret; + + } + + public static void main(String[] args) { + + } + +} diff --git a/Week_03/id_28/src/Node.java b/Week_03/id_28/src/Node.java new file mode 100644 index 00000000..e7545ebe --- /dev/null +++ b/Week_03/id_28/src/Node.java @@ -0,0 +1,15 @@ +package levelTravel429; + +import java.util.List; + +public class Node { + public int val; + public List children; + + public Node() {} + + public Node(int _val,List _children) { + val = _val; + children = _children; + } +} diff --git a/Week_03/id_29/Leetcode_104_29.go b/Week_03/id_29/Leetcode_104_29.go new file mode 100644 index 00000000..dfa20501 --- /dev/null +++ b/Week_03/id_29/Leetcode_104_29.go @@ -0,0 +1,14 @@ +package main + +func maxDepth(root *TreeNode) int { + if root == nil { + return 0 + } + leftDepth := maxDepth(root.Left) + rightDepth := maxDepth(root.Right) + if leftDepth > rightDepth { + return leftDepth + 1 + } else { + return rightDepth + 1 + } +} diff --git a/Week_03/id_29/Leetcode_111_29.go b/Week_03/id_29/Leetcode_111_29.go new file mode 100644 index 00000000..dc623734 --- /dev/null +++ b/Week_03/id_29/Leetcode_111_29.go @@ -0,0 +1,29 @@ +package main + +func minDepth(root *TreeNode) int { + if root == nil { + return 0 + } + left := minDepth(root.Left) + right := minDepth(root.Right) + if left == 0 || right == 0 { + return 1 + max(left, right) + } + return 1 + min(left, right) +} + +func min(x, y int) int { + if x >= y { + return y + } else { + return x + } +} + +func max(x, y int) int { + if x <= y { + return y + } else { + return x + } +} diff --git a/Week_03/id_29/Leetcode_200_29.go b/Week_03/id_29/Leetcode_200_29.go new file mode 100644 index 00000000..2505bea3 --- /dev/null +++ b/Week_03/id_29/Leetcode_200_29.go @@ -0,0 +1,46 @@ +package main + +func numIslands(grid [][]byte) int { + color := 1 + colors := make([][]int, len(grid)) + for x := range colors { + colors[x] = make([]int, len(grid[x])) + } + + for x := range grid { + for y := range grid[x] { + marked := markColor(x, y, grid, colors, color) + if marked { + color++ + } + } + } + + return color - 1 +} + +func markColor(x, y int, grid [][]byte, colors [][]int, color int) bool { + if x < 0 || x >= len(grid) { + return false + } + + if y < 0 || y >= len(grid[x]) { + return false + } + + if colors[x][y] != 0 { + return false + } + + if grid[x][y] == '0' { + colors[x][y] = -1 + return false + } + + colors[x][y] = color + markColor(x+1, y, grid, colors, color) + markColor(x-1, y, grid, colors, color) + markColor(x, y-1, grid, colors, color) + markColor(x, y+1, grid, colors, color) + return true +} diff --git a/Week_03/id_29/Leetcode_210_29.go b/Week_03/id_29/Leetcode_210_29.go new file mode 100644 index 00000000..cfd33c36 --- /dev/null +++ b/Week_03/id_29/Leetcode_210_29.go @@ -0,0 +1,37 @@ +package main + +func findOrder(numCourses int, prerequisites [][]int) []int { + + queue := make([]int, 0, numCourses) + inDegree := make([]int, numCourses, numCourses) + graph := make(map[int][]int) + + for _, edge := range prerequisites { + from, to := edge[1], edge[0] + inDegree[to]++ + graph[from] = append(graph[from], to) + } + + for i, n := range inDegree { + if n == 0 { + queue = append(queue, i) + } + } + + for i := 0; i < numCourses; i++ { + if i >= len(queue) { + return []int{} + } + course := queue[i] + nextCourses := graph[course] + + for _, next := range nextCourses { + inDegree[next]-- + if inDegree[next] == 0 { + queue = append(queue, next) + } + } + } + + return queue +} diff --git a/Week_03/id_29/Leetcode_703_29.go b/Week_03/id_29/Leetcode_703_29.go new file mode 100644 index 00000000..f19bab33 --- /dev/null +++ b/Week_03/id_29/Leetcode_703_29.go @@ -0,0 +1,57 @@ +package main + +import "container/heap" + +type IntHeap []int + +type KthLargest struct { + k int + heap intHeap +} + +func Constructor(k int, nums []int) KthLargest { + h := intHeap(nums) + heap.Init(&h) + + for len(h) > k { + heap.Pop(&h) + } + + return KthLargest{ + k: k, + heap: h, + } +} + +func (kl *KthLargest) Add(val int) int { + heap.Push(&kl.heap, val) + + if len(kl.heap) > kl.k { + heap.Pop(&kl.heap) + } + + return kl.heap[0] +} + +type intHeap []int + +func (h intHeap) Len() int { + return len(h) +} + +func (h intHeap) Less(i, j int) bool { + return h[i] < h[j] +} + +func (h intHeap) Swap(i, j int) { + h[i], h[j] = h[j], h[i] +} +func (h *intHeap) Push(x interface{}) { + *h = append(*h, x.(int)) +} + +func (h *intHeap) Pop() interface{} { + res := (*h)[len(*h)-1] + *h = (*h)[:len(*h)-1] + return res +} diff --git a/Week_03/id_29/main.go b/Week_03/id_29/main.go new file mode 100644 index 00000000..216deaa0 --- /dev/null +++ b/Week_03/id_29/main.go @@ -0,0 +1,11 @@ +package main + +func main() { + +} + +type TreeNode struct { + Val int + Left *TreeNode + Right *TreeNode +} diff --git a/Week_03/id_3/bfs/LeetCode_103_3.py b/Week_03/id_3/bfs/LeetCode_103_3.py new file mode 100644 index 00000000..085e7eab --- /dev/null +++ b/Week_03/id_3/bfs/LeetCode_103_3.py @@ -0,0 +1,40 @@ +""" +Week2做过 这里整理一下思路 +最简单的方式是BFS加上结果部分倒序 +复杂的方式则是在BFS的时候就进行倒序,减少一次倒序操作 +BFS由于有倒序层,而在倒序迭代倒序层的同时又要保证下一层顺序遍历。 +所以倒序层需要使用队列由后向前插入数据,并且先右后左 +例如 [1,2,3]倒序遍历,3的子节点[e,f]先f后e的插入队列前端 +这次使用collections的队列 +""" +import collections + + +class Solution: + def zigzagLevelOrder(self, root): + if not root: + return [] + results = [] + queue = collections.deque([root]) + while queue: + need_reverse = len(results) % 2 == 1 + result = [] + if need_reverse: + for _ in range(len(queue)): + node = queue.pop() + if not node: + continue + result.append(node.val) + node.right and queue.appendleft(node.right) + node.left and queue.appendleft(node.left) + else: + for _ in range(len(queue)): + node = queue.popleft() + if not node: + continue + result.append(node.val) + node.left and queue.append(node.left) + node.right and queue.append(node.right) + results.append(result) + + return results diff --git a/Week_03/id_3/bfs/LeetCode_310_3.py b/Week_03/id_3/bfs/LeetCode_310_3.py new file mode 100644 index 00000000..ab3665a2 --- /dev/null +++ b/Week_03/id_3/bfs/LeetCode_310_3.py @@ -0,0 +1,233 @@ +""" +思路大概就是BFS找出最小值 如果大于已有最小值则剪枝 +=========== 超时了 这个n^2的方案注定要优化 +这是一个失败的版本 v2是优化后的版本 +""" +import collections + + +class Solution: + def findMinHeightTrees(self, n, edges): + graph = {} + for i in range(n): + graph[i] = [] + for n1, n2 in edges: + graph[n1].append(n2) + graph[n2].append(n1) + + min_level = n + result = [] + queue = collections.deque() + if True: + print(self.bfs(3, graph, min_level, queue)) + return + for i in range(n): + count = self.bfs(i, graph, min_level, queue) + if count == min_level: + result.append(i) + elif count < min_level: + min_level = count + result = [i] + return result + + def bfs(self, i, graph, min_level, queue): + queue.appendleft(i) + visited = set() + count = 0 + while queue: + if count > min_level: + return count + print(queue) + for _ in range(len(queue)): + n = queue.pop() + visited.add(n) + for sn in graph[n]: + if sn in visited: + continue + queue.appendleft(sn) + count += 1 + return count + + +s = Solution() +# print(s.findMinHeightTrees(4, [[1, 0], [1, 2], [1, 3]])) +# print(s.findMinHeightTrees(6, [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]])) +print(s.findMinHeightTrees(1313, [[0, 1], [0, 2], [0, 3], [3, 4], [0, 5], [3, 6], [3, 7], [6, 8], [3, 9], [9, 10], [9, 11], + [10, 12], [3, 13], [2, 14], [5, 15], [1, 16], [5, 17], [15, 18], [17, 19], [12, 20], + [20, 21], [21, 22], [2, 23], [12, 24], [13, 25], [23, 26], [6, 27], [14, 28], [7, 29], + [14, 30], [28, 31], [3, 32], [20, 33], [6, 34], [28, 35], [14, 36], [12, 37], [25, 38], + [28, 39], [0, 40], [11, 41], [19, 42], [41, 43], [24, 44], [43, 45], [14, 46], [36, 47], + [26, 48], [16, 49], [42, 50], [43, 51], [11, 52], [7, 53], [50, 54], [17, 55], [9, 56], + [0, 57], [16, 58], [26, 59], [32, 60], [53, 61], [30, 62], [40, 63], [63, 64], [45, 65], + [13, 66], [24, 67], [42, 68], [2, 69], [63, 70], [39, 71], [34, 72], [20, 73], [20, 74], + [63, 75], [12, 76], [57, 77], [51, 78], [17, 79], [24, 80], [22, 81], [76, 82], [4, 83], + [16, 84], [75, 85], [21, 86], [21, 87], [8, 88], [28, 89], [85, 90], [31, 91], [53, 92], + [57, 93], [45, 94], [67, 95], [87, 96], [10, 97], [95, 98], [0, 99], [46, 100], [39, 101], + [47, 102], [101, 103], [72, 104], [2, 105], [3, 106], [78, 107], [32, 108], [23, 109], + [73, 110], [102, 111], [50, 112], [8, 113], [85, 114], [68, 115], [87, 116], [102, 117], + [77, 118], [62, 119], [70, 120], [86, 121], [13, 122], [101, 123], [69, 124], [37, 125], + [48, 126], [78, 127], [40, 128], [26, 129], [7, 130], [80, 131], [21, 132], [81, 133], + [62, 134], [97, 135], [71, 136], [123, 137], [78, 138], [16, 139], [5, 140], [10, 141], + [138, 142], [21, 143], [15, 144], [91, 145], [0, 146], [65, 147], [64, 148], [28, 149], + [86, 150], [28, 151], [111, 152], [140, 153], [138, 154], [77, 155], [145, 156], [50, 157], + [87, 158], [96, 159], [105, 160], [59, 161], [1, 162], [11, 163], [121, 164], [48, 165], + [119, 166], [133, 167], [26, 168], [92, 169], [63, 170], [158, 171], [164, 172], [115, 173], + [66, 174], [123, 175], [33, 176], [76, 177], [119, 178], [114, 179], [124, 180], [164, 181], + [85, 182], [143, 183], [110, 184], [53, 185], [120, 186], [78, 187], [131, 188], [185, 189], + [69, 190], [168, 191], [51, 192], [89, 193], [159, 194], [176, 195], [13, 196], [51, 197], + [6, 198], [28, 199], [46, 200], [105, 201], [167, 202], [148, 203], [19, 204], [204, 205], + [6, 206], [151, 207], [44, 208], [54, 209], [184, 210], [176, 211], [173, 212], [200, 213], + [203, 214], [106, 215], [87, 216], [1, 217], [173, 218], [103, 219], [160, 220], [118, 221], + [50, 222], [152, 223], [25, 224], [9, 225], [64, 226], [6, 227], [61, 228], [144, 229], + [212, 230], [166, 231], [30, 232], [196, 233], [215, 234], [109, 235], [183, 236], + [13, 237], [183, 238], [18, 239], [149, 240], [189, 241], [149, 242], [157, 243], + [116, 244], [99, 245], [30, 246], [56, 247], [239, 248], [239, 249], [57, 250], [31, 251], + [189, 252], [101, 253], [101, 254], [110, 255], [1, 256], [113, 257], [161, 258], [25, 259], + [44, 260], [194, 261], [137, 262], [218, 263], [183, 264], [228, 265], [153, 266], + [136, 267], [201, 268], [265, 269], [116, 270], [236, 271], [32, 272], [70, 273], + [104, 274], [82, 275], [198, 276], [44, 277], [262, 278], [269, 279], [26, 280], [91, 281], + [180, 282], [157, 283], [36, 284], [215, 285], [183, 286], [1, 287], [39, 288], [164, 289], + [110, 290], [266, 291], [208, 292], [258, 293], [68, 294], [1, 295], [100, 296], [16, 297], + [107, 298], [135, 299], [55, 300], [226, 301], [155, 302], [68, 303], [32, 304], [149, 305], + [217, 306], [186, 307], [69, 308], [244, 309], [14, 310], [216, 311], [211, 312], + [232, 313], [148, 314], [85, 315], [91, 316], [168, 317], [90, 318], [228, 319], [216, 320], + [51, 321], [31, 322], [230, 323], [160, 324], [200, 325], [94, 326], [282, 327], [162, 328], + [130, 329], [87, 330], [29, 331], [295, 332], [32, 333], [136, 334], [219, 335], [218, 336], + [25, 337], [233, 338], [55, 339], [130, 340], [319, 341], [165, 342], [255, 343], [15, 344], + [342, 345], [74, 346], [172, 347], [28, 348], [255, 349], [47, 350], [193, 351], [19, 352], + [303, 353], [205, 354], [174, 355], [172, 356], [260, 357], [243, 358], [186, 359], + [181, 360], [51, 361], [34, 362], [31, 363], [283, 364], [283, 365], [122, 366], [137, 367], + [225, 368], [296, 369], [346, 370], [235, 371], [278, 372], [116, 373], [31, 374], + [248, 375], [89, 376], [20, 377], [287, 378], [222, 379], [33, 380], [3, 381], [140, 382], + [185, 383], [255, 384], [241, 385], [164, 386], [185, 387], [208, 388], [347, 389], + [235, 390], [157, 391], [88, 392], [138, 393], [163, 394], [69, 395], [241, 396], + [307, 397], [271, 398], [248, 399], [346, 400], [265, 401], [90, 402], [249, 403], + [43, 404], [10, 405], [159, 406], [383, 407], [174, 408], [292, 409], [288, 410], + [149, 411], [244, 412], [174, 413], [201, 414], [287, 415], [94, 416], [102, 417], + [123, 418], [10, 419], [332, 420], [192, 421], [377, 422], [136, 423], [119, 424], + [187, 425], [128, 426], [413, 427], [3, 428], [255, 429], [410, 430], [303, 431], + [424, 432], [311, 433], [246, 434], [366, 435], [378, 436], [360, 437], [120, 438], + [90, 439], [353, 440], [126, 441], [78, 442], [23, 443], [115, 444], [6, 445], [359, 446], + [338, 447], [180, 448], [71, 449], [190, 450], [128, 451], [408, 452], [341, 453], + [426, 454], [14, 455], [455, 456], [411, 457], [107, 458], [450, 459], [351, 460], + [235, 461], [422, 462], [316, 463], [272, 464], [204, 465], [102, 466], [145, 467], + [20, 468], [326, 469], [186, 470], [266, 471], [127, 472], [144, 473], [112, 474], + [151, 475], [200, 476], [185, 477], [291, 478], [438, 479], [422, 480], [377, 481], + [261, 482], [437, 483], [204, 484], [324, 485], [402, 486], [106, 487], [268, 488], + [237, 489], [49, 490], [253, 491], [256, 492], [8, 493], [115, 494], [46, 495], [101, 496], + [325, 497], [90, 498], [146, 499], [252, 500], [255, 501], [277, 502], [129, 503], + [339, 504], [6, 505], [462, 506], [363, 507], [421, 508], [7, 509], [279, 510], [361, 511], + [35, 512], [112, 513], [113, 514], [194, 515], [128, 516], [65, 517], [26, 518], [305, 519], + [97, 520], [352, 521], [283, 522], [4, 523], [497, 524], [385, 525], [212, 526], [76, 527], + [92, 528], [194, 529], [344, 530], [510, 531], [461, 532], [89, 533], [228, 534], [97, 535], + [194, 536], [446, 537], [100, 538], [120, 539], [257, 540], [46, 541], [230, 542], + [357, 543], [365, 544], [265, 545], [123, 546], [290, 547], [100, 548], [194, 549], + [134, 550], [538, 551], [114, 552], [52, 553], [251, 554], [236, 555], [416, 556], + [264, 557], [461, 558], [14, 559], [376, 560], [254, 561], [422, 562], [233, 563], + [409, 564], [14, 565], [190, 566], [151, 567], [543, 568], [516, 569], [369, 570], + [432, 571], [343, 572], [341, 573], [531, 574], [77, 575], [394, 576], [471, 577], + [293, 578], [428, 579], [360, 580], [524, 581], [471, 582], [63, 583], [556, 584], + [254, 585], [583, 586], [491, 587], [460, 588], [250, 589], [329, 590], [504, 591], + [414, 592], [353, 593], [172, 594], [582, 595], [474, 596], [19, 597], [327, 598], + [464, 599], [39, 600], [278, 601], [234, 602], [131, 603], [569, 604], [466, 605], + [354, 606], [160, 607], [466, 608], [283, 609], [39, 610], [321, 611], [440, 612], + [280, 613], [142, 614], [9, 615], [411, 616], [519, 617], [317, 618], [278, 619], + [412, 620], [352, 621], [96, 622], [540, 623], [1, 624], [370, 625], [274, 626], [277, 627], + [30, 628], [79, 629], [134, 630], [435, 631], [21, 632], [437, 633], [285, 634], [461, 635], + [122, 636], [137, 637], [550, 638], [399, 639], [490, 640], [405, 641], [358, 642], + [205, 643], [352, 644], [544, 645], [319, 646], [412, 647], [554, 648], [561, 649], + [100, 650], [361, 651], [130, 652], [151, 653], [547, 654], [543, 655], [230, 656], + [34, 657], [240, 658], [533, 659], [220, 660], [551, 661], [635, 662], [298, 663], + [510, 664], [32, 665], [56, 666], [271, 667], [386, 668], [328, 669], [511, 670], + [648, 671], [213, 672], [640, 673], [620, 674], [292, 675], [612, 676], [231, 677], + [519, 678], [218, 679], [158, 680], [284, 681], [149, 682], [180, 683], [465, 684], + [101, 685], [97, 686], [592, 687], [577, 688], [501, 689], [130, 690], [574, 691], + [483, 692], [617, 693], [461, 694], [308, 695], [614, 696], [90, 697], [362, 698], + [313, 699], [301, 700], [562, 701], [41, 702], [627, 703], [408, 704], [476, 705], + [161, 706], [282, 707], [481, 708], [209, 709], [576, 710], [437, 711], [10, 712], + [548, 713], [256, 714], [498, 715], [129, 716], [664, 717], [70, 718], [185, 719], + [629, 720], [108, 721], [360, 722], [503, 723], [105, 724], [213, 725], [177, 726], + [46, 727], [104, 728], [398, 729], [209, 730], [89, 731], [499, 732], [368, 733], + [680, 734], [362, 735], [534, 736], [443, 737], [562, 738], [74, 739], [353, 740], + [165, 741], [108, 742], [438, 743], [131, 744], [140, 745], [37, 746], [28, 747], + [698, 748], [523, 749], [113, 750], [430, 751], [695, 752], [670, 753], [546, 754], + [366, 755], [369, 756], [602, 757], [415, 758], [291, 759], [352, 760], [560, 761], + [569, 762], [681, 763], [55, 764], [381, 765], [324, 766], [740, 767], [308, 768], + [728, 769], [374, 770], [118, 771], [97, 772], [646, 773], [6, 774], [626, 775], [444, 776], + [252, 777], [391, 778], [503, 779], [760, 780], [451, 781], [728, 782], [553, 783], + [410, 784], [487, 785], [343, 786], [350, 787], [579, 788], [3, 789], [706, 790], + [213, 791], [212, 792], [792, 793], [99, 794], [534, 795], [63, 796], [167, 797], + [109, 798], [692, 799], [597, 800], [742, 801], [407, 802], [256, 803], [442, 804], + [587, 805], [313, 806], [652, 807], [602, 808], [665, 809], [330, 810], [508, 811], + [683, 812], [598, 813], [661, 814], [709, 815], [594, 816], [337, 817], [219, 818], + [113, 819], [306, 820], [651, 821], [352, 822], [742, 823], [37, 824], [464, 825], + [452, 826], [165, 827], [774, 828], [17, 829], [280, 830], [511, 831], [542, 832], + [439, 833], [581, 834], [687, 835], [758, 836], [618, 837], [378, 838], [697, 839], + [769, 840], [702, 841], [606, 842], [105, 843], [663, 844], [157, 845], [441, 846], + [348, 847], [676, 848], [775, 849], [446, 850], [722, 851], [572, 852], [191, 853], + [765, 854], [710, 855], [569, 856], [134, 857], [596, 858], [304, 859], [20, 860], + [812, 861], [606, 862], [689, 863], [402, 864], [275, 865], [367, 866], [638, 867], + [618, 868], [231, 869], [367, 870], [255, 871], [740, 872], [232, 873], [571, 874], + [668, 875], [72, 876], [483, 877], [599, 878], [631, 879], [420, 880], [352, 881], + [289, 882], [720, 883], [556, 884], [430, 885], [410, 886], [728, 887], [412, 888], + [682, 889], [839, 890], [59, 891], [233, 892], [272, 893], [688, 894], [431, 895], + [310, 896], [407, 897], [567, 898], [743, 899], [811, 900], [808, 901], [246, 902], + [236, 903], [895, 904], [657, 905], [393, 906], [143, 907], [442, 908], [898, 909], + [72, 910], [282, 911], [901, 912], [624, 913], [697, 914], [484, 915], [582, 916], [4, 917], + [186, 918], [426, 919], [753, 920], [513, 921], [504, 922], [821, 923], [549, 924], + [415, 925], [634, 926], [505, 927], [590, 928], [866, 929], [267, 930], [236, 931], + [343, 932], [693, 933], [116, 934], [543, 935], [463, 936], [880, 937], [126, 938], + [832, 939], [205, 940], [33, 941], [284, 942], [941, 943], [940, 944], [943, 945], + [784, 946], [785, 947], [498, 948], [898, 949], [715, 950], [238, 951], [389, 952], + [951, 953], [511, 954], [767, 955], [332, 956], [300, 957], [298, 958], [317, 959], + [221, 960], [253, 961], [438, 962], [751, 963], [492, 964], [384, 965], [274, 966], + [820, 967], [376, 968], [159, 969], [766, 970], [909, 971], [669, 972], [8, 973], + [957, 974], [539, 975], [844, 976], [470, 977], [80, 978], [641, 979], [172, 980], + [962, 981], [756, 982], [195, 983], [131, 984], [216, 985], [503, 986], [330, 987], + [863, 988], [446, 989], [673, 990], [760, 991], [871, 992], [903, 993], [47, 994], + [810, 995], [736, 996], [749, 997], [951, 998], [348, 999], [741, 1000], [448, 1001], + [809, 1002], [704, 1003], [702, 1004], [113, 1005], [392, 1006], [216, 1007], [58, 1008], + [348, 1009], [170, 1010], [695, 1011], [168, 1012], [752, 1013], [168, 1014], [376, 1015], + [856, 1016], [302, 1017], [278, 1018], [554, 1019], [844, 1020], [368, 1021], [555, 1022], + [283, 1023], [220, 1024], [907, 1025], [356, 1026], [415, 1027], [977, 1028], [433, 1029], + [741, 1030], [702, 1031], [202, 1032], [420, 1033], [773, 1034], [929, 1035], [1020, 1036], + [752, 1037], [846, 1038], [909, 1039], [137, 1040], [752, 1041], [728, 1042], [295, 1043], + [998, 1044], [52, 1045], [825, 1046], [727, 1047], [871, 1048], [941, 1049], [342, 1050], + [579, 1051], [424, 1052], [756, 1053], [50, 1054], [587, 1055], [447, 1056], [1042, 1057], + [171, 1058], [322, 1059], [1049, 1060], [189, 1061], [384, 1062], [403, 1063], [468, 1064], + [666, 1065], [282, 1066], [271, 1067], [407, 1068], [323, 1069], [52, 1070], [571, 1071], + [46, 1072], [412, 1073], [616, 1074], [417, 1075], [1042, 1076], [657, 1077], [940, 1078], + [498, 1079], [597, 1080], [95, 1081], [12, 1082], [541, 1083], [519, 1084], [463, 1085], + [848, 1086], [1000, 1087], [788, 1088], [337, 1089], [1001, 1090], [267, 1091], [378, 1092], + [234, 1093], [907, 1094], [826, 1095], [31, 1096], [188, 1097], [502, 1098], [826, 1099], + [948, 1100], [879, 1101], [388, 1102], [34, 1103], [461, 1104], [568, 1105], [79, 1106], + [319, 1107], [364, 1108], [190, 1109], [605, 1110], [717, 1111], [622, 1112], [385, 1113], + [25, 1114], [835, 1115], [1033, 1116], [1085, 1117], [240, 1118], [199, 1119], [693, 1120], + [68, 1121], [478, 1122], [95, 1123], [842, 1124], [1109, 1125], [678, 1126], [104, 1127], + [918, 1128], [414, 1129], [768, 1130], [421, 1131], [825, 1132], [636, 1133], [290, 1134], + [1083, 1135], [473, 1136], [616, 1137], [1094, 1138], [28, 1139], [137, 1140], [590, 1141], + [654, 1142], [1140, 1143], [789, 1144], [670, 1145], [475, 1146], [176, 1147], [27, 1148], + [1106, 1149], [430, 1150], [192, 1151], [869, 1152], [546, 1153], [955, 1154], [493, 1155], + [643, 1156], [663, 1157], [702, 1158], [823, 1159], [1022, 1160], [228, 1161], [578, 1162], + [655, 1163], [611, 1164], [650, 1165], [1093, 1166], [1052, 1167], [966, 1168], + [1095, 1169], [93, 1170], [632, 1171], [875, 1172], [254, 1173], [629, 1174], [55, 1175], + [1134, 1176], [765, 1177], [210, 1178], [388, 1179], [323, 1180], [479, 1181], [160, 1182], + [1174, 1183], [489, 1184], [62, 1185], [875, 1186], [584, 1187], [56, 1188], [1175, 1189], + [592, 1190], [669, 1191], [330, 1192], [876, 1193], [134, 1194], [43, 1195], [1035, 1196], + [760, 1197], [680, 1198], [367, 1199], [409, 1200], [339, 1201], [772, 1202], [1120, 1203], + [347, 1204], [426, 1205], [384, 1206], [1079, 1207], [454, 1208], [313, 1209], [245, 1210], + [61, 1211], [874, 1212], [885, 1213], [702, 1214], [327, 1215], [452, 1216], [1160, 1217], + [1173, 1218], [872, 1219], [905, 1220], [752, 1221], [918, 1222], [624, 1223], [1023, 1224], + [288, 1225], [479, 1226], [982, 1227], [1103, 1228], [1113, 1229], [695, 1230], [760, 1231], + [789, 1232], [592, 1233], [902, 1234], [1164, 1235], [113, 1236], [1098, 1237], [229, 1238], + [99, 1239], [697, 1240], [320, 1241], [464, 1242], [727, 1243], [761, 1244], [307, 1245], + [1215, 1246], [990, 1247], [859, 1248], [598, 1249], [998, 1250], [156, 1251], [489, 1252], + [815, 1253], [1003, 1254], [535, 1255], [1008, 1256], [246, 1257], [808, 1258], [569, 1259], + [148, 1260], [326, 1261], [40, 1262], [68, 1263], [880, 1264], [391, 1265], [189, 1266], + [1035, 1267], [193, 1268], [338, 1269], [77, 1270], [496, 1271], [322, 1272], [1050, 1273], + [801, 1274], [1211, 1275], [134, 1276], [968, 1277], [296, 1278], [930, 1279], [657, 1280], + [890, 1281], [85, 1282], [1007, 1283], [1194, 1284], [80, 1285], [1191, 1286], [178, 1287], + [1162, 1288], [289, 1289], [1099, 1290], [666, 1291], [291, 1292], [435, 1293], [6, 1294], + [1060, 1295], [219, 1296], [1216, 1297], [1282, 1298], [636, 1299], [960, 1300], + [558, 1301], [885, 1302], [603, 1303], [1261, 1304], [728, 1305], [915, 1306], [818, 1307], + [943, 1308], [260, 1309], [1004, 1310], [325, 1311], [875, 1312]])) diff --git a/Week_03/id_3/bfs/LeetCode_310_3_v2.py b/Week_03/id_3/bfs/LeetCode_310_3_v2.py new file mode 100644 index 00000000..1309e579 --- /dev/null +++ b/Week_03/id_3/bfs/LeetCode_310_3_v2.py @@ -0,0 +1,228 @@ +""" +寻找最小高度的根节点,从每一个节点然后向下遍历,最后比较最小值。这个思路是n^2的时间复杂度,无法通过测试。 +从叶子节点反向bfs,找到所有叶子节点最后的根节点,反倒合理的方案。 O(n) +如果 bfs 中出现 一个节点的边除去已经迭代过的子节点外,存在多余一个的边,那么说明改节点不应该继续进行迭代 + +这个有点儿像是拓扑排序,从叶子节点向根节点推进,如果一个叶子节点的父节点还有除该叶子节点以外的节点, +则说明还有其他高度更高的子树没有迭代上来,需要继续等待. + +如此就可以找到整个图最平衡的1-2个节点 + +v2实现参考了网上常见的叶子剪出答案 +""" + + +class Solution: + def findMinHeightTrees(self, n, edges): + if n == 0: + return [] + if n == 1: + return [0] + + graph = {} + for i in range(n): + graph[i] = set() + for n1, n2 in edges: + graph[n1].add(n2) + graph[n2].add(n1) + + leaves = list(filter(lambda x: len(graph[x]) == 1, graph)) + while True: + _leaves = list() + for i in leaves: + parent_set = graph.pop(i) + if len(parent_set) == 0: + continue + j = parent_set.pop() + parent_edges = graph[j] + parent_edges.remove(i) + if len(parent_edges) == 1: + _leaves.append(j) + + if len(_leaves) == 0: + return list(leaves) + + leaves = _leaves + + +s = Solution() +# print(s.findMinHeightTrees(6, [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]])) +print(s.findMinHeightTrees(1313, [[0, 1], [0, 2], [0, 3], [3, 4], [0, 5], [3, 6], [3, 7], [6, 8], [3, 9], [9, 10], [9, 11], + [10, 12], [3, 13], [2, 14], [5, 15], [1, 16], [5, 17], [15, 18], [17, 19], [12, 20], + [20, 21], [21, 22], [2, 23], [12, 24], [13, 25], [23, 26], [6, 27], [14, 28], [7, 29], + [14, 30], [28, 31], [3, 32], [20, 33], [6, 34], [28, 35], [14, 36], [12, 37], [25, 38], + [28, 39], [0, 40], [11, 41], [19, 42], [41, 43], [24, 44], [43, 45], [14, 46], [36, 47], + [26, 48], [16, 49], [42, 50], [43, 51], [11, 52], [7, 53], [50, 54], [17, 55], [9, 56], + [0, 57], [16, 58], [26, 59], [32, 60], [53, 61], [30, 62], [40, 63], [63, 64], [45, 65], + [13, 66], [24, 67], [42, 68], [2, 69], [63, 70], [39, 71], [34, 72], [20, 73], [20, 74], + [63, 75], [12, 76], [57, 77], [51, 78], [17, 79], [24, 80], [22, 81], [76, 82], [4, 83], + [16, 84], [75, 85], [21, 86], [21, 87], [8, 88], [28, 89], [85, 90], [31, 91], [53, 92], + [57, 93], [45, 94], [67, 95], [87, 96], [10, 97], [95, 98], [0, 99], [46, 100], [39, 101], + [47, 102], [101, 103], [72, 104], [2, 105], [3, 106], [78, 107], [32, 108], [23, 109], + [73, 110], [102, 111], [50, 112], [8, 113], [85, 114], [68, 115], [87, 116], [102, 117], + [77, 118], [62, 119], [70, 120], [86, 121], [13, 122], [101, 123], [69, 124], [37, 125], + [48, 126], [78, 127], [40, 128], [26, 129], [7, 130], [80, 131], [21, 132], [81, 133], + [62, 134], [97, 135], [71, 136], [123, 137], [78, 138], [16, 139], [5, 140], [10, 141], + [138, 142], [21, 143], [15, 144], [91, 145], [0, 146], [65, 147], [64, 148], [28, 149], + [86, 150], [28, 151], [111, 152], [140, 153], [138, 154], [77, 155], [145, 156], [50, 157], + [87, 158], [96, 159], [105, 160], [59, 161], [1, 162], [11, 163], [121, 164], [48, 165], + [119, 166], [133, 167], [26, 168], [92, 169], [63, 170], [158, 171], [164, 172], [115, 173], + [66, 174], [123, 175], [33, 176], [76, 177], [119, 178], [114, 179], [124, 180], [164, 181], + [85, 182], [143, 183], [110, 184], [53, 185], [120, 186], [78, 187], [131, 188], [185, 189], + [69, 190], [168, 191], [51, 192], [89, 193], [159, 194], [176, 195], [13, 196], [51, 197], + [6, 198], [28, 199], [46, 200], [105, 201], [167, 202], [148, 203], [19, 204], [204, 205], + [6, 206], [151, 207], [44, 208], [54, 209], [184, 210], [176, 211], [173, 212], [200, 213], + [203, 214], [106, 215], [87, 216], [1, 217], [173, 218], [103, 219], [160, 220], [118, 221], + [50, 222], [152, 223], [25, 224], [9, 225], [64, 226], [6, 227], [61, 228], [144, 229], + [212, 230], [166, 231], [30, 232], [196, 233], [215, 234], [109, 235], [183, 236], + [13, 237], [183, 238], [18, 239], [149, 240], [189, 241], [149, 242], [157, 243], + [116, 244], [99, 245], [30, 246], [56, 247], [239, 248], [239, 249], [57, 250], [31, 251], + [189, 252], [101, 253], [101, 254], [110, 255], [1, 256], [113, 257], [161, 258], [25, 259], + [44, 260], [194, 261], [137, 262], [218, 263], [183, 264], [228, 265], [153, 266], + [136, 267], [201, 268], [265, 269], [116, 270], [236, 271], [32, 272], [70, 273], + [104, 274], [82, 275], [198, 276], [44, 277], [262, 278], [269, 279], [26, 280], [91, 281], + [180, 282], [157, 283], [36, 284], [215, 285], [183, 286], [1, 287], [39, 288], [164, 289], + [110, 290], [266, 291], [208, 292], [258, 293], [68, 294], [1, 295], [100, 296], [16, 297], + [107, 298], [135, 299], [55, 300], [226, 301], [155, 302], [68, 303], [32, 304], [149, 305], + [217, 306], [186, 307], [69, 308], [244, 309], [14, 310], [216, 311], [211, 312], + [232, 313], [148, 314], [85, 315], [91, 316], [168, 317], [90, 318], [228, 319], [216, 320], + [51, 321], [31, 322], [230, 323], [160, 324], [200, 325], [94, 326], [282, 327], [162, 328], + [130, 329], [87, 330], [29, 331], [295, 332], [32, 333], [136, 334], [219, 335], [218, 336], + [25, 337], [233, 338], [55, 339], [130, 340], [319, 341], [165, 342], [255, 343], [15, 344], + [342, 345], [74, 346], [172, 347], [28, 348], [255, 349], [47, 350], [193, 351], [19, 352], + [303, 353], [205, 354], [174, 355], [172, 356], [260, 357], [243, 358], [186, 359], + [181, 360], [51, 361], [34, 362], [31, 363], [283, 364], [283, 365], [122, 366], [137, 367], + [225, 368], [296, 369], [346, 370], [235, 371], [278, 372], [116, 373], [31, 374], + [248, 375], [89, 376], [20, 377], [287, 378], [222, 379], [33, 380], [3, 381], [140, 382], + [185, 383], [255, 384], [241, 385], [164, 386], [185, 387], [208, 388], [347, 389], + [235, 390], [157, 391], [88, 392], [138, 393], [163, 394], [69, 395], [241, 396], + [307, 397], [271, 398], [248, 399], [346, 400], [265, 401], [90, 402], [249, 403], + [43, 404], [10, 405], [159, 406], [383, 407], [174, 408], [292, 409], [288, 410], + [149, 411], [244, 412], [174, 413], [201, 414], [287, 415], [94, 416], [102, 417], + [123, 418], [10, 419], [332, 420], [192, 421], [377, 422], [136, 423], [119, 424], + [187, 425], [128, 426], [413, 427], [3, 428], [255, 429], [410, 430], [303, 431], + [424, 432], [311, 433], [246, 434], [366, 435], [378, 436], [360, 437], [120, 438], + [90, 439], [353, 440], [126, 441], [78, 442], [23, 443], [115, 444], [6, 445], [359, 446], + [338, 447], [180, 448], [71, 449], [190, 450], [128, 451], [408, 452], [341, 453], + [426, 454], [14, 455], [455, 456], [411, 457], [107, 458], [450, 459], [351, 460], + [235, 461], [422, 462], [316, 463], [272, 464], [204, 465], [102, 466], [145, 467], + [20, 468], [326, 469], [186, 470], [266, 471], [127, 472], [144, 473], [112, 474], + [151, 475], [200, 476], [185, 477], [291, 478], [438, 479], [422, 480], [377, 481], + [261, 482], [437, 483], [204, 484], [324, 485], [402, 486], [106, 487], [268, 488], + [237, 489], [49, 490], [253, 491], [256, 492], [8, 493], [115, 494], [46, 495], [101, 496], + [325, 497], [90, 498], [146, 499], [252, 500], [255, 501], [277, 502], [129, 503], + [339, 504], [6, 505], [462, 506], [363, 507], [421, 508], [7, 509], [279, 510], [361, 511], + [35, 512], [112, 513], [113, 514], [194, 515], [128, 516], [65, 517], [26, 518], [305, 519], + [97, 520], [352, 521], [283, 522], [4, 523], [497, 524], [385, 525], [212, 526], [76, 527], + [92, 528], [194, 529], [344, 530], [510, 531], [461, 532], [89, 533], [228, 534], [97, 535], + [194, 536], [446, 537], [100, 538], [120, 539], [257, 540], [46, 541], [230, 542], + [357, 543], [365, 544], [265, 545], [123, 546], [290, 547], [100, 548], [194, 549], + [134, 550], [538, 551], [114, 552], [52, 553], [251, 554], [236, 555], [416, 556], + [264, 557], [461, 558], [14, 559], [376, 560], [254, 561], [422, 562], [233, 563], + [409, 564], [14, 565], [190, 566], [151, 567], [543, 568], [516, 569], [369, 570], + [432, 571], [343, 572], [341, 573], [531, 574], [77, 575], [394, 576], [471, 577], + [293, 578], [428, 579], [360, 580], [524, 581], [471, 582], [63, 583], [556, 584], + [254, 585], [583, 586], [491, 587], [460, 588], [250, 589], [329, 590], [504, 591], + [414, 592], [353, 593], [172, 594], [582, 595], [474, 596], [19, 597], [327, 598], + [464, 599], [39, 600], [278, 601], [234, 602], [131, 603], [569, 604], [466, 605], + [354, 606], [160, 607], [466, 608], [283, 609], [39, 610], [321, 611], [440, 612], + [280, 613], [142, 614], [9, 615], [411, 616], [519, 617], [317, 618], [278, 619], + [412, 620], [352, 621], [96, 622], [540, 623], [1, 624], [370, 625], [274, 626], [277, 627], + [30, 628], [79, 629], [134, 630], [435, 631], [21, 632], [437, 633], [285, 634], [461, 635], + [122, 636], [137, 637], [550, 638], [399, 639], [490, 640], [405, 641], [358, 642], + [205, 643], [352, 644], [544, 645], [319, 646], [412, 647], [554, 648], [561, 649], + [100, 650], [361, 651], [130, 652], [151, 653], [547, 654], [543, 655], [230, 656], + [34, 657], [240, 658], [533, 659], [220, 660], [551, 661], [635, 662], [298, 663], + [510, 664], [32, 665], [56, 666], [271, 667], [386, 668], [328, 669], [511, 670], + [648, 671], [213, 672], [640, 673], [620, 674], [292, 675], [612, 676], [231, 677], + [519, 678], [218, 679], [158, 680], [284, 681], [149, 682], [180, 683], [465, 684], + [101, 685], [97, 686], [592, 687], [577, 688], [501, 689], [130, 690], [574, 691], + [483, 692], [617, 693], [461, 694], [308, 695], [614, 696], [90, 697], [362, 698], + [313, 699], [301, 700], [562, 701], [41, 702], [627, 703], [408, 704], [476, 705], + [161, 706], [282, 707], [481, 708], [209, 709], [576, 710], [437, 711], [10, 712], + [548, 713], [256, 714], [498, 715], [129, 716], [664, 717], [70, 718], [185, 719], + [629, 720], [108, 721], [360, 722], [503, 723], [105, 724], [213, 725], [177, 726], + [46, 727], [104, 728], [398, 729], [209, 730], [89, 731], [499, 732], [368, 733], + [680, 734], [362, 735], [534, 736], [443, 737], [562, 738], [74, 739], [353, 740], + [165, 741], [108, 742], [438, 743], [131, 744], [140, 745], [37, 746], [28, 747], + [698, 748], [523, 749], [113, 750], [430, 751], [695, 752], [670, 753], [546, 754], + [366, 755], [369, 756], [602, 757], [415, 758], [291, 759], [352, 760], [560, 761], + [569, 762], [681, 763], [55, 764], [381, 765], [324, 766], [740, 767], [308, 768], + [728, 769], [374, 770], [118, 771], [97, 772], [646, 773], [6, 774], [626, 775], [444, 776], + [252, 777], [391, 778], [503, 779], [760, 780], [451, 781], [728, 782], [553, 783], + [410, 784], [487, 785], [343, 786], [350, 787], [579, 788], [3, 789], [706, 790], + [213, 791], [212, 792], [792, 793], [99, 794], [534, 795], [63, 796], [167, 797], + [109, 798], [692, 799], [597, 800], [742, 801], [407, 802], [256, 803], [442, 804], + [587, 805], [313, 806], [652, 807], [602, 808], [665, 809], [330, 810], [508, 811], + [683, 812], [598, 813], [661, 814], [709, 815], [594, 816], [337, 817], [219, 818], + [113, 819], [306, 820], [651, 821], [352, 822], [742, 823], [37, 824], [464, 825], + [452, 826], [165, 827], [774, 828], [17, 829], [280, 830], [511, 831], [542, 832], + [439, 833], [581, 834], [687, 835], [758, 836], [618, 837], [378, 838], [697, 839], + [769, 840], [702, 841], [606, 842], [105, 843], [663, 844], [157, 845], [441, 846], + [348, 847], [676, 848], [775, 849], [446, 850], [722, 851], [572, 852], [191, 853], + [765, 854], [710, 855], [569, 856], [134, 857], [596, 858], [304, 859], [20, 860], + [812, 861], [606, 862], [689, 863], [402, 864], [275, 865], [367, 866], [638, 867], + [618, 868], [231, 869], [367, 870], [255, 871], [740, 872], [232, 873], [571, 874], + [668, 875], [72, 876], [483, 877], [599, 878], [631, 879], [420, 880], [352, 881], + [289, 882], [720, 883], [556, 884], [430, 885], [410, 886], [728, 887], [412, 888], + [682, 889], [839, 890], [59, 891], [233, 892], [272, 893], [688, 894], [431, 895], + [310, 896], [407, 897], [567, 898], [743, 899], [811, 900], [808, 901], [246, 902], + [236, 903], [895, 904], [657, 905], [393, 906], [143, 907], [442, 908], [898, 909], + [72, 910], [282, 911], [901, 912], [624, 913], [697, 914], [484, 915], [582, 916], [4, 917], + [186, 918], [426, 919], [753, 920], [513, 921], [504, 922], [821, 923], [549, 924], + [415, 925], [634, 926], [505, 927], [590, 928], [866, 929], [267, 930], [236, 931], + [343, 932], [693, 933], [116, 934], [543, 935], [463, 936], [880, 937], [126, 938], + [832, 939], [205, 940], [33, 941], [284, 942], [941, 943], [940, 944], [943, 945], + [784, 946], [785, 947], [498, 948], [898, 949], [715, 950], [238, 951], [389, 952], + [951, 953], [511, 954], [767, 955], [332, 956], [300, 957], [298, 958], [317, 959], + [221, 960], [253, 961], [438, 962], [751, 963], [492, 964], [384, 965], [274, 966], + [820, 967], [376, 968], [159, 969], [766, 970], [909, 971], [669, 972], [8, 973], + [957, 974], [539, 975], [844, 976], [470, 977], [80, 978], [641, 979], [172, 980], + [962, 981], [756, 982], [195, 983], [131, 984], [216, 985], [503, 986], [330, 987], + [863, 988], [446, 989], [673, 990], [760, 991], [871, 992], [903, 993], [47, 994], + [810, 995], [736, 996], [749, 997], [951, 998], [348, 999], [741, 1000], [448, 1001], + [809, 1002], [704, 1003], [702, 1004], [113, 1005], [392, 1006], [216, 1007], [58, 1008], + [348, 1009], [170, 1010], [695, 1011], [168, 1012], [752, 1013], [168, 1014], [376, 1015], + [856, 1016], [302, 1017], [278, 1018], [554, 1019], [844, 1020], [368, 1021], [555, 1022], + [283, 1023], [220, 1024], [907, 1025], [356, 1026], [415, 1027], [977, 1028], [433, 1029], + [741, 1030], [702, 1031], [202, 1032], [420, 1033], [773, 1034], [929, 1035], [1020, 1036], + [752, 1037], [846, 1038], [909, 1039], [137, 1040], [752, 1041], [728, 1042], [295, 1043], + [998, 1044], [52, 1045], [825, 1046], [727, 1047], [871, 1048], [941, 1049], [342, 1050], + [579, 1051], [424, 1052], [756, 1053], [50, 1054], [587, 1055], [447, 1056], [1042, 1057], + [171, 1058], [322, 1059], [1049, 1060], [189, 1061], [384, 1062], [403, 1063], [468, 1064], + [666, 1065], [282, 1066], [271, 1067], [407, 1068], [323, 1069], [52, 1070], [571, 1071], + [46, 1072], [412, 1073], [616, 1074], [417, 1075], [1042, 1076], [657, 1077], [940, 1078], + [498, 1079], [597, 1080], [95, 1081], [12, 1082], [541, 1083], [519, 1084], [463, 1085], + [848, 1086], [1000, 1087], [788, 1088], [337, 1089], [1001, 1090], [267, 1091], [378, 1092], + [234, 1093], [907, 1094], [826, 1095], [31, 1096], [188, 1097], [502, 1098], [826, 1099], + [948, 1100], [879, 1101], [388, 1102], [34, 1103], [461, 1104], [568, 1105], [79, 1106], + [319, 1107], [364, 1108], [190, 1109], [605, 1110], [717, 1111], [622, 1112], [385, 1113], + [25, 1114], [835, 1115], [1033, 1116], [1085, 1117], [240, 1118], [199, 1119], [693, 1120], + [68, 1121], [478, 1122], [95, 1123], [842, 1124], [1109, 1125], [678, 1126], [104, 1127], + [918, 1128], [414, 1129], [768, 1130], [421, 1131], [825, 1132], [636, 1133], [290, 1134], + [1083, 1135], [473, 1136], [616, 1137], [1094, 1138], [28, 1139], [137, 1140], [590, 1141], + [654, 1142], [1140, 1143], [789, 1144], [670, 1145], [475, 1146], [176, 1147], [27, 1148], + [1106, 1149], [430, 1150], [192, 1151], [869, 1152], [546, 1153], [955, 1154], [493, 1155], + [643, 1156], [663, 1157], [702, 1158], [823, 1159], [1022, 1160], [228, 1161], [578, 1162], + [655, 1163], [611, 1164], [650, 1165], [1093, 1166], [1052, 1167], [966, 1168], + [1095, 1169], [93, 1170], [632, 1171], [875, 1172], [254, 1173], [629, 1174], [55, 1175], + [1134, 1176], [765, 1177], [210, 1178], [388, 1179], [323, 1180], [479, 1181], [160, 1182], + [1174, 1183], [489, 1184], [62, 1185], [875, 1186], [584, 1187], [56, 1188], [1175, 1189], + [592, 1190], [669, 1191], [330, 1192], [876, 1193], [134, 1194], [43, 1195], [1035, 1196], + [760, 1197], [680, 1198], [367, 1199], [409, 1200], [339, 1201], [772, 1202], [1120, 1203], + [347, 1204], [426, 1205], [384, 1206], [1079, 1207], [454, 1208], [313, 1209], [245, 1210], + [61, 1211], [874, 1212], [885, 1213], [702, 1214], [327, 1215], [452, 1216], [1160, 1217], + [1173, 1218], [872, 1219], [905, 1220], [752, 1221], [918, 1222], [624, 1223], [1023, 1224], + [288, 1225], [479, 1226], [982, 1227], [1103, 1228], [1113, 1229], [695, 1230], [760, 1231], + [789, 1232], [592, 1233], [902, 1234], [1164, 1235], [113, 1236], [1098, 1237], [229, 1238], + [99, 1239], [697, 1240], [320, 1241], [464, 1242], [727, 1243], [761, 1244], [307, 1245], + [1215, 1246], [990, 1247], [859, 1248], [598, 1249], [998, 1250], [156, 1251], [489, 1252], + [815, 1253], [1003, 1254], [535, 1255], [1008, 1256], [246, 1257], [808, 1258], [569, 1259], + [148, 1260], [326, 1261], [40, 1262], [68, 1263], [880, 1264], [391, 1265], [189, 1266], + [1035, 1267], [193, 1268], [338, 1269], [77, 1270], [496, 1271], [322, 1272], [1050, 1273], + [801, 1274], [1211, 1275], [134, 1276], [968, 1277], [296, 1278], [930, 1279], [657, 1280], + [890, 1281], [85, 1282], [1007, 1283], [1194, 1284], [80, 1285], [1191, 1286], [178, 1287], + [1162, 1288], [289, 1289], [1099, 1290], [666, 1291], [291, 1292], [435, 1293], [6, 1294], + [1060, 1295], [219, 1296], [1216, 1297], [1282, 1298], [636, 1299], [960, 1300], + [558, 1301], [885, 1302], [603, 1303], [1261, 1304], [728, 1305], [915, 1306], [818, 1307], + [943, 1308], [260, 1309], [1004, 1310], [325, 1311], [875, 1312]])) diff --git a/Week_03/id_3/bfs/LeetCode_310_3_v3.py b/Week_03/id_3/bfs/LeetCode_310_3_v3.py new file mode 100644 index 00000000..3101f8c4 --- /dev/null +++ b/Week_03/id_3/bfs/LeetCode_310_3_v3.py @@ -0,0 +1,227 @@ +""" +寻找最小高度的根节点,从每一个节点然后向下遍历,最后比较最小值。这个思路是n^2的时间复杂度,无法通过测试。 +从叶子节点反向bfs,找到所有叶子节点最后的根节点,反倒合理的方案。 O(n) +如果 bfs 中出现 一个节点的边除去已经迭代过的子节点外,存在多余一个的边,那么说明改节点不应该继续进行迭代 + +这个有点儿像是拓扑排序,从叶子节点向根节点推进,如果一个叶子节点的父节点还有除该叶子节点以外的节点, +则说明还有其他高度更高的子树没有迭代上来,需要继续等待. + +如此就可以找到整个图最平衡的1-2个节点 + +v3 尝试使用拓扑排序的入度值得方案 +""" + + +class Solution: + def findMinHeightTrees(self, n, edges): + if n == 0: + return [] + if n == 1: + return [0] + + graph = [[] for _ in range(n)] + count_graph = [0 for _ in range(n)] + + for n1, n2 in edges: + graph[n1].append(n2) + graph[n2].append(n1) + count_graph[n1] += 1 + count_graph[n2] += 1 + + queue = [] + for i, v in enumerate(count_graph): + if v == 1: + queue.append(i) + + while queue: + _queue = [] + for i in queue: + for sn in graph[i]: + count_graph[sn] -= 1 + if count_graph[sn] == 1: + _queue.append(sn) + if not _queue: + return queue + queue = _queue + + +s = Solution() +print(s.findMinHeightTrees(1313, [[0, 1], [0, 2], [0, 3], [3, 4], [0, 5], [3, 6], [3, 7], [6, 8], [3, 9], [9, 10], [9, 11], + [10, 12], [3, 13], [2, 14], [5, 15], [1, 16], [5, 17], [15, 18], [17, 19], [12, 20], + [20, 21], [21, 22], [2, 23], [12, 24], [13, 25], [23, 26], [6, 27], [14, 28], [7, 29], + [14, 30], [28, 31], [3, 32], [20, 33], [6, 34], [28, 35], [14, 36], [12, 37], [25, 38], + [28, 39], [0, 40], [11, 41], [19, 42], [41, 43], [24, 44], [43, 45], [14, 46], [36, 47], + [26, 48], [16, 49], [42, 50], [43, 51], [11, 52], [7, 53], [50, 54], [17, 55], [9, 56], + [0, 57], [16, 58], [26, 59], [32, 60], [53, 61], [30, 62], [40, 63], [63, 64], [45, 65], + [13, 66], [24, 67], [42, 68], [2, 69], [63, 70], [39, 71], [34, 72], [20, 73], [20, 74], + [63, 75], [12, 76], [57, 77], [51, 78], [17, 79], [24, 80], [22, 81], [76, 82], [4, 83], + [16, 84], [75, 85], [21, 86], [21, 87], [8, 88], [28, 89], [85, 90], [31, 91], [53, 92], + [57, 93], [45, 94], [67, 95], [87, 96], [10, 97], [95, 98], [0, 99], [46, 100], [39, 101], + [47, 102], [101, 103], [72, 104], [2, 105], [3, 106], [78, 107], [32, 108], [23, 109], + [73, 110], [102, 111], [50, 112], [8, 113], [85, 114], [68, 115], [87, 116], [102, 117], + [77, 118], [62, 119], [70, 120], [86, 121], [13, 122], [101, 123], [69, 124], [37, 125], + [48, 126], [78, 127], [40, 128], [26, 129], [7, 130], [80, 131], [21, 132], [81, 133], + [62, 134], [97, 135], [71, 136], [123, 137], [78, 138], [16, 139], [5, 140], [10, 141], + [138, 142], [21, 143], [15, 144], [91, 145], [0, 146], [65, 147], [64, 148], [28, 149], + [86, 150], [28, 151], [111, 152], [140, 153], [138, 154], [77, 155], [145, 156], [50, 157], + [87, 158], [96, 159], [105, 160], [59, 161], [1, 162], [11, 163], [121, 164], [48, 165], + [119, 166], [133, 167], [26, 168], [92, 169], [63, 170], [158, 171], [164, 172], [115, 173], + [66, 174], [123, 175], [33, 176], [76, 177], [119, 178], [114, 179], [124, 180], [164, 181], + [85, 182], [143, 183], [110, 184], [53, 185], [120, 186], [78, 187], [131, 188], [185, 189], + [69, 190], [168, 191], [51, 192], [89, 193], [159, 194], [176, 195], [13, 196], [51, 197], + [6, 198], [28, 199], [46, 200], [105, 201], [167, 202], [148, 203], [19, 204], [204, 205], + [6, 206], [151, 207], [44, 208], [54, 209], [184, 210], [176, 211], [173, 212], [200, 213], + [203, 214], [106, 215], [87, 216], [1, 217], [173, 218], [103, 219], [160, 220], [118, 221], + [50, 222], [152, 223], [25, 224], [9, 225], [64, 226], [6, 227], [61, 228], [144, 229], + [212, 230], [166, 231], [30, 232], [196, 233], [215, 234], [109, 235], [183, 236], + [13, 237], [183, 238], [18, 239], [149, 240], [189, 241], [149, 242], [157, 243], + [116, 244], [99, 245], [30, 246], [56, 247], [239, 248], [239, 249], [57, 250], [31, 251], + [189, 252], [101, 253], [101, 254], [110, 255], [1, 256], [113, 257], [161, 258], [25, 259], + [44, 260], [194, 261], [137, 262], [218, 263], [183, 264], [228, 265], [153, 266], + [136, 267], [201, 268], [265, 269], [116, 270], [236, 271], [32, 272], [70, 273], + [104, 274], [82, 275], [198, 276], [44, 277], [262, 278], [269, 279], [26, 280], [91, 281], + [180, 282], [157, 283], [36, 284], [215, 285], [183, 286], [1, 287], [39, 288], [164, 289], + [110, 290], [266, 291], [208, 292], [258, 293], [68, 294], [1, 295], [100, 296], [16, 297], + [107, 298], [135, 299], [55, 300], [226, 301], [155, 302], [68, 303], [32, 304], [149, 305], + [217, 306], [186, 307], [69, 308], [244, 309], [14, 310], [216, 311], [211, 312], + [232, 313], [148, 314], [85, 315], [91, 316], [168, 317], [90, 318], [228, 319], [216, 320], + [51, 321], [31, 322], [230, 323], [160, 324], [200, 325], [94, 326], [282, 327], [162, 328], + [130, 329], [87, 330], [29, 331], [295, 332], [32, 333], [136, 334], [219, 335], [218, 336], + [25, 337], [233, 338], [55, 339], [130, 340], [319, 341], [165, 342], [255, 343], [15, 344], + [342, 345], [74, 346], [172, 347], [28, 348], [255, 349], [47, 350], [193, 351], [19, 352], + [303, 353], [205, 354], [174, 355], [172, 356], [260, 357], [243, 358], [186, 359], + [181, 360], [51, 361], [34, 362], [31, 363], [283, 364], [283, 365], [122, 366], [137, 367], + [225, 368], [296, 369], [346, 370], [235, 371], [278, 372], [116, 373], [31, 374], + [248, 375], [89, 376], [20, 377], [287, 378], [222, 379], [33, 380], [3, 381], [140, 382], + [185, 383], [255, 384], [241, 385], [164, 386], [185, 387], [208, 388], [347, 389], + [235, 390], [157, 391], [88, 392], [138, 393], [163, 394], [69, 395], [241, 396], + [307, 397], [271, 398], [248, 399], [346, 400], [265, 401], [90, 402], [249, 403], + [43, 404], [10, 405], [159, 406], [383, 407], [174, 408], [292, 409], [288, 410], + [149, 411], [244, 412], [174, 413], [201, 414], [287, 415], [94, 416], [102, 417], + [123, 418], [10, 419], [332, 420], [192, 421], [377, 422], [136, 423], [119, 424], + [187, 425], [128, 426], [413, 427], [3, 428], [255, 429], [410, 430], [303, 431], + [424, 432], [311, 433], [246, 434], [366, 435], [378, 436], [360, 437], [120, 438], + [90, 439], [353, 440], [126, 441], [78, 442], [23, 443], [115, 444], [6, 445], [359, 446], + [338, 447], [180, 448], [71, 449], [190, 450], [128, 451], [408, 452], [341, 453], + [426, 454], [14, 455], [455, 456], [411, 457], [107, 458], [450, 459], [351, 460], + [235, 461], [422, 462], [316, 463], [272, 464], [204, 465], [102, 466], [145, 467], + [20, 468], [326, 469], [186, 470], [266, 471], [127, 472], [144, 473], [112, 474], + [151, 475], [200, 476], [185, 477], [291, 478], [438, 479], [422, 480], [377, 481], + [261, 482], [437, 483], [204, 484], [324, 485], [402, 486], [106, 487], [268, 488], + [237, 489], [49, 490], [253, 491], [256, 492], [8, 493], [115, 494], [46, 495], [101, 496], + [325, 497], [90, 498], [146, 499], [252, 500], [255, 501], [277, 502], [129, 503], + [339, 504], [6, 505], [462, 506], [363, 507], [421, 508], [7, 509], [279, 510], [361, 511], + [35, 512], [112, 513], [113, 514], [194, 515], [128, 516], [65, 517], [26, 518], [305, 519], + [97, 520], [352, 521], [283, 522], [4, 523], [497, 524], [385, 525], [212, 526], [76, 527], + [92, 528], [194, 529], [344, 530], [510, 531], [461, 532], [89, 533], [228, 534], [97, 535], + [194, 536], [446, 537], [100, 538], [120, 539], [257, 540], [46, 541], [230, 542], + [357, 543], [365, 544], [265, 545], [123, 546], [290, 547], [100, 548], [194, 549], + [134, 550], [538, 551], [114, 552], [52, 553], [251, 554], [236, 555], [416, 556], + [264, 557], [461, 558], [14, 559], [376, 560], [254, 561], [422, 562], [233, 563], + [409, 564], [14, 565], [190, 566], [151, 567], [543, 568], [516, 569], [369, 570], + [432, 571], [343, 572], [341, 573], [531, 574], [77, 575], [394, 576], [471, 577], + [293, 578], [428, 579], [360, 580], [524, 581], [471, 582], [63, 583], [556, 584], + [254, 585], [583, 586], [491, 587], [460, 588], [250, 589], [329, 590], [504, 591], + [414, 592], [353, 593], [172, 594], [582, 595], [474, 596], [19, 597], [327, 598], + [464, 599], [39, 600], [278, 601], [234, 602], [131, 603], [569, 604], [466, 605], + [354, 606], [160, 607], [466, 608], [283, 609], [39, 610], [321, 611], [440, 612], + [280, 613], [142, 614], [9, 615], [411, 616], [519, 617], [317, 618], [278, 619], + [412, 620], [352, 621], [96, 622], [540, 623], [1, 624], [370, 625], [274, 626], [277, 627], + [30, 628], [79, 629], [134, 630], [435, 631], [21, 632], [437, 633], [285, 634], [461, 635], + [122, 636], [137, 637], [550, 638], [399, 639], [490, 640], [405, 641], [358, 642], + [205, 643], [352, 644], [544, 645], [319, 646], [412, 647], [554, 648], [561, 649], + [100, 650], [361, 651], [130, 652], [151, 653], [547, 654], [543, 655], [230, 656], + [34, 657], [240, 658], [533, 659], [220, 660], [551, 661], [635, 662], [298, 663], + [510, 664], [32, 665], [56, 666], [271, 667], [386, 668], [328, 669], [511, 670], + [648, 671], [213, 672], [640, 673], [620, 674], [292, 675], [612, 676], [231, 677], + [519, 678], [218, 679], [158, 680], [284, 681], [149, 682], [180, 683], [465, 684], + [101, 685], [97, 686], [592, 687], [577, 688], [501, 689], [130, 690], [574, 691], + [483, 692], [617, 693], [461, 694], [308, 695], [614, 696], [90, 697], [362, 698], + [313, 699], [301, 700], [562, 701], [41, 702], [627, 703], [408, 704], [476, 705], + [161, 706], [282, 707], [481, 708], [209, 709], [576, 710], [437, 711], [10, 712], + [548, 713], [256, 714], [498, 715], [129, 716], [664, 717], [70, 718], [185, 719], + [629, 720], [108, 721], [360, 722], [503, 723], [105, 724], [213, 725], [177, 726], + [46, 727], [104, 728], [398, 729], [209, 730], [89, 731], [499, 732], [368, 733], + [680, 734], [362, 735], [534, 736], [443, 737], [562, 738], [74, 739], [353, 740], + [165, 741], [108, 742], [438, 743], [131, 744], [140, 745], [37, 746], [28, 747], + [698, 748], [523, 749], [113, 750], [430, 751], [695, 752], [670, 753], [546, 754], + [366, 755], [369, 756], [602, 757], [415, 758], [291, 759], [352, 760], [560, 761], + [569, 762], [681, 763], [55, 764], [381, 765], [324, 766], [740, 767], [308, 768], + [728, 769], [374, 770], [118, 771], [97, 772], [646, 773], [6, 774], [626, 775], [444, 776], + [252, 777], [391, 778], [503, 779], [760, 780], [451, 781], [728, 782], [553, 783], + [410, 784], [487, 785], [343, 786], [350, 787], [579, 788], [3, 789], [706, 790], + [213, 791], [212, 792], [792, 793], [99, 794], [534, 795], [63, 796], [167, 797], + [109, 798], [692, 799], [597, 800], [742, 801], [407, 802], [256, 803], [442, 804], + [587, 805], [313, 806], [652, 807], [602, 808], [665, 809], [330, 810], [508, 811], + [683, 812], [598, 813], [661, 814], [709, 815], [594, 816], [337, 817], [219, 818], + [113, 819], [306, 820], [651, 821], [352, 822], [742, 823], [37, 824], [464, 825], + [452, 826], [165, 827], [774, 828], [17, 829], [280, 830], [511, 831], [542, 832], + [439, 833], [581, 834], [687, 835], [758, 836], [618, 837], [378, 838], [697, 839], + [769, 840], [702, 841], [606, 842], [105, 843], [663, 844], [157, 845], [441, 846], + [348, 847], [676, 848], [775, 849], [446, 850], [722, 851], [572, 852], [191, 853], + [765, 854], [710, 855], [569, 856], [134, 857], [596, 858], [304, 859], [20, 860], + [812, 861], [606, 862], [689, 863], [402, 864], [275, 865], [367, 866], [638, 867], + [618, 868], [231, 869], [367, 870], [255, 871], [740, 872], [232, 873], [571, 874], + [668, 875], [72, 876], [483, 877], [599, 878], [631, 879], [420, 880], [352, 881], + [289, 882], [720, 883], [556, 884], [430, 885], [410, 886], [728, 887], [412, 888], + [682, 889], [839, 890], [59, 891], [233, 892], [272, 893], [688, 894], [431, 895], + [310, 896], [407, 897], [567, 898], [743, 899], [811, 900], [808, 901], [246, 902], + [236, 903], [895, 904], [657, 905], [393, 906], [143, 907], [442, 908], [898, 909], + [72, 910], [282, 911], [901, 912], [624, 913], [697, 914], [484, 915], [582, 916], [4, 917], + [186, 918], [426, 919], [753, 920], [513, 921], [504, 922], [821, 923], [549, 924], + [415, 925], [634, 926], [505, 927], [590, 928], [866, 929], [267, 930], [236, 931], + [343, 932], [693, 933], [116, 934], [543, 935], [463, 936], [880, 937], [126, 938], + [832, 939], [205, 940], [33, 941], [284, 942], [941, 943], [940, 944], [943, 945], + [784, 946], [785, 947], [498, 948], [898, 949], [715, 950], [238, 951], [389, 952], + [951, 953], [511, 954], [767, 955], [332, 956], [300, 957], [298, 958], [317, 959], + [221, 960], [253, 961], [438, 962], [751, 963], [492, 964], [384, 965], [274, 966], + [820, 967], [376, 968], [159, 969], [766, 970], [909, 971], [669, 972], [8, 973], + [957, 974], [539, 975], [844, 976], [470, 977], [80, 978], [641, 979], [172, 980], + [962, 981], [756, 982], [195, 983], [131, 984], [216, 985], [503, 986], [330, 987], + [863, 988], [446, 989], [673, 990], [760, 991], [871, 992], [903, 993], [47, 994], + [810, 995], [736, 996], [749, 997], [951, 998], [348, 999], [741, 1000], [448, 1001], + [809, 1002], [704, 1003], [702, 1004], [113, 1005], [392, 1006], [216, 1007], [58, 1008], + [348, 1009], [170, 1010], [695, 1011], [168, 1012], [752, 1013], [168, 1014], [376, 1015], + [856, 1016], [302, 1017], [278, 1018], [554, 1019], [844, 1020], [368, 1021], [555, 1022], + [283, 1023], [220, 1024], [907, 1025], [356, 1026], [415, 1027], [977, 1028], [433, 1029], + [741, 1030], [702, 1031], [202, 1032], [420, 1033], [773, 1034], [929, 1035], [1020, 1036], + [752, 1037], [846, 1038], [909, 1039], [137, 1040], [752, 1041], [728, 1042], [295, 1043], + [998, 1044], [52, 1045], [825, 1046], [727, 1047], [871, 1048], [941, 1049], [342, 1050], + [579, 1051], [424, 1052], [756, 1053], [50, 1054], [587, 1055], [447, 1056], [1042, 1057], + [171, 1058], [322, 1059], [1049, 1060], [189, 1061], [384, 1062], [403, 1063], [468, 1064], + [666, 1065], [282, 1066], [271, 1067], [407, 1068], [323, 1069], [52, 1070], [571, 1071], + [46, 1072], [412, 1073], [616, 1074], [417, 1075], [1042, 1076], [657, 1077], [940, 1078], + [498, 1079], [597, 1080], [95, 1081], [12, 1082], [541, 1083], [519, 1084], [463, 1085], + [848, 1086], [1000, 1087], [788, 1088], [337, 1089], [1001, 1090], [267, 1091], [378, 1092], + [234, 1093], [907, 1094], [826, 1095], [31, 1096], [188, 1097], [502, 1098], [826, 1099], + [948, 1100], [879, 1101], [388, 1102], [34, 1103], [461, 1104], [568, 1105], [79, 1106], + [319, 1107], [364, 1108], [190, 1109], [605, 1110], [717, 1111], [622, 1112], [385, 1113], + [25, 1114], [835, 1115], [1033, 1116], [1085, 1117], [240, 1118], [199, 1119], [693, 1120], + [68, 1121], [478, 1122], [95, 1123], [842, 1124], [1109, 1125], [678, 1126], [104, 1127], + [918, 1128], [414, 1129], [768, 1130], [421, 1131], [825, 1132], [636, 1133], [290, 1134], + [1083, 1135], [473, 1136], [616, 1137], [1094, 1138], [28, 1139], [137, 1140], [590, 1141], + [654, 1142], [1140, 1143], [789, 1144], [670, 1145], [475, 1146], [176, 1147], [27, 1148], + [1106, 1149], [430, 1150], [192, 1151], [869, 1152], [546, 1153], [955, 1154], [493, 1155], + [643, 1156], [663, 1157], [702, 1158], [823, 1159], [1022, 1160], [228, 1161], [578, 1162], + [655, 1163], [611, 1164], [650, 1165], [1093, 1166], [1052, 1167], [966, 1168], + [1095, 1169], [93, 1170], [632, 1171], [875, 1172], [254, 1173], [629, 1174], [55, 1175], + [1134, 1176], [765, 1177], [210, 1178], [388, 1179], [323, 1180], [479, 1181], [160, 1182], + [1174, 1183], [489, 1184], [62, 1185], [875, 1186], [584, 1187], [56, 1188], [1175, 1189], + [592, 1190], [669, 1191], [330, 1192], [876, 1193], [134, 1194], [43, 1195], [1035, 1196], + [760, 1197], [680, 1198], [367, 1199], [409, 1200], [339, 1201], [772, 1202], [1120, 1203], + [347, 1204], [426, 1205], [384, 1206], [1079, 1207], [454, 1208], [313, 1209], [245, 1210], + [61, 1211], [874, 1212], [885, 1213], [702, 1214], [327, 1215], [452, 1216], [1160, 1217], + [1173, 1218], [872, 1219], [905, 1220], [752, 1221], [918, 1222], [624, 1223], [1023, 1224], + [288, 1225], [479, 1226], [982, 1227], [1103, 1228], [1113, 1229], [695, 1230], [760, 1231], + [789, 1232], [592, 1233], [902, 1234], [1164, 1235], [113, 1236], [1098, 1237], [229, 1238], + [99, 1239], [697, 1240], [320, 1241], [464, 1242], [727, 1243], [761, 1244], [307, 1245], + [1215, 1246], [990, 1247], [859, 1248], [598, 1249], [998, 1250], [156, 1251], [489, 1252], + [815, 1253], [1003, 1254], [535, 1255], [1008, 1256], [246, 1257], [808, 1258], [569, 1259], + [148, 1260], [326, 1261], [40, 1262], [68, 1263], [880, 1264], [391, 1265], [189, 1266], + [1035, 1267], [193, 1268], [338, 1269], [77, 1270], [496, 1271], [322, 1272], [1050, 1273], + [801, 1274], [1211, 1275], [134, 1276], [968, 1277], [296, 1278], [930, 1279], [657, 1280], + [890, 1281], [85, 1282], [1007, 1283], [1194, 1284], [80, 1285], [1191, 1286], [178, 1287], + [1162, 1288], [289, 1289], [1099, 1290], [666, 1291], [291, 1292], [435, 1293], [6, 1294], + [1060, 1295], [219, 1296], [1216, 1297], [1282, 1298], [636, 1299], [960, 1300], + [558, 1301], [885, 1302], [603, 1303], [1261, 1304], [728, 1305], [915, 1306], [818, 1307], + [943, 1308], [260, 1309], [1004, 1310], [325, 1311], [875, 1312]])) diff --git a/Week_03/id_3/dfs/LeetCode_127_3_v1.py b/Week_03/id_3/dfs/LeetCode_127_3_v1.py new file mode 100644 index 00000000..5b740a0d --- /dev/null +++ b/Week_03/id_3/dfs/LeetCode_127_3_v1.py @@ -0,0 +1,322 @@ +""" +初步思路就是 回溯暴力 并缓存每个节点的最近值用来剪枝 +例如经过 n1次到达节点w1 cache[w1] = n1 +当再次触达 w1时,当前n2如果>=n1则没有必要进一步下钻了 + +===== 超时了 + +改进思路,之前太过暴力 n^n,这次先用n^2构建邻接表,避免过多重复的判断试试 +时间复杂度就变成了 e^n 如果还是超时 就要进一步剪枝了 + +===== 跑单个用力耗时接近2s 还是继续优化 +由于cache的存在 visited的set没有存在的必要了 因为如果出现环 必然后迭代的level要超过cache之前都值,就会被剪掉 + +===== 后面居然还有个4位 2800个单词的用例 又超时了 +尝试使用两个cache,一个做正向的visited_cache,剪掉触达过慢的节点。另一个做逆向结果缓存cache。 +另外邻接表也不搞了,这个用例光构建邻接表就超时了 + +===== 依然没用过 看这个用例官方的答案是11,2000^11也是不可能的,必须做更多预处理 +利用模糊一个字符的方式快速构建类似邻接表的东西,把原本n^2简化为n +本地运算的时间在可控范围内了,但是服务器提交肯定是不行 + +DFS怕是不行了…… +""" +import sys +sys.setrecursionlimit(10000) + + +class Solution: + def ladderLength(self, begin, end, word_list) -> int: + if not begin or not end or not word_list or end not in word_list: + return 0 + visited_cache = {} + arrived_cache = {} + word_graph = {} + for w in word_list: + for i in range(len(w)): + k = w[0:i] + '*' + w[i+1:] + arr = word_graph.get(k, []) + arr.append(w) + word_graph[k] = arr + return self.dfs(begin, end, 1, word_graph, visited_cache, arrived_cache) + + def dfs(self, curr, end, level, word_graph, visited_cache, arrived_cache): + if curr in arrived_cache: + return arrived_cache[curr] + if curr in visited_cache and level >= visited_cache[curr]: + return 0 + + visited_cache[curr] = level + results = [] + for i in range(len(curr)): + k = curr[0:i] + '*' + curr[i+1:] + if k not in word_graph: + continue + for w in word_graph[k]: + if w == curr: + continue + if w == end: + arrived_cache[curr] = 2 + return 2 + results.append(self.dfs(w, end, level + 1, word_graph, visited_cache, arrived_cache)) + + results = list(filter(lambda r: r != 0, results)) + if not results: + return 0 + return 1 + min(results) + # + # def diff_count(self, ss, ts): + # count = 0 + # for i in range(len(ss)): + # if ss[i] != ts[i]: + # count += 1 + # return count + # + # def check(self, ss, ts): + # if len(ss) != len(ts): + # return False + # return self.diff_count(ss, ts) == 1 + + +s = Solution() +print(s.ladderLength("hit", "cog", ["hot", "dot", "dog", "lot", "log", "cog"])) +print(s.ladderLength("hit", "cog", ["hot", "dot", "dog", "lot"])) +print(s.ladderLength("sand", "acne", + ["slit", "bunk", "wars", "ping", "viva", "wynn", "wows", "irks", "gang", "pool", "mock", "fort", + "heel", "send", "ship", "cols", "alec", "foal", "nabs", "gaze", "giza", "mays", "dogs", "karo", + "cums", "jedi", "webb", "lend", "mire", "jose", "catt", "grow", "toss", "magi", "leis", "bead", + "kara", "hoof", "than", "ires", "baas", "vein", "kari", "riga", "oars", "gags", "thug", "yawn", + "wive", "view", "germ", "flab", "july", "tuck", "rory", "bean", "feed", "rhee", "jeez", "gobs", + "lath", "desk", "yoko", "cute", "zeus", "thus", "dims", "link", "dirt", "mara", "disc", "limy", + "lewd", "maud", "duly", "elsa", "hart", "rays", "rues", "camp", "lack", "okra", "tome", "math", + "plug", "monk", "orly", "friz", "hogs", "yoda", "poop", "tick", "plod", "cloy", "pees", "imps", + "lead", "pope", "mall", "frey", "been", "plea", "poll", "male", "teak", "soho", "glob", "bell", + "mary", "hail", "scan", "yips", "like", "mull", "kory", "odor", "byte", "kaye", "word", "honk", + "asks", "slid", "hopi", "toke", "gore", "flew", "tins", "mown", "oise", "hall", "vega", "sing", + "fool", "boat", "bobs", "lain", "soft", "hard", "rots", "sees", "apex", "chan", "told", "woos", + "unit", "scow", "gilt", "beef", "jars", "tyre", "imus", "neon", "soap", "dabs", "rein", "ovid", + "hose", "husk", "loll", "asia", "cope", "tail", "hazy", "clad", "lash", "sags", "moll", "eddy", + "fuel", "lift", "flog", "land", "sigh", "saks", "sail", "hook", "visa", "tier", "maws", "roeg", + "gila", "eyes", "noah", "hypo", "tore", "eggs", "rove", "chap", "room", "wait", "lurk", "race", + "host", "dada", "lola", "gabs", "sobs", "joel", "keck", "axed", "mead", "gust", "laid", "ends", + "oort", "nose", "peer", "kept", "abet", "iran", "mick", "dead", "hags", "tens", "gown", "sick", + "odis", "miro", "bill", "fawn", "sumo", "kilt", "huge", "ores", "oran", "flag", "tost", "seth", + "sift", "poet", "reds", "pips", "cape", "togo", "wale", "limn", "toll", "ploy", "inns", "snag", + "hoes", "jerk", "flux", "fido", "zane", "arab", "gamy", "raze", "lank", "hurt", "rail", "hind", + "hoot", "dogy", "away", "pest", "hoed", "pose", "lose", "pole", "alva", "dino", "kind", "clan", + "dips", "soup", "veto", "edna", "damp", "gush", "amen", "wits", "pubs", "fuzz", "cash", "pine", + "trod", "gunk", "nude", "lost", "rite", "cory", "walt", "mica", "cart", "avow", "wind", "book", + "leon", "life", "bang", "draw", "leek", "skis", "dram", "ripe", "mine", "urea", "tiff", "over", + "gale", "weir", "defy", "norm", "tull", "whiz", "gill", "ward", "crag", "when", "mill", "firs", + "sans", "flue", "reid", "ekes", "jain", "mutt", "hems", "laps", "piss", "pall", "rowe", "prey", + "cull", "knew", "size", "wets", "hurl", "wont", "suva", "girt", "prys", "prow", "warn", "naps", + "gong", "thru", "livy", "boar", "sade", "amok", "vice", "slat", "emir", "jade", "karl", "loyd", + "cerf", "bess", "loss", "rums", "lats", "bode", "subs", "muss", "maim", "kits", "thin", "york", + "punt", "gays", "alpo", "aids", "drag", "eras", "mats", "pyre", "clot", "step", "oath", "lout", + "wary", "carp", "hums", "tang", "pout", "whip", "fled", "omar", "such", "kano", "jake", "stan", + "loop", "fuss", "mini", "byrd", "exit", "fizz", "lire", "emil", "prop", "noes", "awed", "gift", + "soli", "sale", "gage", "orin", "slur", "limp", "saar", "arks", "mast", "gnat", "port", "into", + "geed", "pave", "awls", "cent", "cunt", "full", "dint", "hank", "mate", "coin", "tars", "scud", + "veer", "coax", "bops", "uris", "loom", "shod", "crib", "lids", "drys", "fish", "edit", "dick", + "erna", "else", "hahs", "alga", "moho", "wire", "fora", "tums", "ruth", "bets", "duns", "mold", + "mush", "swop", "ruby", "bolt", "nave", "kite", "ahem", "brad", "tern", "nips", "whew", "bait", + "ooze", "gino", "yuck", "drum", "shoe", "lobe", "dusk", "cult", "paws", "anew", "dado", "nook", + "half", "lams", "rich", "cato", "java", "kemp", "vain", "fees", "sham", "auks", "gish", "fire", + "elam", "salt", "sour", "loth", "whit", "yogi", "shes", "scam", "yous", "lucy", "inez", "geld", + "whig", "thee", "kelp", "loaf", "harm", "tomb", "ever", "airs", "page", "laud", "stun", "paid", + "goop", "cobs", "judy", "grab", "doha", "crew", "item", "fogs", "tong", "blip", "vest", "bran", + "wend", "bawl", "feel", "jets", "mixt", "tell", "dire", "devi", "milo", "deng", "yews", "weak", + "mark", "doug", "fare", "rigs", "poke", "hies", "sian", "suez", "quip", "kens", "lass", "zips", + "elva", "brat", "cosy", "teri", "hull", "spun", "russ", "pupa", "weed", "pulp", "main", "grim", + "hone", "cord", "barf", "olav", "gaps", "rote", "wilt", "lars", "roll", "balm", "jana", "give", + "eire", "faun", "suck", "kegs", "nita", "weer", "tush", "spry", "loge", "nays", "heir", "dope", + "roar", "peep", "nags", "ates", "bane", "seas", "sign", "fred", "they", "lien", "kiev", "fops", + "said", "lawn", "lind", "miff", "mass", "trig", "sins", "furl", "ruin", "sent", "cray", "maya", + "clog", "puns", "silk", "axis", "grog", "jots", "dyer", "mope", "rand", "vend", "keen", "chou", + "dose", "rain", "eats", "sped", "maui", "evan", "time", "todd", "skit", "lief", "sops", "outs", + "moot", "faze", "biro", "gook", "fill", "oval", "skew", "veil", "born", "slob", "hyde", "twin", + "eloy", "beat", "ergs", "sure", "kobe", "eggo", "hens", "jive", "flax", "mons", "dunk", "yest", + "begs", "dial", "lodz", "burp", "pile", "much", "dock", "rene", "sago", "racy", "have", "yalu", + "glow", "move", "peps", "hods", "kins", "salk", "hand", "cons", "dare", "myra", "sega", "type", + "mari", "pelt", "hula", "gulf", "jugs", "flay", "fest", "spat", "toms", "zeno", "taps", "deny", + "swag", "afro", "baud", "jabs", "smut", "egos", "lara", "toes", "song", "fray", "luis", "brut", + "olen", "mere", "ruff", "slum", "glad", "buds", "silt", "rued", "gelt", "hive", "teem", "ides", + "sink", "ands", "wisp", "omen", "lyre", "yuks", "curb", "loam", "darn", "liar", "pugs", "pane", + "carl", "sang", "scar", "zeds", "claw", "berg", "hits", "mile", "lite", "khan", "erik", "slug", + "loon", "dena", "ruse", "talk", "tusk", "gaol", "tads", "beds", "sock", "howe", "gave", "snob", + "ahab", "part", "meir", "jell", "stir", "tels", "spit", "hash", "omit", "jinx", "lyra", "puck", + "laue", "beep", "eros", "owed", "cede", "brew", "slue", "mitt", "jest", "lynx", "wads", "gena", + "dank", "volt", "gray", "pony", "veld", "bask", "fens", "argo", "work", "taxi", "afar", "boon", + "lube", "pass", "lazy", "mist", "blot", "mach", "poky", "rams", "sits", "rend", "dome", "pray", + "duck", "hers", "lure", "keep", "gory", "chat", "runt", "jams", "lays", "posy", "bats", "hoff", + "rock", "keri", "raul", "yves", "lama", "ramp", "vote", "jody", "pock", "gist", "sass", "iago", + "coos", "rank", "lowe", "vows", "koch", "taco", "jinn", "juno", "rape", "band", "aces", "goal", + "huck", "lila", "tuft", "swan", "blab", "leda", "gems", "hide", "tack", "porn", "scum", "frat", + "plum", "duds", "shad", "arms", "pare", "chin", "gain", "knee", "foot", "line", "dove", "vera", + "jays", "fund", "reno", "skid", "boys", "corn", "gwyn", "sash", "weld", "ruiz", "dior", "jess", + "leaf", "pars", "cote", "zing", "scat", "nice", "dart", "only", "owls", "hike", "trey", "whys", + "ding", "klan", "ross", "barb", "ants", "lean", "dopy", "hock", "tour", "grip", "aldo", "whim", + "prom", "rear", "dins", "duff", "dell", "loch", "lava", "sung", "yank", "thar", "curl", "venn", + "blow", "pomp", "heat", "trap", "dali", "nets", "seen", "gash", "twig", "dads", "emmy", "rhea", + "navy", "haws", "mite", "bows", "alas", "ives", "play", "soon", "doll", "chum", "ajar", "foam", + "call", "puke", "kris", "wily", "came", "ales", "reef", "raid", "diet", "prod", "prut", "loot", + "soar", "coed", "celt", "seam", "dray", "lump", "jags", "nods", "sole", "kink", "peso", "howl", + "cost", "tsar", "uric", "sore", "woes", "sewn", "sake", "cask", "caps", "burl", "tame", "bulk", + "neva", "from", "meet", "webs", "spar", "fuck", "buoy", "wept", "west", "dual", "pica", "sold", + "seed", "gads", "riff", "neck", "deed", "rudy", "drop", "vale", "flit", "romp", "peak", "jape", + "jews", "fain", "dens", "hugo", "elba", "mink", "town", "clam", "feud", "fern", "dung", "newt", + "mime", "deem", "inti", "gigs", "sosa", "lope", "lard", "cara", "smug", "lego", "flex", "doth", + "paar", "moon", "wren", "tale", "kant", "eels", "muck", "toga", "zens", "lops", "duet", "coil", + "gall", "teal", "glib", "muir", "ails", "boer", "them", "rake", "conn", "neat", "frog", "trip", + "coma", "must", "mono", "lira", "craw", "sled", "wear", "toby", "reel", "hips", "nate", "pump", + "mont", "died", "moss", "lair", "jibe", "oils", "pied", "hobs", "cads", "haze", "muse", "cogs", + "figs", "cues", "roes", "whet", "boru", "cozy", "amos", "tans", "news", "hake", "cots", "boas", + "tutu", "wavy", "pipe", "typo", "albs", "boom", "dyke", "wail", "woke", "ware", "rita", "fail", + "slab", "owes", "jane", "rack", "hell", "lags", "mend", "mask", "hume", "wane", "acne", "team", + "holy", "runs", "exes", "dole", "trim", "zola", "trek", "puma", "wacs", "veep", "yaps", "sums", + "lush", "tubs", "most", "witt", "bong", "rule", "hear", "awry", "sots", "nils", "bash", "gasp", + "inch", "pens", "fies", "juts", "pate", "vine", "zulu", "this", "bare", "veal", "josh", "reek", + "ours", "cowl", "club", "farm", "teat", "coat", "dish", "fore", "weft", "exam", "vlad", "floe", + "beak", "lane", "ella", "warp", "goth", "ming", "pits", "rent", "tito", "wish", "amps", "says", + "hawk", "ways", "punk", "nark", "cagy", "east", "paul", "bose", "solo", "teed", "text", "hews", + "snip", "lips", "emit", "orgy", "icon", "tuna", "soul", "kurd", "clod", "calk", "aunt", "bake", + "copy", "acid", "duse", "kiln", "spec", "fans", "bani", "irma", "pads", "batu", "logo", "pack", + "oder", "atop", "funk", "gide", "bede", "bibs", "taut", "guns", "dana", "puff", "lyme", "flat", + "lake", "june", "sets", "gull", "hops", "earn", "clip", "fell", "kama", "seal", "diaz", "cite", + "chew", "cuba", "bury", "yard", "bank", "byes", "apia", "cree", "nosh", "judo", "walk", "tape", + "taro", "boot", "cods", "lade", "cong", "deft", "slim", "jeri", "rile", "park", "aeon", "fact", + "slow", "goff", "cane", "earp", "tart", "does", "acts", "hope", "cant", "buts", "shin", "dude", + "ergo", "mode", "gene", "lept", "chen", "beta", "eden", "pang", "saab", "fang", "whir", "cove", + "perk", "fads", "rugs", "herb", "putt", "nous", "vane", "corm", "stay", "bids", "vela", "roof", + "isms", "sics", "gone", "swum", "wiry", "cram", "rink", "pert", "heap", "sikh", "dais", "cell", + "peel", "nuke", "buss", "rasp", "none", "slut", "bent", "dams", "serb", "dork", "bays", "kale", + "cora", "wake", "welt", "rind", "trot", "sloe", "pity", "rout", "eves", "fats", "furs", "pogo", + "beth", "hued", "edam", "iamb", "glee", "lute", "keel", "airy", "easy", "tire", "rube", "bogy", + "sine", "chop", "rood", "elbe", "mike", "garb", "jill", "gaul", "chit", "dons", "bars", "ride", + "beck", "toad", "make", "head", "suds", "pike", "snot", "swat", "peed", "same", "gaza", "lent", + "gait", "gael", "elks", "hang", "nerf", "rosy", "shut", "glop", "pain", "dion", "deaf", "hero", + "doer", "wost", "wage", "wash", "pats", "narc", "ions", "dice", "quay", "vied", "eons", "case", + "pour", "urns", "reva", "rags", "aden", "bone", "rang", "aura", "iraq", "toot", "rome", "hals", + "megs", "pond", "john", "yeps", "pawl", "warm", "bird", "tint", "jowl", "gibe", "come", "hold", + "pail", "wipe", "bike", "rips", "eery", "kent", "hims", "inks", "fink", "mott", "ices", "macy", + "serf", "keys", "tarp", "cops", "sods", "feet", "tear", "benz", "buys", "colo", "boil", "sews", + "enos", "watt", "pull", "brag", "cork", "save", "mint", "feat", "jamb", "rubs", "roxy", "toys", + "nosy", "yowl", "tamp", "lobs", "foul", "doom", "sown", "pigs", "hemp", "fame", "boor", "cube", + "tops", "loco", "lads", "eyre", "alta", "aged", "flop", "pram", "lesa", "sawn", "plow", "aral", + "load", "lied", "pled", "boob", "bert", "rows", "zits", "rick", "hint", "dido", "fist", "marc", + "wuss", "node", "smog", "nora", "shim", "glut", "bale", "perl", "what", "tort", "meek", "brie", + "bind", "cake", "psst", "dour", "jove", "tree", "chip", "stud", "thou", "mobs", "sows", "opts", + "diva", "perm", "wise", "cuds", "sols", "alan", "mild", "pure", "gail", "wins", "offs", "nile", + "yelp", "minn", "tors", "tran", "homy", "sadr", "erse", "nero", "scab", "finn", "mich", "turd", + "then", "poem", "noun", "oxus", "brow", "door", "saws", "eben", "wart", "wand", "rosa", "left", + "lina", "cabs", "rapt", "olin", "suet", "kalb", "mans", "dawn", "riel", "temp", "chug", "peal", + "drew", "null", "hath", "many", "took", "fond", "gate", "sate", "leak", "zany", "vans", "mart", + "hess", "home", "long", "dirk", "bile", "lace", "moog", "axes", "zone", "fork", "duct", "rico", + "rife", "deep", "tiny", "hugh", "bilk", "waft", "swig", "pans", "with", "kern", "busy", "film", + "lulu", "king", "lord", "veda", "tray", "legs", "soot", "ells", "wasp", "hunt", "earl", "ouch", + "diem", "yell", "pegs", "blvd", "polk", "soda", "zorn", "liza", "slop", "week", "kill", "rusk", + "eric", "sump", "haul", "rims", "crop", "blob", "face", "bins", "read", "care", "pele", "ritz", + "beau", "golf", "drip", "dike", "stab", "jibs", "hove", "junk", "hoax", "tats", "fief", "quad", + "peat", "ream", "hats", "root", "flak", "grit", "clap", "pugh", "bosh", "lock", "mute", "crow", + "iced", "lisa", "bela", "fems", "oxes", "vies", "gybe", "huff", "bull", "cuss", "sunk", "pups", + "fobs", "turf", "sect", "atom", "debt", "sane", "writ", "anon", "mayo", "aria", "seer", "thor", + "brim", "gawk", "jack", "jazz", "menu", "yolk", "surf", "libs", "lets", "bans", "toil", "open", + "aced", "poor", "mess", "wham", "fran", "gina", "dote", "love", "mood", "pale", "reps", "ines", + "shot", "alar", "twit", "site", "dill", "yoga", "sear", "vamp", "abel", "lieu", "cuff", "orbs", + "rose", "tank", "gape", "guam", "adar", "vole", "your", "dean", "dear", "hebe", "crab", "hump", + "mole", "vase", "rode", "dash", "sera", "balk", "lela", "inca", "gaea", "bush", "loud", "pies", + "aide", "blew", "mien", "side", "kerr", "ring", "tess", "prep", "rant", "lugs", "hobo", "joke", + "odds", "yule", "aida", "true", "pone", "lode", "nona", "weep", "coda", "elmo", "skim", "wink", + "bras", "pier", "bung", "pets", "tabs", "ryan", "jock", "body", "sofa", "joey", "zion", "mace", + "kick", "vile", "leno", "bali", "fart", "that", "redo", "ills", "jogs", "pent", "drub", "slaw", + "tide", "lena", "seep", "gyps", "wave", "amid", "fear", "ties", "flan", "wimp", "kali", "shun", + "crap", "sage", "rune", "logs", "cain", "digs", "abut", "obit", "paps", "rids", "fair", "hack", + "huns", "road", "caws", "curt", "jute", "fisk", "fowl", "duty", "holt", "miss", "rude", "vito", + "baal", "ural", "mann", "mind", "belt", "clem", "last", "musk", "roam", "abed", "days", "bore", + "fuze", "fall", "pict", "dump", "dies", "fiat", "vent", "pork", "eyed", "docs", "rive", "spas", + "rope", "ariz", "tout", "game", "jump", "blur", "anti", "lisp", "turn", "sand", "food", "moos", + "hoop", "saul", "arch", "fury", "rise", "diss", "hubs", "burs", "grid", "ilks", "suns", "flea", + "soil", "lung", "want", "nola", "fins", "thud", "kidd", "juan", "heps", "nape", "rash", "burt", + "bump", "tots", "brit", "mums", "bole", "shah", "tees", "skip", "limb", "umps", "ache", "arcs", + "raft", "halo", "luce", "bahs", "leta", "conk", "duos", "siva", "went", "peek", "sulk", "reap", + "free", "dubs", "lang", "toto", "hasp", "ball", "rats", "nair", "myst", "wang", "snug", "nash", + "laos", "ante", "opal", "tina", "pore", "bite", "haas", "myth", "yugo", "foci", "dent", "bade", + "pear", "mods", "auto", "shop", "etch", "lyly", "curs", "aron", "slew", "tyro", "sack", "wade", + "clio", "gyro", "butt", "icky", "char", "itch", "halt", "gals", "yang", "tend", "pact", "bees", + "suit", "puny", "hows", "nina", "brno", "oops", "lick", "sons", "kilo", "bust", "nome", "mona", + "dull", "join", "hour", "papa", "stag", "bern", "wove", "lull", "slip", "laze", "roil", "alto", + "bath", "buck", "alma", "anus", "evil", "dumb", "oreo", "rare", "near", "cure", "isis", "hill", + "kyle", "pace", "comb", "nits", "flip", "clop", "mort", "thea", "wall", "kiel", "judd", "coop", + "dave", "very", "amie", "blah", "flub", "talc", "bold", "fogy", "idea", "prof", "horn", "shoo", + "aped", "pins", "helm", "wees", "beer", "womb", "clue", "alba", "aloe", "fine", "bard", "limo", + "shaw", "pint", "swim", "dust", "indy", "hale", "cats", "troy", "wens", "luke", "vern", "deli", + "both", "brig", "daub", "sara", "sued", "bier", "noel", "olga", "dupe", "look", "pisa", "knox", + "murk", "dame", "matt", "gold", "jame", "toge", "luck", "peck", "tass", "calf", "pill", "wore", + "wadi", "thur", "parr", "maul", "tzar", "ones", "lees", "dark", "fake", "bast", "zoom", "here", + "moro", "wine", "bums", "cows", "jean", "palm", "fume", "plop", "help", "tuba", "leap", "cans", + "back", "avid", "lice", "lust", "polo", "dory", "stew", "kate", "rama", "coke", "bled", "mugs", + "ajax", "arts", "drug", "pena", "cody", "hole", "sean", "deck", "guts", "kong", "bate", "pitt", + "como", "lyle", "siam", "rook", "baby", "jigs", "bret", "bark", "lori", "reba", "sups", "made", + "buzz", "gnaw", "alps", "clay", "post", "viol", "dina", "card", "lana", "doff", "yups", "tons", + "live", "kids", "pair", "yawl", "name", "oven", "sirs", "gyms", "prig", "down", "leos", "noon", + "nibs", "cook", "safe", "cobb", "raja", "awes", "sari", "nerd", "fold", "lots", "pete", "deal", + "bias", "zeal", "girl", "rage", "cool", "gout", "whey", "soak", "thaw", "bear", "wing", "nagy", + "well", "oink", "sven", "kurt", "etna", "held", "wood", "high", "feta", "twee", "ford", "cave", + "knot", "tory", "ibis", "yaks", "vets", "foxy", "sank", "cone", "pius", "tall", "seem", "wool", + "flap", "gird", "lore", "coot", "mewl", "sere", "real", "puts", "sell", "nuts", "foil", "lilt", + "saga", "heft", "dyed", "goat", "spew", "daze", "frye", "adds", "glen", "tojo", "pixy", "gobi", + "stop", "tile", "hiss", "shed", "hahn", "baku", "ahas", "sill", "swap", "also", "carr", "manx", + "lime", "debs", "moat", "eked", "bola", "pods", "coon", "lacy", "tube", "minx", "buff", "pres", + "clew", "gaff", "flee", "burn", "whom", "cola", "fret", "purl", "wick", "wigs", "donn", "guys", + "toni", "oxen", "wite", "vial", "spam", "huts", "vats", "lima", "core", "eula", "thad", "peon", + "erie", "oats", "boyd", "cued", "olaf", "tams", "secs", "urey", "wile", "penn", "bred", "rill", + "vary", "sues", "mail", "feds", "aves", "code", "beam", "reed", "neil", "hark", "pols", "gris", + "gods", "mesa", "test", "coup", "heed", "dora", "hied", "tune", "doze", "pews", "oaks", "bloc", + "tips", "maid", "goof", "four", "woof", "silo", "bray", "zest", "kiss", "yong", "file", "hilt", + "iris", "tuns", "lily", "ears", "pant", "jury", "taft", "data", "gild", "pick", "kook", "colt", + "bohr", "anal", "asps", "babe", "bach", "mash", "biko", "bowl", "huey", "jilt", "goes", "guff", + "bend", "nike", "tami", "gosh", "tike", "gees", "urge", "path", "bony", "jude", "lynn", "lois", + "teas", "dunn", "elul", "bonn", "moms", "bugs", "slay", "yeah", "loan", "hulk", "lows", "damn", + "nell", "jung", "avis", "mane", "waco", "loin", "knob", "tyke", "anna", "hire", "luau", "tidy", + "nuns", "pots", "quid", "exec", "hans", "hera", "hush", "shag", "scot", "moan", "wald", "ursa", + "lorn", "hunk", "loft", "yore", "alum", "mows", "slog", "emma", "spud", "rice", "worn", "erma", + "need", "bags", "lark", "kirk", "pooh", "dyes", "area", "dime", "luvs", "foch", "refs", "cast", + "alit", "tugs", "even", "role", "toed", "caph", "nigh", "sony", "bide", "robs", "folk", "daft", + "past", "blue", "flaw", "sana", "fits", "barr", "riot", "dots", "lamp", "cock", "fibs", "harp", + "tent", "hate", "mali", "togs", "gear", "tues", "bass", "pros", "numb", "emus", "hare", "fate", + "wife", "mean", "pink", "dune", "ares", "dine", "oily", "tony", "czar", "spay", "push", "glum", + "till", "moth", "glue", "dive", "scad", "pops", "woks", "andy", "leah", "cusp", "hair", "alex", + "vibe", "bulb", "boll", "firm", "joys", "tara", "cole", "levy", "owen", "chow", "rump", "jail", + "lapp", "beet", "slap", "kith", "more", "maps", "bond", "hick", "opus", "rust", "wist", "shat", + "phil", "snow", "lott", "lora", "cary", "mote", "rift", "oust", "klee", "goad", "pith", "heep", + "lupe", "ivan", "mimi", "bald", "fuse", "cuts", "lens", "leer", "eyry", "know", "razz", "tare", + "pals", "geek", "greg", "teen", "clef", "wags", "weal", "each", "haft", "nova", "waif", "rate", + "katy", "yale", "dale", "leas", "axum", "quiz", "pawn", "fend", "capt", "laws", "city", "chad", + "coal", "nail", "zaps", "sort", "loci", "less", "spur", "note", "foes", "fags", "gulp", "snap", + "bogs", "wrap", "dane", "melt", "ease", "felt", "shea", "calm", "star", "swam", "aery", "year", + "plan", "odin", "curd", "mira", "mops", "shit", "davy", "apes", "inky", "hues", "lome", "bits", + "vila", "show", "best", "mice", "gins", "next", "roan", "ymir", "mars", "oman", "wild", "heal", + "plus", "erin", "rave", "robe", "fast", "hutu", "aver", "jodi", "alms", "yams", "zero", "revs", + "wean", "chic", "self", "jeep", "jobs", "waxy", "duel", "seek", "spot", "raps", "pimp", "adan", + "slam", "tool", "morn", "futz", "ewes", "errs", "knit", "rung", "kans", "muff", "huhs", "tows", + "lest", "meal", "azov", "gnus", "agar", "sips", "sway", "otis", "tone", "tate", "epic", "trio", + "tics", "fade", "lear", "owns", "robt", "weds", "five", "lyon", "terr", "arno", "mama", "grey", + "disk", "sept", "sire", "bart", "saps", "whoa", "turk", "stow", "pyle", "joni", "zinc", "negs", + "task", "leif", "ribs", "malt", "nine", "bunt", "grin", "dona", "nope", "hams", "some", "molt", + "smit", "sacs", "joan", "slav", "lady", "base", "heck", "list", "take", "herd", "will", "nubs", + "burg", "hugs", "peru", "coif", "zoos", "nick", "idol", "levi", "grub", "roth", "adam", "elma", + "tags", "tote", "yaws", "cali", "mete", "lula", "cubs", "prim", "luna", "jolt", "span", "pita", + "dodo", "puss", "deer", "term", "dolt", "goon", "gary", "yarn", "aims", "just", "rena", "tine", + "cyst", "meld", "loki", "wong", "were", "hung", "maze", "arid", "cars", "wolf", "marx", "faye", + "eave", "raga", "flow", "neal", "lone", "anne", "cage", "tied", "tilt", "soto", "opel", "date", + "buns", "dorm", "kane", "akin", "ewer", "drab", "thai", "jeer", "grad", "berm", "rods", "saki", + "grus", "vast", "late", "lint", "mule", "risk", "labs", "snit", "gala", "find", "spin", "ired", + "slot", "oafs", "lies", "mews", "wino", "milk", "bout", "onus", "tram", "jaws", "peas", "cleo", + "seat", "gums", "cold", "vang", "dewy", "hood", "rush", "mack", "yuan", "odes", "boos", "jami", + "mare", "plot", "swab", "borg", "hays", "form", "mesh", "mani", "fife", "good", "gram", "lion", + "myna", "moor", "skin", "posh", "burr", "rime", "done", "ruts", "pays", "stem", "ting", "arty", + "slag", "iron", "ayes", "stub", "oral", "gets", "chid", "yens", "snub", "ages", "wide", "bail", + "verb", "lamb", "bomb", "army", "yoke", "gels", "tits", "bork", "mils", "nary", "barn", "hype", + "odom", "avon", "hewn", "rios", "cams", "tact", "boss", "oleo", "duke", "eris", "gwen", "elms", + "deon", "sims", "quit", "nest", "font", "dues", "yeas", "zeta", "bevy", "gent", "torn", "cups", + "worm", "baum", "axon", "purr", "vise", "grew", "govs", "meat", "chef", "rest", "lame"])) diff --git a/Week_03/id_3/dfs/LeetCode_127_3_v2.py b/Week_03/id_3/dfs/LeetCode_127_3_v2.py new file mode 100644 index 00000000..d3f5c926 --- /dev/null +++ b/Week_03/id_3/dfs/LeetCode_127_3_v2.py @@ -0,0 +1,59 @@ +""" +似乎DFS不行, 时间不受控制,试试双向BFS +""" + + +class Solution: + def ladderLength(self, begin, end, word_list) -> int: + if not begin or not end or not word_list or end not in word_list: + return 0 + + word_graph = {} + for w in word_list: + for i in range(len(w)): + k = w[0:i] + '*' + w[i+1:] + arr = word_graph.get(k, []) + arr.append(w) + word_graph[k] = arr + + begin_set = set() + end_set = set([end]) + count = 0 + begin_queue = [begin] + end_queue = [end] + + while begin_queue or end_queue: + if count % 2 == 0: + queue = begin_queue + cur_set, target_set = begin_set, end_set + else: + queue = end_queue + cur_set, target_set = end_set, begin_set + + _queue = [] + for w in queue: + for i in range(len(w)): + k = w[0:i] + '*' + w[i+1:] + if k not in word_graph: + continue + for sw in word_graph[k]: + if sw in cur_set: + continue + if sw in target_set: + return count + 2 + else: + cur_set.add(sw) + _queue.append(sw) + if count % 2 == 0: + begin_queue = _queue + else: + end_queue = _queue + count += 1 + + return 0 + + +s = Solution() +print(s.ladderLength("hit", "cog", ["hot", "dot", "dog", "lot", "log", "cog"])) +print(s.ladderLength("hit", "cog", ["hot", "dot", "dog", "lot"])) +print(s.ladderLength("hot", "dog", ["hot", "dog"])) diff --git a/Week_03/id_3/dfs/LeetCode_329_3_v1.py b/Week_03/id_3/dfs/LeetCode_329_3_v1.py new file mode 100644 index 00000000..8a9dd33c --- /dev/null +++ b/Week_03/id_3/dfs/LeetCode_329_3_v1.py @@ -0,0 +1,52 @@ +""" +矩阵中的最长递增路径 +思路:DFS + 缓存 +DFS过程由于需求是数值递增,所以在下钻到过程中不会出现回路,不需要缓存去重。 +由于需要找到全局最优解,所以也不需要依赖贪心。 +""" + + +class Solution: + def longestIncreasingPath(self, matrix): + if not matrix: + return 0 + col_length = len(matrix) + row_length = len(matrix[0]) + cache = [ + [0] * row_length for _ in range(col_length) + ] + r = 0 + for i in range(col_length): + for j in range(row_length): + r = max(r, self.dfs(matrix, cache, i, j, col_length, row_length, None)) + + return r + + def dfs(self, matrix, cache, i, j, col_length, row_length, prev): + if i < 0 or i >= col_length or j < 0 or j >= row_length: + return 0 + + curr = matrix[i][j] + if prev is not None and prev >= curr: + return 0 + + if cache[i][j]: + return cache[i][j] + + r = 1 + max( + self.dfs(matrix, cache, i+1, j, col_length, row_length, curr), + self.dfs(matrix, cache, i-1, j, col_length, row_length, curr), + self.dfs(matrix, cache, i, j+1, col_length, row_length, curr), + self.dfs(matrix, cache, i, j-1, col_length, row_length, curr), + ) + cache[i][j] = r + return r + + +s = Solution() +print(s.longestIncreasingPath( +[ + [9, 9, 4], + [6, 6, 8], + [2, 1, 1] +])) diff --git a/Week_03/id_3/dfs/LeetCode_529_3_v1.py b/Week_03/id_3/dfs/LeetCode_529_3_v1.py new file mode 100644 index 00000000..d3ebd1b3 --- /dev/null +++ b/Week_03/id_3/dfs/LeetCode_529_3_v1.py @@ -0,0 +1,76 @@ +""" +典型二维数组DFS +退出条件:当前节点是雷或者出界 +下钻条件:当前节点不是雷,且周边没有雷,则下钻周边8个节点 +""" +DIRECT_LIST = [ + (-1, 0), + (-1, 1), + (0, 1), + (1, 1), + (1, 0), + (1, -1), + (0, -1), + (-1, -1), +] + + +class Solution: + def updateBoard(self, board, click): + if not board: + return board + + i, j = click + v = board[i][j] + if v == 'M': + board[i][j] = 'X' + return board + self.dfs(board, i, j) + return board + + def dfs(self, board, i, j): + if self.check_out_border(board, i, j): + return + v = board[i][j] + if v != 'E': + return + num = self.check_num(board, i, j) + if num: + board[i][j] = str(num) + else: + board[i][j] = 'B' + for _i, _j in DIRECT_LIST: + __i = i + _i + __j = j + _j + self.dfs(board, __i, __j) + + def check_num(self, board, i, j): + num = 0 + for _i, _j in DIRECT_LIST: + __i = i + _i + __j = j + _j + if self.check_out_border(board, __i, __j): + continue + if board[__i][__j] == 'M': + num += 1 + return num + + def check_out_border(self, board, i, j): + return i < 0 or j < 0 or i >= len(board) or j >= len(board[0]) + + +def check(board, click, result): + s = Solution() + r = s.updateBoard(board, click) + print(r) + print(r == result) + + +check([['E', 'E', 'E', 'E', 'E'], + ['E', 'E', 'M', 'E', 'E'], + ['E', 'E', 'E', 'E', 'E'], + ['E', 'E', 'E', 'E', 'E']], [3, 0], + [['B', '1', 'E', '1', 'B'], + ['B', '1', 'M', '1', 'B'], + ['B', '1', '1', '1', 'B'], + ['B', 'B', 'B', 'B', 'B']]) diff --git a/Week_03/id_3/graph/LeetCode_200_3.py b/Week_03/id_3/graph/LeetCode_200_3.py new file mode 100644 index 00000000..7f480dd3 --- /dev/null +++ b/Week_03/id_3/graph/LeetCode_200_3.py @@ -0,0 +1,70 @@ +""" +grid为二维数组 +给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量。 +一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。 + +输入: +11110 +11010 +11000 +00000 +输出: 1 + +输入: +11000 +11000 +00100 +00011 +输出: 3 +""" + + +class Solution: + def numIslands(self, grid) -> int: + if not grid: + return 0 + + width = len(grid[0]) + height = len(grid) + + count = 0 + for i in range(height): + arr = grid[i] + for j in range(width): + ceil = arr[j] + if ceil == '1': + count += 1 + self.dfs(grid, i, j, width, height) + return count + + def dfs(self, grid, i, j, width, height): + if i < 0 or i >= height or j < 0 or j >= width: + return + if grid[i][j] == '0': + return + grid[i][j] = '0' + self.dfs(grid, i + 1, j, width, height) + self.dfs(grid, i - 1, j, width, height) + self.dfs(grid, i, j + 1, width, height) + self.dfs(grid, i, j - 1, width, height) + + +s = Solution() + +print(s.numIslands( + [ + ["1", "1", "1", "1", "0"], + ["1", "1", "0", "1", "0"], + ["1", "1", "0", "0", "0"], + ["0", "0", "0", "0", "0"] + ] +)) + +print(s.numIslands( + [ + ["1", "1", "0", "0", "0"], + ["1", "1", "0", "0", "0"], + ["0", "0", "1", "0", "0"], + ["0", "0", "0", "1", "1"] + ] +)) diff --git a/Week_03/id_3/graph/LeetCode_207_3_v1.py b/Week_03/id_3/graph/LeetCode_207_3_v1.py new file mode 100644 index 00000000..1a83c9a7 --- /dev/null +++ b/Week_03/id_3/graph/LeetCode_207_3_v1.py @@ -0,0 +1,43 @@ +""" +经典的拓扑排序 +numCourses 课程数 +prerequisites 课程依赖关系 也就是边列表 + +在拓扑排序过程中如果无法完成则说明图中存在环 也就是返回False +例如图中存在 (0,1) (1,2) (2,0) 形成一个环 +则三个节点0,1,2的入度都不小于1,在进行拓扑排序时,三个节点由于环的存在,不会出现有节点降为0的情况。 + +BFS实现 +""" + + +class Solution: + def canFinish(self, numCourses, prerequisites): + queue = [] + node_list = [[] for _ in range(numCourses)] + topology_list = [0 for _ in range(numCourses)] + + for e in prerequisites: + node_list[e[1]].append(e[0]) + topology_list[e[0]] += 1 + + for i, n in enumerate(topology_list): + if n == 0: + queue.append(i) + + while queue: + node = queue.pop() + for sn in node_list[node]: + topology_list[sn] -= 1 + if topology_list[sn] == 0: + queue.insert(0, sn) + + for count in topology_list: + if count != 0: + return False + return True + + +s = Solution() +print(s.canFinish(2, [[1, 0]])) +print(s.canFinish(2, [[1, 0], [0, 1]])) diff --git a/Week_03/id_3/graph/LeetCode_207_3_v2.py b/Week_03/id_3/graph/LeetCode_207_3_v2.py new file mode 100644 index 00000000..5420fea2 --- /dev/null +++ b/Week_03/id_3/graph/LeetCode_207_3_v2.py @@ -0,0 +1,44 @@ +""" +经典的拓扑排序 +numCourses 课程数 +prerequisites 课程依赖关系 也就是边列表 + +在拓扑排序过程中如果无法完成则说明图中存在环 也就是返回False +例如图中存在 (0,1) (1,2) (2,0) 形成一个环 +则三个节点0,1,2的入度都不小于1,在进行拓扑排序时,三个节点由于环的存在,不会出现有节点降为0的情况。 + +DFS实现 +""" + + +class Solution: + def canFinish(self, numCourses, prerequisites): + node_list = [[] for _ in range(numCourses)] + topology_list = [0 for _ in range(numCourses)] + + for e in prerequisites: + node_list[e[1]].append(e[0]) + topology_list[e[0]] += 1 + + for i, n in list(filter(lambda e: not e[1], enumerate(topology_list))): + self.dfs(i, node_list, topology_list) + + for count in topology_list: + if count != 0: + return False + return True + + def dfs(self, node, node_list, topology_list): + for sn in node_list[node]: + topology_list[sn] -= 1 + if topology_list[sn] == 0: + self.dfs(sn, node_list, topology_list) + + +s = Solution() +# print(s.canFinish(2, [[1, 0]])) +# print(s.canFinish(2, [[1, 0], [0, 1]])) +# print(s.canFinish(3, [[0, 1], [0, 2], [1, 2]])) +# print(s.canFinish(3, [[1, 0], [2, 0]])) +# print(s.canFinish(3, [[0, 1], [0, 2], [1, 2]])) +print(s.canFinish(4, [[1, 0], [2, 1], [0, 2], [2, 3]])) diff --git a/Week_03/id_3/graph/LeetCode_210_3_v1.py b/Week_03/id_3/graph/LeetCode_210_3_v1.py new file mode 100644 index 00000000..2588db30 --- /dev/null +++ b/Week_03/id_3/graph/LeetCode_210_3_v1.py @@ -0,0 +1,34 @@ +""" +经典的拓扑排序 +numCourses 课程数 +prerequisites 课程依赖关系 也就是边列表 +BFS +""" + + +class Solution: + def findOrder(self, numCourses, prerequisites): + queue = [] + node_list = [[] for _ in range(numCourses)] + topology_list = [0 for _ in range(numCourses)] + + for e in prerequisites: + node_list[e[1]].append(e[0]) + topology_list[e[0]] += 1 + + for i, n in enumerate(topology_list): + if n == 0: + queue.append(i) + + results = [] + while queue: + node = queue.pop() + results.append(node) + for sn in node_list[node]: + topology_list[sn] -= 1 + if topology_list[sn] == 0: + queue.insert(0, sn) + + if len(results) != numCourses: + return [] + return results diff --git a/Week_03/id_3/graph/LeetCode_210_3_v2.py b/Week_03/id_3/graph/LeetCode_210_3_v2.py new file mode 100644 index 00000000..f4a13554 --- /dev/null +++ b/Week_03/id_3/graph/LeetCode_210_3_v2.py @@ -0,0 +1,41 @@ +""" +经典的拓扑排序 +numCourses 课程数 +prerequisites 课程依赖关系 也就是边列表 +DFS + +由于我使用的是从起点向后下钻,当遇到新的入度为0的节点才下钻,所以不会出现死循环的问题。 +如果是从后向前,或者不判断入度数量,可能就需要一个visited的缓存来判断是否在迭代过程中出现了环。 +""" + + +class Solution: + def findOrder(self, numCourses, prerequisites): + node_list = list([] for _ in range(numCourses)) + topology_list = list(0 for _ in range(numCourses)) + + for t, s in prerequisites: + node_list[s].append(t) + topology_list[t] += 1 + + results = [] + for e in list(filter(lambda e: e[1] == 0, enumerate(topology_list))): + results.append(e[0]) + self.dfs(e[0], node_list, topology_list, results) + + if len(results) != numCourses: + return [] + return results + + def dfs(self, node, node_list, topology_list, results): + for sn in node_list[node]: + topology_list[sn] -= 1 + if topology_list[sn] == 0: + results.append(sn) + self.dfs(sn, node_list, topology_list, results) + + +s = Solution() +print(s.findOrder(4, [[2, 0], [1, 0], [3, 1], [3, 2], [1, 3]])) +print(s.findOrder(7, [[1, 0], [0, 3], [0, 2], [3, 2], [2, 5], [4, 5], [5, 6], [2, 4]])) +print(s.findOrder(3, [[1, 0], [1, 2], [0, 1]])) diff --git a/Week_03/id_3/heap/LeetCode_295_3_v1.py b/Week_03/id_3/heap/LeetCode_295_3_v1.py new file mode 100644 index 00000000..af68d50e --- /dev/null +++ b/Week_03/id_3/heap/LeetCode_295_3_v1.py @@ -0,0 +1,50 @@ +import heapq + + +class MedianFinder: + """ + 用最大最小双堆实现 + """ + + def __init__(self): + self.min_heap = [] + self.max_heap = [] + + def addNum(self, num: int) -> None: + # >= 其实不是最优的写法 但是大差不差 理论上如果存在相等的值,可以判断哪个堆数量少 + # 优雅的写法不是最高效的,但是可以忽略不计 + if not self.min_heap or -num >= self.min_heap[0]: + heapq.heappush(self.min_heap, -num) + else: + heapq.heappush(self.max_heap, num) + if abs(len(self.min_heap) - len(self.max_heap)) == 2: + if len(self.min_heap) > len(self.max_heap): + heapq.heappush(self.max_heap, -heapq.heappop(self.min_heap)) + else: + heapq.heappush(self.min_heap, -heapq.heappop(self.max_heap)) + + def findMedian(self) -> float: + if not self.min_heap and not self.max_heap: + return None + if len(self.min_heap) == len(self.max_heap): + return (-self.min_heap[0] + self.max_heap[0])/2 + if len(self.min_heap) > len(self.max_heap): + return -self.min_heap[0] + else: + return self.max_heap[0] + + +s = MedianFinder() +s.addNum(1) +s.addNum(2) +print(s.findMedian(), s.findMedian() == 1.5) +s.addNum(3) +print(s.findMedian(), s.findMedian() == 2) +s.addNum(0) +print(s.findMedian(), s.findMedian() == 1.5) +s.addNum(9) +print(s.findMedian(), s.findMedian() == 2) +s.addNum(6) +print(s.findMedian(), s.findMedian() == 2.5) +s.addNum(7) +print(s.findMedian(), s.findMedian() == 3) diff --git a/Week_03/id_3/heap/LeetCode_295_3_v2.py b/Week_03/id_3/heap/LeetCode_295_3_v2.py new file mode 100644 index 00000000..928004a4 --- /dev/null +++ b/Week_03/id_3/heap/LeetCode_295_3_v2.py @@ -0,0 +1,21 @@ +class MedianFinder: + """ + 尝试跳表实现 + """ + + def __init__(self): + pass + + def addNum(self, num: int) -> None: + pass + + def findMedian(self) -> float: + pass + + +s = MedianFinder() +s.addNum(1) +s.addNum(2) +print(s.findMedian(), s.findMedian() == 1.5) +s.addNum(3) +print(s.findMedian(), s.findMedian() == 2) diff --git a/Week_03/id_3/heap/LeetCode_703_3.py b/Week_03/id_3/heap/LeetCode_703_3.py new file mode 100644 index 00000000..3879979b --- /dev/null +++ b/Week_03/id_3/heap/LeetCode_703_3.py @@ -0,0 +1,31 @@ +import heapq + + +class KthLargest: + + def __init__(self, k: int, nums): + self.heap = [] + self.k = k + for v in nums: + self.add(v) + + def add(self, val: int): + if len(self.heap) < self.k: + heapq.heappush(self.heap, val) + elif val > self.heap[0]: + heapq.heapreplace(self.heap, val) + + return self.heap[0] + + +kthLargest = KthLargest(3, [4, 5, 8, 2]) +print(kthLargest.add(3) == 4) +print(kthLargest.add(5) == 5) +print(kthLargest.add(10) == 5) +print(kthLargest.add(9) == 8) +print(kthLargest.add(4) == 8) + +h = heapq.nlargest(3, [1, 2, 3, 4, 5]) +heapq.heappush(h, 9) +print(h) + diff --git a/Week_03/id_30/LeetCode_200_030.cpp b/Week_03/id_30/LeetCode_200_030.cpp new file mode 100644 index 00000000..9e80c3a2 --- /dev/null +++ b/Week_03/id_30/LeetCode_200_030.cpp @@ -0,0 +1,34 @@ +class Solution { +public: + vector> visited; + int dx[4] = { 1, -1, 0, 0 }; + int dy[4] = { 0, 0, 1, -1 }; + int numIslands(vector>& grid) { + int numIslands = 0; + for (int i = 0; i < grid.size(); ++i) + { + for (int j = 0; j < grid[i].size(); ++j) + { + if (grid[i][j] == '1') + { + dfsIslands(grid, i, j); + ++numIslands; + } + } + } + + return numIslands; + } + + void dfsIslands(vector>& grid, int x, int y) + { + if (x < 0 || x >= grid.size() || y < 0 || y >= grid[0].size()) return; + if (grid[x][y] == '0') return; + + grid[x][y] = '0'; + for (int i = 0; i < 4; ++i) + { + dfsIslands(grid, x + dx[i], y + dy[i]); + } + } +}; \ No newline at end of file diff --git a/Week_03/id_30/LeetCode_210_030.cpp b/Week_03/id_30/LeetCode_210_030.cpp new file mode 100644 index 00000000..e0417719 --- /dev/null +++ b/Week_03/id_30/LeetCode_210_030.cpp @@ -0,0 +1,46 @@ +class Solution { +public: + struct CourseRelations + { + CourseRelations() : count(0) { } + int count; + vector nextCourses; + }; + vector findOrder(int numCourses, vector>& prerequisites) { + vector crVec(numCourses); + for (int i = 0; i < prerequisites.size(); ++i) + { + int preCourse = prerequisites[i][1]; + int postCourse = prerequisites[i][0]; + ++crVec[postCourse].count; + crVec[preCourse].nextCourses.push_back(postCourse); + } + queue selectedCourses; + for (int i = 0; i < crVec.size(); ++i) + { + if (crVec[i].count == 0) + { + selectedCourses.push(i); + } + } + vector orders; + while(!selectedCourses.empty()) + { + int selectedCourse = selectedCourses.front(); + selectedCourses.pop(); + orders.push_back(selectedCourse); + for (int course : crVec[selectedCourse].nextCourses) + { + if (--crVec[course].count == 0) + { + selectedCourses.push(course); + } + } + } + if (orders.size() < numCourses) + { + orders.clear(); + } + return orders; + } +}; \ No newline at end of file diff --git a/Week_03/id_30/LeetCode_529_030.cpp b/Week_03/id_30/LeetCode_529_030.cpp new file mode 100644 index 00000000..a84d83be --- /dev/null +++ b/Week_03/id_30/LeetCode_529_030.cpp @@ -0,0 +1,56 @@ +class Solution { +public: + static const int DIRS = 8; + int dx[DIRS] = { -1, -1, -1, 0, 0, 1, 1, 1 }; + int dy[DIRS] = { -1, 0, 1, -1, 1, -1, 0, 1 }; + int GetMineCountAround(const vector>& board, int x, int y) + { + int mineCount = 0; + for (int i = 0; i < DIRS; ++i) + { + int xx = x + dx[i]; + int yy = y + dy[i]; + if(xx < 0 || xx >= board.size() || yy < 0 || yy >= board[0].size()) continue; + if (board[xx][yy] == 'M') ++mineCount; + } + return mineCount; + } + + vector> updateBoard(vector>& board, vector& click) { + int x = click[0]; + int y = click[1]; + if (board[x][y] == 'M') + { + board[x][y] = 'X'; + } + else + { + queue> que; + que.push(make_pair(x, y)); + while (!que.empty()) + { + pair square = que.front(); + que.pop(); + int mineCount = GetMineCountAround(board, square.first, square.second); + if (mineCount > 0) + { + board[square.first][square.second] = '0' + mineCount; + } + else + { + board[square.first][square.second] = 'B'; + for (int i = 0; i < DIRS; ++i) + { + int xx = square.first + dx[i]; + int yy = square.second + dy[i]; + if (xx < 0 || xx >= board.size() || yy < 0 || yy >= board[0].size()) continue; + if (board[xx][yy] != 'E') continue; + board[xx][yy] = 'W'; + que.push(make_pair(xx, yy)); + } + } + } + } + return board; + } +}; \ No newline at end of file diff --git a/Week_03/id_30/LeetCode_547_030.cpp b/Week_03/id_30/LeetCode_547_030.cpp new file mode 100644 index 00000000..2af1adcc --- /dev/null +++ b/Week_03/id_30/LeetCode_547_030.cpp @@ -0,0 +1,38 @@ +class Solution { +public: + vector parents; + void unionSet(int i, int j) + { + while (parents[i] != i) i = parents[i]; + while (parents[j] != j) + { + int p = parents[j]; + parents[j] = i; + j = p; + } + parents[j] = i; + } + + int findCircleNum(vector>& M) { + const int N = M.size(); + for (int i = 0; i < N; ++i) + { + parents.push_back(i); + } + for (int i = 0; i < N - 1; ++i) + { + for (int j = i + 1; j < N; ++j) + { + if (M[i][j] == 1) unionSet(i, j); + } + } + unordered_set circleSet; + for (int i = 0; i < N; ++i) + { + int p = i; + while (parents[p] != p) p = parents[p]; + circleSet.insert(p); + } + return circleSet.size(); + } +}; \ No newline at end of file diff --git a/Week_03/id_30/LeetCode_802_030.cpp b/Week_03/id_30/LeetCode_802_030.cpp new file mode 100644 index 00000000..b94088c5 --- /dev/null +++ b/Week_03/id_30/LeetCode_802_030.cpp @@ -0,0 +1,29 @@ +class Solution { +public: + bool dfsSaveNodes(const vector>& graph, vector& visited, int curNode) + { + if (visited[curNode] > 0) return visited[curNode] == 2; + visited[curNode] = 1; + for (int i = 0; i < graph[curNode].size(); ++i) + { + if (!dfsSaveNodes(graph, visited, graph[curNode][i])) return false; + if(visited[curNode] == 2) break; + } + visited[curNode] = 2; + return true; + } + + vector eventualSafeNodes(vector>& graph) { + const int nodeCount = graph.size(); + vector visited(nodeCount, 0); + vector safeNodes; + for (int i = 0; i < nodeCount; ++i) + { + if (dfsSaveNodes(graph, visited, i)) + { + safeNodes.push_back(i); + } + } + return safeNodes; + } +}; \ No newline at end of file diff --git a/Week_03/id_33/Leetcode_102_33.java b/Week_03/id_33/Leetcode_102_33.java new file mode 100644 index 00000000..2a9524d1 --- /dev/null +++ b/Week_03/id_33/Leetcode_102_33.java @@ -0,0 +1,35 @@ +/* + * @lc app=leetcode id=102 lang=java + * + * [102] Binary Tree Level Order Traversal + */ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +class Solution { + public List> levelOrder(TreeNode root) { + List> list = new ArrayList>(); + if(root == null) return list; + Queue queue = new LinkedList<>(); + queue.offer(root); + while(!queue.isEmpty()){ + int size = queue.size(); + List levelList=new ArrayList(); + for(int i = 0; i < size; i++){ + TreeNode node = queue.poll(); + levelList.add(node.val); + if(node.left != null) queue.offer(node.left); + if(node.right != null) queue.offer(node.right); + } + list.add(levelList); + } + return list; + } +} + diff --git a/Week_03/id_33/Leetcode_127_33.java b/Week_03/id_33/Leetcode_127_33.java new file mode 100644 index 00000000..b8aa9cb7 --- /dev/null +++ b/Week_03/id_33/Leetcode_127_33.java @@ -0,0 +1,42 @@ +/* + * @lc app=leetcode id=127 lang=java + * + * [127] Word Ladder + */ +class Solution { + public int ladderLength(String beginWord, String endWord, List wordList) { + if (!wordList.contains(endWord)) return 0; + int level = 1; + Set set = new HashSet<>(); + for(String word: wordList){ + set.add(word); + } + Queue queue = new LinkedList<>(); + queue.offer(beginWord); + while(!queue.isEmpty()){ + int size = queue.size(); + for(int i = 0; i < size; i++){ + String tmpWord = queue.poll(); + char[] array = tmpWord.toCharArray(); + for(int j = 0; j < array.length; j++){ + char c = array[j]; + for(char k = 'a'; k <= 'z'; k++){ + array[j] = k; + String newWord = String.valueOf(array); + if(k != c &&set.contains(newWord)){ + queue.offer(newWord); + set.remove(newWord); + if(newWord.equals(endWord)){ + return ++level; + } + } + } + array[j] = c; + } + } + level++; + } + return 0; + } +} + diff --git a/Week_03/id_33/Leetcode_200_33.java b/Week_03/id_33/Leetcode_200_33.java new file mode 100644 index 00000000..f863c1c4 --- /dev/null +++ b/Week_03/id_33/Leetcode_200_33.java @@ -0,0 +1,31 @@ +/* + * @lc app=leetcode id=200 lang=java + * + * [200] Number of Islands + */ +class Solution { + public int numIslands(char[][] grid) { + int island = 0; + if (grid.length == 0 || grid[0].length == 0) return 0; + for (int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid[0].length; j++) { + if (grid[i][j] == '1') { + island++; + dfs(grid, i, j); + } + } + } + return island; + } + + public static void dfs (char[][] grid, int i, int j) { + if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length || grid[i][j] == '0') + return; + grid[i][j] = '0'; + dfs(grid, i - 1, j); + dfs(grid, i, j - 1); + dfs(grid, i, j + 1); + dfs(grid, i + 1, j); + } +} + diff --git a/Week_03/id_33/Leetcode_295_33.java b/Week_03/id_33/Leetcode_295_33.java new file mode 100644 index 00000000..542c0669 --- /dev/null +++ b/Week_03/id_33/Leetcode_295_33.java @@ -0,0 +1,28 @@ +/* + * @lc app=leetcode id=295 lang=java + * + * [295] Find Median from Data Stream + */ +class MedianFinder { + + /** initialize your data structure here. */ + public MedianFinder() { + + } + + public void addNum(int num) { + + } + + public double findMedian() { + + } +} + +/** + * Your MedianFinder object will be instantiated and called as such: + * MedianFinder obj = new MedianFinder(); + * obj.addNum(num); + * double param_2 = obj.findMedian(); + */ + diff --git a/Week_03/id_33/Leetcode_703_33.java b/Week_03/id_33/Leetcode_703_33.java new file mode 100644 index 00000000..645b546f --- /dev/null +++ b/Week_03/id_33/Leetcode_703_33.java @@ -0,0 +1,33 @@ +/* + * @lc app=leetcode id=703 lang=java + * + * [703] Kth Largest Element in a Stream + */ +class KthLargest { + + private PriorityQueue minHeap; + private int k; + public KthLargest(int k, int[] nums) { + this.k = k; + this.minHeap = new PriorityQueue<>(); + for (Integer n : nums) { + minHeap.add(n); + if(minHeap.size()>k) + minHeap.poll(); + } + } + + public int add(int val) { + minHeap.add(val); + if(minHeap.size() > k) + minHeap.poll(); + return minHeap.peek(); + } +} + +/** + * Your KthLargest object will be instantiated and called as such: + * KthLargest obj = new KthLargest(k, nums); + * int param_1 = obj.add(val); + */ + diff --git a/Week_03/id_35/Leetcode_102_35.java b/Week_03/id_35/Leetcode_102_35.java new file mode 100644 index 00000000..2738113d --- /dev/null +++ b/Week_03/id_35/Leetcode_102_35.java @@ -0,0 +1,70 @@ +package com.leecode.week03; + +import com.leecode.TreeNode; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; + +/** + * https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/ + * 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。 + */ +public class Leetcode_102_35 { + public static void main(String[] args) { + Leetcode_102_35 lc=new Leetcode_102_35(); + //int[] arr={3,2,9,-1,-1,10,-1,-1,8,-1,11,-1}; + //[3,9,20,null,null,15,7] + int[] arr={3,9,20,-1,-1,-1,15,7}; + // int[] arr={3,2}; + TreeNode treeNode=TreeNode.createBinaryV1(arr,arr.length); + + List> list= lc.levelOrder(treeNode); + System.out.println(list); + + } + + /** + * 思考过程,我是做了多叉树按层次遍历的题目之后来做这道题目的 + * + * @param root + * @return + */ + public List> levelOrder(TreeNode root) { + + List> list=new ArrayList<>(); + if(root==null){ + return list; + } + + Queue queue=new ArrayDeque<>(); + queue.offer(root); + + while (!queue.isEmpty()){ + int queueSize=queue.size(); + List ls =new ArrayList<>(queueSize); + + for(int i=0;i> list= lc.zigzagLevelOrder(treeNode); + System.out.println(list); + + } + + /** + * 思考过程,我是做了多叉树按层次遍历的题目之后来做这道题目的 + * ,同样在上面基础上面进行改进,要从左到右,然后从右到做,只要把每层加入的时候顺序往后或者往前就好了 + * 需要注意的是,出队列是有顺序的,所以只能是在写入list中元素的下标进行控制了 + * + * @param root + * @return + */ + public List> zigzagLevelOrder(TreeNode root) { + + + List> list=new ArrayList<>(); + if(root==null){ + return list; + } + + Queue queue=new ArrayDeque<>(); + queue.offer(root); + boolean needReverse=false;//false ->从左到右 true->从右到左 + + while (!queue.isEmpty()){ + int queueSize=queue.size(); + Integer[] arr=new Integer[queueSize]; + + for(int i=0;i"+maxDept); + } + + + /** + * 递归 + * @param root + * @return + */ + public int maxDepth(TreeNode root) { + return root == null ? 0 : (1 + Math.max(maxDepth(root.left), maxDepth(root.right))); + } + + +} diff --git a/Week_03/id_35/Leetcode_107_35.java b/Week_03/id_35/Leetcode_107_35.java new file mode 100644 index 00000000..fc397789 --- /dev/null +++ b/Week_03/id_35/Leetcode_107_35.java @@ -0,0 +1,77 @@ +package com.leecode.week03; + +import com.leecode.TreeNode; + +import java.util.*; + +/** + * 107. Binary Tree Level Order Traversal II + */ + +public class Leetcode_107_35 { + + public static void main(String[] args) { + Leetcode_107_35 lc=new Leetcode_107_35(); + //int[] arr={3,2,9,-1,-1,10,-1,-1,8,-1,11,-1}; + //[3,9,20,null,null,15,7] + int[] arr={3,9,20,-1,-1,-1,15,7}; + // int[] arr={3,2}; + TreeNode treeNode=TreeNode.createBinaryV1(arr,arr.length); + + List> list= lc.levelOrderBottom(treeNode); + System.out.println(list); + + } + + /** + * 思考过程,我是做了多叉树按层次遍历的题目之后来做这道题目的 + * ,直接想法就是把结果反着输出就好了,要反着输出,就把结果压到栈上面 + * + * @param root + * @return + */ + public List> levelOrderBottom(TreeNode root) { + + List> list=new ArrayList<>(); + if(root==null){ + return list; + } + + Stack> stack=new Stack<>(); + + Queue queue=new ArrayDeque<>(); + queue.offer(root); + + while (!queue.isEmpty()){ + int queueSize=queue.size(); + List ls =new ArrayList<>(queueSize); + + for(int i=0;i ls =stack.pop(); + list.add(ls); + } + + return list; + } +} diff --git a/Week_03/id_35/Leetcode_111_35.java b/Week_03/id_35/Leetcode_111_35.java new file mode 100644 index 00000000..74c34269 --- /dev/null +++ b/Week_03/id_35/Leetcode_111_35.java @@ -0,0 +1,54 @@ +package com.leecode.week03; + +import com.geekbang.BinaryTree; +import com.leecode.TreeNode; + +import java.util.ArrayDeque; +import java.util.Queue; + +/** + * https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/ + * 给定一个二叉树,找出其最小深度 + */ +public class Leetcode_111_35 { + public static void main(String[] args) { + Leetcode_111_35 lc=new Leetcode_111_35(); + //int[] arr={3,2,9,-1,-1,10,-1,-1,8,-1,11,-1}; + //[3,9,20,null,null,15,7] + int[] arr={3,9,20,-1,-1,-1,15,7}; + // int[] arr={3,2}; + TreeNode treeNode=TreeNode.createBinaryV1(arr,arr.length); + int minDept= lc.minDepth(treeNode); + System.out.println("minDepth->"+minDept); + } + + + /** + * 思考过程: + * 凡是要了解深度,都是要遍历到叶子节点,直接的想法就是遍历到所有的叶子节点,找到深度最小的那波即可 + * + * @param root + * @return + */ + public int minDepth(TreeNode root) { + + if(root==null){ + return 0; + } + //当前的叶子节点的条件,左右都是null的 + if(root.left==null&&root.right==null){ + return 1; + } + int minDept=Integer.MAX_VALUE; + if(root.left!=null){ + minDept=Math.min(minDepth(root.left),minDept); + } + + if(root.right!=null){ + minDept=Math.min(minDepth(root.right),minDept); + } + + //左右节点中不为空的情况,会往下递推一层,深度+1 + return minDept+1; + } +} diff --git a/Week_03/id_35/Leetcode_429_35.java b/Week_03/id_35/Leetcode_429_35.java new file mode 100644 index 00000000..af36d198 --- /dev/null +++ b/Week_03/id_35/Leetcode_429_35.java @@ -0,0 +1,128 @@ +package com.leecode.week03; + +import com.leecode.TreeNode; + +import java.util.*; + +/** + * + * N叉树的层序遍历 + */ +public class Leetcode_429_35 { + + class Node { + public int val; + public List children; + + public Node() {} + + public Node(int _val,List _children) { + val = _val; + children = _children; + } + }; + + + public static void main(String[] args) { + Leetcode_429_35 lc=new Leetcode_429_35(); + + Node root=lc.createTree(); + + + + List> list= lc.levelOrder(root); + System.out.println(list); + + } + + + public Node createTree(){ + List _children56=new ArrayList<>(); + Node n5=new Node(5,null); + Node n6=new Node(6,null); + + _children56.add(n5); + _children56.add(n6); + + + List _children324=new ArrayList<>(); + Node n3=new Node(3,_children56); + Node n2=new Node(2,null); + + List _children78=new ArrayList<>(); + + Node n7=new Node(7,null); + Node n8=new Node(8,null); + + _children78.add(n7); + _children78.add(n8); + + Node n4=new Node(4,_children78); + + + + _children324.add(n3); + _children324.add(n2); + _children324.add(n4); + + Node root=new Node(1,_children324); + + return root; + + + + + } + + + /** + * 思考过程,按照层次遍历只是可以打印顺序,一开始是直接输出 + * 但是碰到有个问题的就是层次没注意, + * 第一把提交未通过,再寻找原因 + *后面发现每次入队列的时候队列上面的元素其实就是当前层的顺序,但是这次需要每次取元素的时候把 + * 队列里面的元素都拿出来 + * 拿出来之后队列必然是空的,接下来就把下一层元素全部放进队列里面 + * 每个元素会被访问到两次,入队列一次,出队列一次 + * @param root + * @return + */ + public List> levelOrder(Node root) { + + List> list=new ArrayList<>(); + if(root==null){ + return list; + } + + Queue queue=new ArrayDeque<>(); + queue.offer(root); + + + while (!queue.isEmpty()){ + int curQueueSize=queue.size(); + List ls=new ArrayList<>(curQueueSize); + for (int i=0;i List[List[int]]: +# levels = [] +# if not root: +# return levels + +# def helper(node, level): +# if len(levels) == level: +# levels.append([]) + +# levels[level].append(node.val) + +# if node.left: +# helper(node.left, level + 1) +# if node.right: +# helper(node.right, level + 1) + +# helper(root, 0) +# return levels + +# BFS +class Solution: + def levelOrder(self, root: TreeNode) -> List[List[int]]: + levels = [] + if not root: + return levels + + level = 0 + from collections import deque + queue = deque([root,]) + + while queue: + levels.append([]) + level_length = len(queue) + + for i in range(level_length): + node = queue.popleft() + + levels[level].append(node.val) + + if node.left: + queue.append(node.left) + if node.right: + queue.append(node.right) + + level += 1 + + return levels + diff --git a/Week_03/id_36/LeetCode_104_36.py b/Week_03/id_36/LeetCode_104_36.py new file mode 100644 index 00000000..8e5dd1ac --- /dev/null +++ b/Week_03/id_36/LeetCode_104_36.py @@ -0,0 +1,70 @@ +# +# @lc app=leetcode.cn id=104 lang=python3 +# +# [104] 二叉树的最大深度 +# +# https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/description/ +# +# algorithms +# Easy (69.37%) +# Likes: 298 +# Dislikes: 0 +# Total Accepted: 52.1K +# Total Submissions: 75.1K +# Testcase Example: '[3,9,20,null,null,15,7]' +# +# 给定一个二叉树,找出其最大深度。 +# +# 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。 +# +# 说明: 叶子节点是指没有子节点的节点。 +# +# 示例: +# 给定二叉树 [3,9,20,null,null,15,7], +# +# ⁠ 3 +# ⁠ / \ +# ⁠ 9 20 +# ⁠ / \ +# ⁠ 15 7 +# +# 返回它的最大深度 3 。 +# +# +# Definition for a binary tree node. + + +class TreeNode: + def __init__(self, x): + self.val = x + self.left = None + self.right = None + +# # 递归 +# class Solution: +# def maxDepth(self, root: TreeNode) -> int: +# if not root: +# return 0 +# return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1 + +# DFS +class Solution: + def maxDepth(self, root: TreeNode) -> int: + if root is None: + return 0 + + stack = [] + stack.append((root, 1)) + max_depth = 0 + while len(stack) > 0: + current = stack.pop() + root = current[0] + current_depth = current[1] + if root.left is None and root.right is None: + max_depth = max(max_depth, current_depth) + if root.left is not None: + stack.append((root.left, current_depth + 1)) + if root.right is not None: + stack.append((root.right, current_depth + 1)) + + return max_depth diff --git a/Week_03/id_36/LeetCode_107_36.py b/Week_03/id_36/LeetCode_107_36.py new file mode 100644 index 00000000..4315a325 --- /dev/null +++ b/Week_03/id_36/LeetCode_107_36.py @@ -0,0 +1,73 @@ +# +# @lc app=leetcode.cn id=107 lang=python3 +# +# [107] 二叉树的层次遍历 II +# +# https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii/description/ +# +# algorithms +# Easy (60.90%) +# Likes: 108 +# Dislikes: 0 +# Total Accepted: 17.6K +# Total Submissions: 28.9K +# Testcase Example: '[3,9,20,null,null,15,7]' +# +# 给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历) +# +# 例如: +# 给定二叉树 [3,9,20,null,null,15,7], +# +# ⁠ 3 +# ⁠ / \ +# ⁠ 9 20 +# ⁠ / \ +# ⁠ 15 7 +# +# +# 返回其自底向上的层次遍历为: +# +# [ +# ⁠ [15,7], +# ⁠ [9,20], +# ⁠ [3] +# ] +# +# +# +# Definition for a binary tree node. +class TreeNode: + def __init__(self, x): + self.val = x + self.left = None + self.right = None + +# BFS +class Solution: + def levelOrderBottom(self, root: TreeNode) -> List[List[int]]: + levels = [] + if not root: + return levels + + from collections import deque + queue = deque([root,]) + children_list = [] + + while queue: + level_length = len(queue) + + for i in range(level_length): + node = queue.popleft() + + if node.left: + queue.append(node.left) + if node.right: + queue.append(node.right) + + children_list.append(node.val) + + levels.insert(0, children_list) + children_list = [] + + return levels + diff --git a/Week_03/id_36/LeetCode_111_36.py b/Week_03/id_36/LeetCode_111_36.py new file mode 100644 index 00000000..5ade1f1d --- /dev/null +++ b/Week_03/id_36/LeetCode_111_36.py @@ -0,0 +1,36 @@ +# +# @lc app=leetcode.cn id=111 lang=python3 +# +# [111] 二叉树的最小深度 +# +# Definition for a binary tree node. + + +class TreeNode: + def __init__(self, x): + self.val = x + self.left = None + self.right = None + +DFS +class Solution: + def minDepth(self, root: TreeNode) -> int: + if root is None: + return 0 + + stack = [] + import sys + stack.append((root, 1)) + min_depth = sys.maxsize + while len(stack) > 0: + current = stack.pop() + root = current[0] + current_depth = current[1] + if root.left is None and root.right is None: + min_depth = min(min_depth, current_depth) + if root.left is not None: + stack.append((root.left, current_depth + 1)) + if root.right is not None: + stack.append((root.right, current_depth + 1)) + + return min_depth diff --git a/Week_03/id_36/LeetCode_200_36.py b/Week_03/id_36/LeetCode_200_36.py new file mode 100644 index 00000000..91552989 --- /dev/null +++ b/Week_03/id_36/LeetCode_200_36.py @@ -0,0 +1,50 @@ +# +# @lc app=leetcode.cn id=200 lang=python3 +# +# [200] 岛屿数量 +# +# https://leetcode-cn.com/problems/number-of-islands/description/ +# +# algorithms +# Medium (44.05%) +# Likes: 171 +# Dislikes: 0 +# Total Accepted: 16.5K +# Total Submissions: 37.4K +# Testcase Example: '[["1","1","1","1","0"],["1","1","0","1","0"],["1","1","0","0","0"],["0","0","0","0","0"]]' +# +# 给定一个由 '1'(陆地)和 +# '0'(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。 +# +# 示例 1: +# +# 输入: +# 11110 +# 11010 +# 11000 +# 00000 +# +# 输出: 1 +# +# +# 示例 2: +# +# 输入: +# 11000 +# 11000 +# 00100 +# 00011 +# +# 输出: 3 +# +# +# + + +class Solution: + def numIslands(self, grid: List[List[str]]) -> int: + def sink(i, j): + if 0 <= i < len(grid) and 0 <= j < len(grid[0]) and grid[i][j] == '1': + grid[i][j] = '0' + list(map(sink, (i-1, i, i+1, i), (j, j-1, j, j+1))) + return sum(grid[i][j] == '1' and not sink(i, j) for i in range(len(grid)) for j in range(len(grid[0]))) diff --git a/Week_03/id_36/LeetCode_429_36.py b/Week_03/id_36/LeetCode_429_36.py new file mode 100644 index 00000000..32e2036e --- /dev/null +++ b/Week_03/id_36/LeetCode_429_36.py @@ -0,0 +1,76 @@ +# +# @lc app=leetcode.cn id=429 lang=python3 +# +# [429] N叉树的层序遍历 +# +# https://leetcode-cn.com/problems/n-ary-tree-level-order-traversal/description/ +# +# algorithms +# Easy (61.82%) +# Likes: 36 +# Dislikes: 0 +# Total Accepted: 6.6K +# Total Submissions: 10.6K +# Testcase Example: '{"$id":"1","children":[{"$id":"2","children":[{"$id":"5","children":[],"val":5},{"$id":"6","children":[],"val":6}],"val":3},{"$id":"3","children":[],"val":2},{"$id":"4","children":[],"val":4}],"val":1}' +# +# 给定一个 N 叉树,返回其节点值的层序遍历。 (即从左到右,逐层遍历)。 +# +# 例如,给定一个 3叉树 : +# +# +# +# +# +# +# +# 返回其层序遍历: +# +# [ +# ⁠ [1], +# ⁠ [3,2,4], +# ⁠ [5,6] +# ] +# +# +# +# +# 说明: +# +# +# 树的深度不会超过 1000。 +# 树的节点总数不会超过 5000。 +# +# + +# Definition for a Node. +class Node: + def __init__(self, val, children): + self.val = val + self.children = children + +class Solution: + def levelOrder(self, root: 'Node') -> List[List[int]]: + levels = [] + if not root: + return levels + + level = 0 + from collections import deque + queue = deque([root,]) + + while queue: + levels.append([]) + level_length = len(queue) + + for i in range(level_length): + node = queue.popleft() + + levels[level].append(node.val) + + if node.children: + queue.extend(node.children) + + level += 1 + + return levels + diff --git "a/Week_03/id_36/\345\260\217\347\273\204\350\256\250\350\256\272\347\232\204\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\347\232\204\346\200\235\347\273\264\345\257\274\345\233\276.PNG" "b/Week_03/id_36/\345\260\217\347\273\204\350\256\250\350\256\272\347\232\204\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\347\232\204\346\200\235\347\273\264\345\257\274\345\233\276.PNG" new file mode 100644 index 00000000..4f5286d7 Binary files /dev/null and "b/Week_03/id_36/\345\260\217\347\273\204\350\256\250\350\256\272\347\232\204\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\347\232\204\346\200\235\347\273\264\345\257\274\345\233\276.PNG" differ diff --git a/Week_03/id_37/LeetCode_102_037.java b/Week_03/id_37/LeetCode_102_037.java new file mode 100644 index 00000000..6b97b6e9 --- /dev/null +++ b/Week_03/id_37/LeetCode_102_037.java @@ -0,0 +1,10 @@ +public class Solution { + public int maxDepth(TreeNode root) { + if(root==null){ + return 0; + } + int leftDepth=maxDepth(root.left); + int rightDepth=maxDepth(root.right); + return Math.max(leftDepth,rightDepth)+1; + } +} \ No newline at end of file diff --git a/Week_03/id_37/LeetCode_200_037.java b/Week_03/id_37/LeetCode_200_037.java new file mode 100644 index 00000000..916d0124 --- /dev/null +++ b/Week_03/id_37/LeetCode_200_037.java @@ -0,0 +1,64 @@ +public class Solution { + boolean[][] visited; + int res=0; + public int numIslands(char[][] grid) { + if(grid==null||grid.length==0||grid[0].length==0){ + return 0; + } + int m=grid.length; + int n=grid[0].length; + visited=new boolean[m][n]; + for(int i=0;i=0&&newi=0&&newj= grid.length) return; + if(row < 0 || row >= grid[0].length) return; + if(grid[col][row] == '1') { + grid[col][row] = '0'; + bfs(col + 1, row, grid); + bfs(col, row + 1, grid); + bfs(col - 1, row, grid); + bfs(col, row - 1, grid); + } + } + + public static void main(String[] args) { + LeetCode_200_038 testCode_200_038 = new LeetCode_200_038(); + char[][] grid = new char[][]{{'1', '1', '1', '1', '0'}, + {'1', '1', '0', '1', '0'}, + {'1', '1', '0', '0', '0'}, + {'0', '0', '0', '0', '0'}}; + System.out.println(testCode_200_038.numIslands(grid)); + } +} \ No newline at end of file diff --git a/Week_03/id_38/LeetCode_703_038.java b/Week_03/id_38/LeetCode_703_038.java new file mode 100644 index 00000000..64ae1677 --- /dev/null +++ b/Week_03/id_38/LeetCode_703_038.java @@ -0,0 +1,40 @@ +/* + * @lc app=leetcode.cn id=703 lang=java + * + * [703] 数据流中的第K大元素 + */ +class LeetCode_703_038 { + + public static void main(String[] args) { + KthLargest kthLargest = new KthLargest(3, new int[]{1, 2, 4, 9}); + System.out.println(kthLargest.add(3)); + System.out.println(kthLargest.add(0)); + System.out.println(kthLargest.add(8)); + } +} + +/** + * 优先队列 + */ +class KthLargest { + + final PriorityQueue pq; + final int k; + public KthLargest(int k, int[] nums) { + this.k = k; + pq = new PriorityQueue<>(k); + for(int i : nums) { + add(i); + } + } + + public int add(int val) { + if(pq.size() < k) { + pq.offer(val); + }else if(pq.peek() < val) { + pq.poll(); + pq.offer(val); + } + return pq.peek(); + } +} \ No newline at end of file diff --git a/Week_03/id_38/README.md b/Week_03/id_38/README.md new file mode 100644 index 00000000..34d9e3de --- /dev/null +++ b/Week_03/id_38/README.md @@ -0,0 +1,29 @@ +# 学习笔记 + +## 第三周题目 +--- + +### 图 +* [x] 【中等】[200. 岛屿数量](https://leetcode-cn.com/problems/number-of-islands/) +* [ ] 【中等】[210. 课程表 II](https://leetcode-cn.com/problems/course-schedule-ii) +--- +### 堆和排序 +* [x] 【简单】[703. 数据流中的第K大元素](https://leetcode-cn.com/problems/kth-largest-element-in-a-stream/) +* [ ] 【困难】[295. 数据流的中位数](https://leetcode-cn.com/problems/find-median-from-data-stream/) +--- +### DFS +* [x] 【简单】[104. 二叉树的最大深度](https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/) +* [x] 【简单】[111. 二叉树的最小深度](https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/) +* [ ] 【中等】[547. 朋友圈](https://leetcode-cn.com/problems/friend-circles/) +* [ ] 【中等】[802. 找到最终的安全状态](https://leetcode-cn.com/problems/find-eventual-safe-states/) +* [ ] 【困难】[329. 矩阵中的最长递增路径](https://leetcode-cn.com/problems/longest-increasing-path-in-a-matrix/) +* [ ] 【中等】[529. 扫雷游戏](https://leetcode-cn.com/problems/minesweeper/) +* [ ] 【困难】[127. 单词接龙](https://leetcode-cn.com/problems/word-ladder/) +--- +### BFS +* [ ] 【简单】[429. N叉树的层序遍历](https://leetcode-cn.com/problems/n-ary-tree-level-order-traversal/) +* [ ] 【中等】[102. 二叉树的层次遍历](https://leetcode-cn.com/problems/binary-tree-level-order-traversal/) +* [ ] 【简单】[107. 二叉树的层次遍历 II](https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii/) +* [ ] 【中等】[103. 二叉树的锯齿形层次遍历](https://leetcode-cn.com/problems/binary-tree-zigzag-level-order-traversal/) +* [ ] 【中等】[529. 扫雷游戏](https://leetcode-cn.com/problems/minesweeper/) +* [ ] 【中等】[310. 最小高度树](https://leetcode-cn.com/problems/minimum-height-trees/) diff --git a/Week_03/id_39/LeetCode_102_39.js b/Week_03/id_39/LeetCode_102_39.js new file mode 100644 index 00000000..620300a1 --- /dev/null +++ b/Week_03/id_39/LeetCode_102_39.js @@ -0,0 +1,46 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number[][]} + * https://leetcode.com/problems/binary-tree-level-order-traversal/ + */ +var levelOrder = function(root) { + if (!root) { + return []; + } + let result = []; + let level = [root]; + let queue = []; + let depth = -1; + + while (level.length) { + result[++depth] = []; + + while (level.length) { + let node = level.shift(); + + if (node.val != null) { + result[depth].push(node.val); + } + + + if (node.left) { + queue.push(node.left); + } + if (node.right) { + queue.push(node.right); + } + } + + level = queue; + queue = []; + } + + return result; +}; \ No newline at end of file diff --git a/Week_03/id_39/LeetCode_103_39.js b/Week_03/id_39/LeetCode_103_39.js new file mode 100644 index 00000000..c1bcc201 --- /dev/null +++ b/Week_03/id_39/LeetCode_103_39.js @@ -0,0 +1,50 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number[][]} + * https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/ + */ +var zigzagLevelOrder = function(root) { + if (!root) { + return []; + } + let queue = [root]; + let isOdd = true; + let levelNum = 1; + let result = []; + + while (queue.length) { + result.push([]); + let level = result.length - 1; + let count = 0; + while (levelNum) { + levelNum--; + let node = queue.shift(); + if (node.val != null) { + if (isOdd) { + result[level].push(node.val); + } else { + result[level].unshift(node.val); + } + } + if (node.left) { + queue.push(node.left); + count++; + } + if (node.right) { + queue.push(node.right); + count++; + } + } + levelNum = count; + isOdd = !isOdd; + } + + return result; +}; \ No newline at end of file diff --git a/Week_03/id_39/LeetCode_107_39.js b/Week_03/id_39/LeetCode_107_39.js new file mode 100644 index 00000000..3190adc1 --- /dev/null +++ b/Week_03/id_39/LeetCode_107_39.js @@ -0,0 +1,41 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number[][]} + * https://leetcode.com/problems/binary-tree-level-order-traversal-ii/ + */ +var levelOrderBottom = function(root) { + if (!root) { + return []; + } + let queue = [root]; + let levelNum = 1; + let result = []; + + while (queue.length) { + result.unshift([]); + let count = 0; + for (let i = 0; i < levelNum; i++) { + let node = queue.shift(); + if (node.val != null) { + result[0].push(node.val); + } + if (node.left) { + queue.push(node.left); + count++; + } + if (node.right) { + queue.push(node.right); + count++; + } + } + levelNum = count; + } + return result; +}; \ No newline at end of file diff --git a/Week_03/id_39/LeetCode_200_39.js b/Week_03/id_39/LeetCode_200_39.js new file mode 100644 index 00000000..0d3c8aef --- /dev/null +++ b/Week_03/id_39/LeetCode_200_39.js @@ -0,0 +1,101 @@ +/** + * @param {character[][]} grid + * @return {number} + * https://leetcode.com/problems/number-of-islands/ + */ + +/** + * 以下为 dfs递归染色解法 + */ +var dfs = function (grid, i, j) { + let direction = [[1, 0], [-1, 0], [0, 1], [0, -1]]; + grid[i][j] = '0'; + for (let h = 0; h < direction.length; h++) { + let x = direction[h][0]; + let y = direction[h][1]; + if (grid[i+x] && grid[i+x][j+y] == '1') { + grid[i+x][j+y] = '0'; + dfs(grid, i+x, j+y); + } + } +} + +var numIslands = function(grid) { + let count = 0; + for (let i = 0; i < grid.length; i++) { + for (let j = 0; j < grid[i].length; j++) { + if (grid[i][j] == '1') { + count++; + dfs(grid, i, j); + } + } + } + return count; +}; + + +/** + * 以下为用并查集的解法 + */ +class UnionFind{ + constructor(grid) { + let m = grid.length, n = grid[0].length; + this.count = 0; + this.parent = new Array(m*n).fill(-1); + this.rank = new Array(m*n).fill(0); + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (grid[i][j] == '1') { + this.parent[i * n + j] = i * n + j; + this.count++; + } + } + } + } + find(i) { + if (this.parent[i] != i) { + this.parent[i] = this.find(this.parent[i]); + } + return this.parent[i]; + } + union(x, y) { + let rootx = this.find(x); + let rooty = this.find(y); + if (rootx != rooty) { + if (this.rank[rootx] > this.rank[rooty]) { + this.parent[rooty] = rootx; + } else if (this.rank[rootx] < this.rank[rooty]) { + this.parent[rootx] = rooty; + } else { + this.parent[rooty] = rootx; + this.rank[rootx] += 1; + } + this.count--; + } + } +} + +var numIslands = function(grid) { + if (!grid || !grid[0]) { + return 0; + } + let uf = new UnionFind(grid); + let direction = [[1, 0], [-1, 0], [0, 1], [0, -1]]; + let m = grid.length, n = grid[0].length; + + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (grid[i][j] == '0') { + continue; + } + for (let d = 0; d < direction.length; d++) { + let nr = i + direction[d][0], nc = j + direction[d][1]; + if (nr >= 0 && nc >= 0 && nr < m && nc < n && grid[nr][nc] == '1') { + uf.union(i * n + j, nr * n + nc); + } + } + } + } + + return uf.count; +}; \ No newline at end of file diff --git a/Week_03/id_39/LeetCode_329_39.js b/Week_03/id_39/LeetCode_329_39.js new file mode 100644 index 00000000..c87fd170 --- /dev/null +++ b/Week_03/id_39/LeetCode_329_39.js @@ -0,0 +1,41 @@ +/** + * @param {number[][]} matrix + * @return {number} + * https://leetcode.com/problems/longest-increasing-path-in-a-matrix/ + * dfs + 记忆化 + */ + +var direction = [[0, 1], [1, 0], [-1, 0], [0, -1]]; + +var dfs = function (matrix, i, j, memo) { + let m = matrix.length, n = matrix[0].length; + let index = i * n + j; + if (memo[index] != -1) { + return memo[index]; + } + let max = 1; + + for (let d = 0; d < direction.length; d++) { + let x = i + direction[d][0], y = j + direction[d][1]; + if (x >= 0 && y >= 0 && x < m && y < n && matrix[x][y] > matrix[i][j]) { + max = Math.max(max, dfs(matrix, x, y, memo) + 1); + } + } + memo[index] = max; + return max; +} + +var longestIncreasingPath = function(matrix) { + if (!matrix || !matrix.length) { + return 0; + } + let m = matrix.length, n = matrix[0].length; + let max = 1; + let memo = new Array(m*n).fill(-1); + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + max = Math.max(max, dfs(matrix, i, j, memo)); + } + } + return max; +}; \ No newline at end of file diff --git a/Week_03/id_39/LeetCode_429_39.js b/Week_03/id_39/LeetCode_429_39.js new file mode 100644 index 00000000..aeeaa524 --- /dev/null +++ b/Week_03/id_39/LeetCode_429_39.js @@ -0,0 +1,43 @@ +/** + * // Definition for a Node. + * function Node(val,children) { + * this.val = val; + * this.children = children; + * }; + */ +/** + * @param {Node} root + * @return {number[][]} + * https://leetcode.com/problems/n-ary-tree-level-order-traversal/ + */ +var levelOrder = function(root) { + if (!root) { + return []; + } + let result = []; + + let queue = []; + let level = [root]; + let depth = -1; + + while (level.length) { + depth++; + result[depth] = []; + + while (level.length) { + let node = level.shift(); + result[depth].push(node.val); + + if (!node.children) { + continue; + } + for (let i = 0; i < node.children.length; i++) { + queue.push(node.children[i]); + } + } + + level = queue; + queue = []; + } + return result; +}; \ No newline at end of file diff --git a/Week_03/id_39/LeetCode_529_39.js b/Week_03/id_39/LeetCode_529_39.js new file mode 100644 index 00000000..dda59517 --- /dev/null +++ b/Week_03/id_39/LeetCode_529_39.js @@ -0,0 +1,37 @@ +/** + * @param {character[][]} board + * @param {number[]} click + * @return {character[][]} + * https://leetcode.com/problems/minesweeper/ + */ +var updateBoard = function(board, click) { + let m = board.length, n = board[0].length; + let direction = [[0, 1], [1, 0], [0, -1], [-1, 0], [1, 1], [-1, -1], [1, -1], [-1, 1]]; + + let cX = click[0]; + let cY = click[1]; + if (board[cX][cY] == 'M') { + board[cX][cY] = 'X'; + } + if (board[cX][cY] == 'E') { + let count = 0; + for (let i = 0; i < direction.length; i++) { + let x = cX + direction[i][0], y = cY + direction[i][1]; + if (x >= 0 && y >= 0 && x < m && y < n && board[x][y] == 'M') { + count++; + } + } + if (count == 0) { + board[cX][cY] = 'B'; + for (let i = 0; i < direction.length; i++) { + let x = cX + direction[i][0], y = cY + direction[i][1]; + if (x >= 0 && y >= 0 && x < m && y < n) { + updateBoard(board, [x, y]); + } + } + } else { + board[cX][cY] = count.toString(); + } + } + return board; +}; \ No newline at end of file diff --git a/Week_03/id_39/NOTE.md b/Week_03/id_39/NOTE.md index 107ea7d6..1dce625f 100644 --- a/Week_03/id_39/NOTE.md +++ b/Week_03/id_39/NOTE.md @@ -1 +1,14 @@ # 学习笔记 + +## 并查集 +- 并查集的逻辑理解起来不难 +- 但是写起来不是特别简单,虽然都是基础数据结构,但是还是不那么好写,尤其是带rank的,路径压缩还比较好理解,得多写几次 +- 岛屿的题目用dfs来做非常好理解,突然觉得递归这个之前觉得很难的东西,在算法题里反倒是最简单的了 +- 自己还是有很多成长的,加油~ + +## 树 +- 写了很多个按层遍历BFS的题,现在已经非常熟悉使用queue来做按层遍历的题 +- 之前觉得树对我是一个不小的难点,但是做的多了,都是套路化的应用dfs(stack)和bfs(queue) + +## 堆 +- 堆的应用其实不难,像java这种语言有直接提供优先队列使用倒是不复杂,但是像js这个,得自己实现一个大顶堆、小顶堆,是个不小的挑战。 \ No newline at end of file diff --git a/Week_03/id_40/LeetCode_103_40.cpp b/Week_03/id_40/LeetCode_103_40.cpp new file mode 100644 index 00000000..8b78a89d --- /dev/null +++ b/Week_03/id_40/LeetCode_103_40.cpp @@ -0,0 +1,53 @@ +/* + * @lc app=leetcode id=103 lang=cpp + * + * [103] Binary Tree Zigzag Level Order Traversal + */ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +class Solution { +public: + vector> zigzagLevelOrder(TreeNode* root) { + vector> result; + queue q; + bool zig = true; /*left then right on true*/ + q.push(root); + stack s; + while(!q.empty() && root) + { + vector vec; + int cnt = q.size(); + while(cnt > 0) + { + TreeNode* node = q.front(); + q.pop(); + if(node) + { + if(zig) vec.push_back(node->val); + else s.push(node->val); + if(node->left) q.push(node->left); + if(node->right) q.push(node->right); + } + + cnt--; + } + zig = !zig; + while(!s.empty()) + { + vec.push_back(s.top()); + s.pop(); + } + result.push_back(vec); + } + return result; + + } +}; + diff --git a/Week_03/id_40/LeetCode_200_40.cpp b/Week_03/id_40/LeetCode_200_40.cpp new file mode 100644 index 00000000..7a7a1b42 --- /dev/null +++ b/Week_03/id_40/LeetCode_200_40.cpp @@ -0,0 +1,86 @@ +/* + * @lc app=leetcode id=200 lang=cpp + * + * [200] Number of Islands + */ + +/* +class Solution { +public: + + int numIslands(const vector>& inputGrid) const { + vector> grid = inputGrid; + + const int rows = grid.size(); + const int cols = rows ? grid[0].size() : 0; + + int islandCount = 0; + + stack> s; + for (int j = 0; j < rows; j++) { + for (int k = 0; k < cols; k++) { + if (grid[j][k] == '1') { + islandCount++; + grid[j][k] = '0'; + s.push({j, k}); + while (!s.empty()) { + int m = s.top().first; + int n = s.top().second; + if (n + 1 < cols && grid[m][n + 1] == '1') { + grid[m][n + 1] = '0'; + s.push({m, n + 1}); + } else if (m + 1 < rows && grid[m + 1][n] == '1') { + grid[m + 1][n] = '0'; + s.push({m + 1, n}); + } else if (n - 1 >= 0 && grid[m][n - 1] == '1') { + grid[m][n - 1] = '0'; + s.push({m, n - 1}); + } else if (m - 1 >= 0 && grid[m - 1][n] == '1') { + grid[m - 1][n] = '0'; + s.push({m - 1, n}); + } else { + s.pop(); + } + } + } + } + } + + return islandCount; + + } +}; +*/ +class Solution { +public: + int numIslands(vector>& grid) { + + int numTotal=0; + for(int i=0; i>& grid, int x, int y){ + + if(x<0 || x>=grid.size() || + y < 0 || y >= grid[0].size()) + return; + + if(grid[x][y] != '1') + return; + grid[x][y]='0'; + + FloodFillIsland(grid,x-1,y); + FloodFillIsland(grid,x+1,y); + FloodFillIsland(grid,x,y-1); + FloodFillIsland(grid,x,y+1); + } +}; + diff --git a/Week_03/id_40/LeetCode_329_40.cpp b/Week_03/id_40/LeetCode_329_40.cpp new file mode 100644 index 00000000..7ebc8b05 --- /dev/null +++ b/Week_03/id_40/LeetCode_329_40.cpp @@ -0,0 +1,40 @@ +/* + * @lc app=leetcode id=329 lang=cpp + * + * [329] Longest Increasing Path in a Matrix + */ +class Solution { +public: + // dp[i][j][k]表示matrix[i][j]结尾且数组长度不超过k时的最长递增路径长度 + int longestIncreasingPath(vector>& matrix) { + + int m = matrix.size(); if(m==0) return 0; + int n = matrix[0].size(); if(n==0) return 0; + vector>> dp(m, vector>(n, vector{1,1})); + int cur = 0; + int ans = 1; + while(1){ + bool is_change = false; + for(int i=0; i=0 && matrix[i][j]>matrix[i-1][j] && 1+dp[i-1][j][cur]>dp[i][j][1-cur]) dp[i][j][1-cur] = 1+dp[i-1][j][cur]; + if(i+1matrix[i+1][j] && 1+dp[i+1][j][cur]>dp[i][j][1-cur]) dp[i][j][1-cur] = 1+dp[i+1][j][cur]; + if(j-1>=0 && matrix[i][j]>matrix[i][j-1] && 1+dp[i][j-1][cur]>dp[i][j][1-cur]) dp[i][j][1-cur] = 1+dp[i][j-1][cur]; + if(j+1matrix[i][j+1] && 1+dp[i][j+1][cur]>dp[i][j][1-cur]) dp[i][j][1-cur] = 1+dp[i][j+1][cur]; + if(old!=dp[i][j][1-cur]) is_change = true; + } + } + if(is_change){ + ans++; + cur = 1-cur; + }else{ + return ans; + } + } + return ans; + } + +}; + diff --git a/Week_03/id_40/LeetCode_547_40.cpp b/Week_03/id_40/LeetCode_547_40.cpp new file mode 100644 index 00000000..aad936df --- /dev/null +++ b/Week_03/id_40/LeetCode_547_40.cpp @@ -0,0 +1,24 @@ +/* + * @lc app=leetcode id=547 lang=cpp + * + * [547] Friend Circles + */ +class Solution { +public: + int findCircleNum(vector>& M) { + bool check[M.size()] {}; + queue q; + int sol = 0; + for(int i = 0; i < M.size(); i++){ + if(!check[i]) sol++, q.push(i), check[i] = 1; + while(!q.empty()){ + int res = q.front(); + q.pop(); + for(int n = 0; n < M.size(); n++) + if(M[res][n] && !check[n]) q.push(n), check[n] = 1; + } + } + return sol; + } +}; + diff --git "a/Week_03/id_40/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\200\235\347\273\264\345\233\276.png" "b/Week_03/id_40/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\200\235\347\273\264\345\233\276.png" new file mode 100644 index 00000000..4f5286d7 Binary files /dev/null and "b/Week_03/id_40/\346\225\260\346\215\256\347\273\223\346\236\204\344\270\216\347\256\227\346\263\225\346\200\235\347\273\264\345\233\276.png" differ diff --git a/Week_03/id_41/LeetCode_102_41.cpp b/Week_03/id_41/LeetCode_102_41.cpp new file mode 100644 index 00000000..cac487a4 --- /dev/null +++ b/Week_03/id_41/LeetCode_102_41.cpp @@ -0,0 +1,38 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + * T(n) = O(N) + * S(n) = O(N) + */ +class Solution { +public: + vector> levelOrder(TreeNode* root) { + vector> res; + queue q; + if (root == nullptr) + return res; + q.push(root); + while (!q.empty()) + { + vector level; + int n = q.size(); + for (int i = 0; i < n; i++) + { + auto current = q.front(); + q.pop(); + if (current->left) + q.push(current->left); + if (current->right) + q.push(current->right); + level.push_back(current->val); + } + res.push_back(level); + } + return res; + } +}; diff --git a/Week_03/id_41/LeetCode_103_41.cpp b/Week_03/id_41/LeetCode_103_41.cpp new file mode 100644 index 00000000..0f13559d --- /dev/null +++ b/Week_03/id_41/LeetCode_103_41.cpp @@ -0,0 +1,74 @@ +/* + * @lc app=leetcode id=103 lang=cpp + * + * [103] Binary Tree Zigzag Level Order Traversal + */ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + * T(n) = O(N) + * S(n) = O(N) + */ +class Solution +{ +public: + vector> zigzagLevelOrder(TreeNode *root) + { + vector> res; + if (root == nullptr) + return res; + deque dq; + bool leftToRight = false; + + dq.push_back(root); + + while (!dq.empty()) + { + int n = dq.size(); + vector level; + TreeNode *current; + leftToRight = !leftToRight; + + for (int i = 0; i < n; i++) + { + if (leftToRight) + { + current = dq.back(); + dq.pop_back(); + level.push_back(current->val); + + if (current->left) + { + dq.push_front(current->left); + } + if (current->right) + { + dq.push_front(current->right); + } + } + else + { + current = dq.front(); + dq.pop_front(); + level.push_back(current->val); + if (current->right) + { + dq.push_back(current->right); + } + if (current->left) + { + dq.push_back(current->left); + } + } + } + if (!level.empty()) + res.push_back(std::move(level)); + } + return res; + } +}; diff --git a/Week_03/id_41/LeetCode_107_41.cpp b/Week_03/id_41/LeetCode_107_41.cpp new file mode 100644 index 00000000..1cb46ba3 --- /dev/null +++ b/Week_03/id_41/LeetCode_107_41.cpp @@ -0,0 +1,42 @@ +/* + * @lc app=leetcode id=107 lang=cpp + * + * [107] Binary Tree Level Order Traversal II + */ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + * Without reverse, use in order traversal. + * T(n) = O(N) + * S(n) = O(N) + */ +class Solution +{ +public: + vector> levelOrderBottom(TreeNode *root) + { + int h = getTreeheight(root); + vector> res(h); + inOrderTraversal(root, h - 1, res); + return res; + } + + int getTreeheight(TreeNode *root) + { + return root ? (max(getTreeheight(root->left), getTreeheight(root->right)) + 1) : 0; + } + + void inOrderTraversal(TreeNode *root, int level, vector> &res) + { + if (root == nullptr) + return; + inOrderTraversal(root->left, level - 1, res); + res[level].push_back(root->val); + inOrderTraversal(root->right, level - 1, res); + } +}; diff --git a/Week_03/id_41/LeetCode_111_41.cpp b/Week_03/id_41/LeetCode_111_41.cpp new file mode 100644 index 00000000..a69a4fe7 --- /dev/null +++ b/Week_03/id_41/LeetCode_111_41.cpp @@ -0,0 +1,60 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + * BFS: T(n) = O(K) K为树的最小深度 + * DFS: T(n) = O(N) N为树结点数 + */ + +DFS(C): +static inline int min(int a, int b) +{ + return a < b ? a : b; +} + +int minDepth(struct TreeNode* root){ + if (root == NULL) + return 0; + int left = minDepth(root->left); + int right = minDepth(root->right); + + return (left == 0 || right == 0) ? (left + right + 1) : min(left, right) + 1; +} + + + +BFS: +class Solution { +public: + int minDepth(TreeNode* root) { + if (root == NULL) + return 0; + queue q; + int depth = 0; + q.push(root); + while (!q.empty()) + { + int n = q.size(); + depth++; + + for (int i = 0; i < n; i++) + { + TreeNode* r = q.front(); + q.pop(); + // 注意左右子树同时为空的情况 + if (r->left == NULL && r->right == NULL) + return depth; + if (r->left != NULL) + q.push(r->left); + if (r->right != NULL) + q.push(r->right); + } + } + return depth; + } +}; + diff --git a/Week_03/id_41/LeetCode_127_41.cpp b/Week_03/id_41/LeetCode_127_41.cpp new file mode 100644 index 00000000..8cfda153 --- /dev/null +++ b/Week_03/id_41/LeetCode_127_41.cpp @@ -0,0 +1,48 @@ +/* + * @lc app=leetcode id=127 lang=cpp + * + * [127] Word Ladder + * T(n) = O(word_count * num_char_in_word) + */ +class Solution +{ +public: + int ladderLength(string beginWord, string endWord, vector &wordList) + { + if (!beginWord.compare(endWord)) + return 1; + unordered_set dict(wordList.begin(), wordList.end()); + queue toVisit; + toVisit.push(beginWord); + int dist = 2; + while (!toVisit.empty()) + { + int n = toVisit.size(); + for (int i = 0; i < n; i++) + { + string word = toVisit.front(); + toVisit.pop(); + for (int i = 0; i < word.size(); i++) + { + // process current + char letter = word[i]; + for (int k = 0; k < 26; k++) + { + word[i] = 'a' + k; + if (dict.find(word) != dict.end()) + { + if (word == endWord) + return dist; + toVisit.push(word); + dict.erase(word); + } + } + // restore + word[i] = letter; + } + } + dist++; + } + return 0; + } +}; diff --git a/Week_03/id_41/LeetCode_200_41.cpp b/Week_03/id_41/LeetCode_200_41.cpp new file mode 100644 index 00000000..8304a31f --- /dev/null +++ b/Week_03/id_41/LeetCode_200_41.cpp @@ -0,0 +1,100 @@ +class UnionFind +{ +public: + UnionFind(int n) : roots(n), rank(n, 0) + { + for (int i = 0; i < n; ++i) + { + roots[i] = i; + } + } + + bool uni(int p, int q) + { + int pRoot = find(p); + int qRoot = find(q); + if (pRoot == qRoot) + return false; + + // use rank + if (rank[pRoot] < rank[qRoot]) + { + roots[pRoot] = qRoot; + } + else if (rank[pRoot] > rank[qRoot]) + { + roots[qRoot] = pRoot; + } + else + { + roots[qRoot] = pRoot; + rank[pRoot]++; + } + + return true; + } + + int find(int node) + { + if (roots[node] == node) + { + return node; + } + //path compression + roots[node] = find(roots[node]); + return roots[node]; + } + + bool connected(int p, int q) + { + return find(p) == find(q); + } + +private: + vector roots; + vector rank; +}; + +class Solution +{ +public: + int numIslands(vector> &grid) + { + if (grid.empty()) + return 0; + + // pruning: only search right/down. + int dx[2] = {1, 0}; + int dy[2] = {0, 1}; + + int m = grid.size(); + int n = grid[0].size(); + UnionFind uf(m * n); + for (int i = 0; i < m; i++) + { + for (int j = 0; j < n; j++) + { + if (grid[i][j] == '1') + { + count++; + for (int k = 0; k < 2; k++) + { + int x = i + dx[k]; + int y = j + dy[k]; + if (x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == '1') + { + int node1 = i * n + j; + int node2 = x * n + y; + if (uf.uni(node1, node2)) + count--; + } + } + } + } + } + return count; + } + +private: + int count = 0; +}; diff --git a/Week_03/id_41/LeetCode_210_41.cpp b/Week_03/id_41/LeetCode_210_41.cpp new file mode 100644 index 00000000..b3324a13 --- /dev/null +++ b/Week_03/id_41/LeetCode_210_41.cpp @@ -0,0 +1,42 @@ +/* + * @lc app=leetcode id=210 lang=cpp + * + * [210] Course Schedule II + * T(n) = O(V+E) + * S(n) = O(V) + */ +class Solution +{ +public: + vector findOrder(int numCourses, vector>& prerequisites) + { + vector> vertex(numCourses); + vector indegrees(numCourses, 0); + vector topoOrder; + queue zeroQ; + int count = 0; + for (int i = 0; i < prerequisites.size(); i++) + { + int dst = prerequisites[i][0]; + int src = prerequisites[i][1]; + vertex[src].push_back(dst); + indegrees[dst]++; + } + for (int i = 0; i < numCourses; i++) + if (indegrees[i] == 0) + zeroQ.push(i); + while (!zeroQ.empty()) + { + int current = zeroQ.front(); + zeroQ.pop(); + for (auto neighbor : vertex[current]) + if (--indegrees[neighbor] == 0) + zeroQ.push(neighbor); + count++; + topoOrder.push_back(current); + } + if (count == numCourses) + return topoOrder; + return {}; + } +}; diff --git a/Week_03/id_41/LeetCode_295_41.cpp b/Week_03/id_41/LeetCode_295_41.cpp new file mode 100644 index 00000000..f4767716 --- /dev/null +++ b/Week_03/id_41/LeetCode_295_41.cpp @@ -0,0 +1,46 @@ +/* + * @lc app=leetcode id=295 lang=cpp + * + * [295] Find Median from Data Stream + * T(n) = O(1) + * S(n) = O(N) + */ +class MedianFinder +{ +public: + /** initialize your data structure here. */ + MedianFinder() + { + + } + + void addNum(int num) + { + small.push(num); + large.push(-small.top()); + small.pop(); + if (small.size() < large.size()) + { + small.push(-large.top()); + large.pop(); + } + } + + double findMedian() + { + if (small.size() > large.size()) + return small.top(); + else + return (small.top() - large.top()) / 2.0; + } +private: + priority_queue small; + priority_queue large; +}; + +/** + * Your MedianFinder object will be instantiated and called as such: + * MedianFinder* obj = new MedianFinder(); + * obj->addNum(num); + * double param_2 = obj->findMedian(); + */ diff --git a/Week_03/id_41/LeetCode_429_41.cpp b/Week_03/id_41/LeetCode_429_41.cpp new file mode 100644 index 00000000..914f20ab --- /dev/null +++ b/Week_03/id_41/LeetCode_429_41.cpp @@ -0,0 +1,49 @@ +/* + * @lc app=leetcode id=429 lang=cpp + * + * [429] N-ary Tree Level Order Traversal + */ +/* +// Definition for a Node. +class Node { +public: + int val; + vector children; + + Node() {} + + Node(int _val, vector _children) { + val = _val; + children = _children; + } +}; +T(n) = O(N); +S(n) = O(N); +*/ +class Solution { +public: + vector> levelOrder(Node* root) { + vector> res; + queue q; + if (root == nullptr) + return res; + q.push(root); + while (!q.empty()) + { + vector level; + int n = q.size(); + for (int i = 0; i < n; i++) + { + Node* current = q.front(); + q.pop(); + level.push_back(current->val); + // diff with Binary Tree part. + if (current->children.size() > 0) + for (auto child : current->children) + q.push(child); + } + res.push_back(level); + } + return res; + } +}; diff --git a/Week_03/id_41/LeetCode_529_41.cpp b/Week_03/id_41/LeetCode_529_41.cpp new file mode 100644 index 00000000..7bd71b13 --- /dev/null +++ b/Week_03/id_41/LeetCode_529_41.cpp @@ -0,0 +1,76 @@ +/* BFS without visited. + * T(n) = O(M*N) 遍历所有元素 + * S(n) = O(M*N) board的空间大小 + */ +class Solution +{ +public: + vector> updateBoard(vector> &board, vector &click) + { + rowMax = board.size(); + colMax = board[0].size(); + queue> q; + if (board[click[0]][click[1]] == 'M') + { + board[click[0]][click[1]] = 'X'; + return board; + } + q.push(make_pair(click[0], click[1])); + + while (!q.empty()) + { + int n = q.size(); + for (int i = 0; i < n; i++) + { + pair c = q.front(); + q.pop(); + if (board[c.first][c.second] == 'E') + { + int count = getSurroundingMineCount(board, c.first, c.second); + if (count == 0) + { + board[c.first][c.second] = 'B'; + + for (int k = 0; k < 8; k++) + { + if (isInBoard(c.first + dx[k], c.second + dy[k])) + { + q.push(make_pair(c.first + dx[k], c.second + dy[k])); + } + } + } + else + { + board[c.first][c.second] = '0' + count; + } + } + } + } + return board; + } + + bool isInBoard(int row, int col) + { + return (row >= 0) && (row < rowMax) && (col >= 0) && (col < colMax); + } + + int getSurroundingMineCount(vector> &board, int row, int col) + { + int count = 0; + for (int k = 0; k < 8; k++) + { + int x = row + dx[k]; + int y = col + dy[k]; + if (isInBoard(row + dx[k], col + dy[k])) + if (board[x][y] == 'M') + count++; + } + return count; + } + +private: + int rowMax; + int colMax; + int dx[8] = {-1, -1, -1, 0, 0, 1, 1, 1}; + int dy[8] = {-1, 0, 1, -1, 1, -1, 0, 1}; +}; \ No newline at end of file diff --git a/Week_03/id_41/LeetCode_547_41.c b/Week_03/id_41/LeetCode_547_41.c new file mode 100644 index 00000000..3b2e6a16 --- /dev/null +++ b/Week_03/id_41/LeetCode_547_41.c @@ -0,0 +1,69 @@ +/* + * @lc app=leetcode id=547 lang=c + * + * [547] Friend Circles + * T(n) = O(MSize) + * S(n) = O(MSize) + */ + +#define MAX_NUM_STUDENTS (200) + +static void makeSet(int *roots, int MSize) +{ + for (int i = 0; i < MSize; i++) + { + roots[i] = i; + } +} + +static int find(int *roots, int i) +{ + if (roots[i] == i) + return i; + + while (i != roots[i]) + { + roots[i] = roots[roots[i]]; + i = roots[i]; + } + return roots[i]; +} + +static void unionCircles(int** M, int* circles, int MSize) +{ + for (int i = 0; i < MSize - 1; i++) + { + for (int j = i + 1; j < MSize; j++) + { + int rootI = find(circles, i); + int rootJ = find(circles, j); + if (M[i][j] == 1) + { + circles[rootI] = rootJ; + } + } + } +} + +static int getCirCleCount(int* circles, int MSize) +{ + int count = 0; + for (int i = 0; i < MSize; i++) + { + if (circles[i] == i) + count++; + } + return count; +} + +int findCircleNum(int** M, int MSize, int* MColSize){ + int circlesNum = 0; + int circles[MAX_NUM_STUDENTS] = {0}; + if (MSize == 0 || *MColSize == 0) + return 0; + + makeSet(circles, MSize); + unionCircles(M, circles, MSize); + circlesNum = getCirCleCount(circles, MSize); + return circlesNum; +} diff --git a/Week_03/id_41/LeetCode_703_41.cpp b/Week_03/id_41/LeetCode_703_41.cpp new file mode 100644 index 00000000..df7733d6 --- /dev/null +++ b/Week_03/id_41/LeetCode_703_41.cpp @@ -0,0 +1,32 @@ +/* + * @lc app=leetcode id=703 lang=cpp + * + * [703] Kth Largest Element in a Stream + */ +class KthLargest { + +public: + KthLargest(int k, vector& nums) { + this->k = k; + for (int n : nums) + { + add(n); + } + } + + int add(int val) + { + if (q.size() < k) + q.push(val); + else if (val > q.top()) + { + q.pop(); + q.push(val); + } + return q.top(); + } + +private: + priority_queue, greater> q; + int k; +}; diff --git a/Week_03/id_42/leetCode_429_42.java b/Week_03/id_42/leetCode_429_42.java new file mode 100644 index 00000000..b06b33a4 --- /dev/null +++ b/Week_03/id_42/leetCode_429_42.java @@ -0,0 +1,46 @@ +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +class Node { + public int val; + public List children; + + public Node() {} + + public Node(int _val,List _children) { + val = _val; + children = _children; + } +}; + + + +public class leetCode_429_42 { + public List> levelOrder(Node root) { + List>res=new ArrayList<>(); + if(root==null) + return res; + Queue queue=new LinkedList<>(); + queue.offer(root); + while(!queue.isEmpty()){ + int len=queue.size(); + List temp=new ArrayList<>(); + Node curNode=null; + for(int i=0;i0){ + if(heap[i]heap[i+1]){ + i++; + } + if(heap[(i-1)/2]>heap[i]){ + swap((i-1)/2,i); + } + } + } + + private void swap(int i,int j){ + int cup = heap[i]; + heap[i] = heap[j]; + heap[j] = cup; + } + + public int add(int val) { + if(count < capacity){ + heap[count++]=val; + shiftUp(count -1); + }else if (val > heap[0]){ + heap[0] =val; + shiftDown(); + } + return heap[0]; + } + +} diff --git a/Week_03/id_6/LeetCode_104_6.php b/Week_03/id_6/LeetCode_104_6.php new file mode 100644 index 00000000..eb60d95a --- /dev/null +++ b/Week_03/id_6/LeetCode_104_6.php @@ -0,0 +1,25 @@ +val = $value; } + * } + */ +class Solution +{ + + /** + * @param TreeNode $root + * @return Integer + */ + function maxDepth($root) + { + if ($root == null) return 0; + return max($this->maxDepth($root->left), $this->maxDepth($root->right)) + 1; + } +} \ No newline at end of file diff --git a/Week_03/id_6/LeetCode_111_6.php b/Week_03/id_6/LeetCode_111_6.php new file mode 100644 index 00000000..4c05677e --- /dev/null +++ b/Week_03/id_6/LeetCode_111_6.php @@ -0,0 +1,32 @@ +val = $value; } + * } + */ +class Solution { + + /** + * @param TreeNode $root + * @return Integer + */ + function minDepth($root) + { + if ($root == null) return 0; + if (($root->left == null) && ($root->right == null)) return 1; + $min = PHP_INT_MAX; + if (null != $root->left) { + $min = min($this->minDepth($root->left), $min); + } + if (null != $root->right) { + $min = min($this->minDepth($root->right), $min); + } + return $min + 1; + } +} \ No newline at end of file diff --git a/Week_03/id_6/LeetCode_200_6.php b/Week_03/id_6/LeetCode_200_6.php new file mode 100644 index 00000000..54009914 --- /dev/null +++ b/Week_03/id_6/LeetCode_200_6.php @@ -0,0 +1,49 @@ +bfs($grid, $i, $j); + } + } + } + + return $sum; + } + + function bfs(&$grid, $i, $j) + { + $x = [$i - 1, $i, $i + 1, $i]; + $y = [$j, $j - 1, $j, $j + 1]; + $width = count($grid); + $height = count($grid[0]); + + for ($k = 0; $k < 4; $k ++) { + if ($x[$k] < 0 || $y[$k] < 0 || $x[$k] > $width - 1 || $y[$k] > $height - 1 || $grid[$x[$k]][$y[$k]] == '0') { + continue; + } + + $grid[$x[$k]][$y[$k]] = '0'; + $this->bfs($grid, $x[$k], $y[$k]); + } + } +} + +$grid = [["1","1","0","0","0"],["1","1","0","0","0"],["0","0","1","0","0"],["0","0","0","1","1"]]; +$sol = new Solution(); +var_dump($sol->numIslands($grid)); \ No newline at end of file diff --git a/Week_03/id_6/LeetCode_210_6.php b/Week_03/id_6/LeetCode_210_6.php new file mode 100644 index 00000000..594ef703 --- /dev/null +++ b/Week_03/id_6/LeetCode_210_6.php @@ -0,0 +1,58 @@ +findOrder($numCourses, $prerequisites)); \ No newline at end of file diff --git a/Week_03/id_6/LeetCode_295_6.php b/Week_03/id_6/LeetCode_295_6.php new file mode 100644 index 00000000..37e0aef0 --- /dev/null +++ b/Week_03/id_6/LeetCode_295_6.php @@ -0,0 +1,87 @@ +arr = []; + } + + /** + * @param Integer $num + * @return NULL + */ + function addNum($num) { + if (count($this->arr) == 0) { + $this->arr[] = $num; + return; + } + + $left = 0; + $right = count($this->arr) - 1; + + if ($this->arr[0] >= $num) { + array_unshift($this->arr, $num); + return; + } + + if ($this->arr[$right] <= $num) { + $this->arr[] = $num; + return; + } + + while ($left < $right) { + $mid = (int)($left + $right) / 2; + if ($num <= $this->arr[$mid]) { + $right = $mid; + } else { + $left = $mid + 1; + } + } + + for ($i = count($this->arr); $i > $left; $i --) { + $this->arr[$i] = $this->arr[$i - 1]; + } + $this->arr[$left] = $num; + return; + } + + /** + * @return Float + */ + function findMedian() { + $len = count($this->arr); + if ($len & 1) { + return $this->arr[(int)($len / 2)]; + } + + return (float)($this->arr[$len / 2 - 1] + $this->arr[$len / 2]) / 2; + } +} + +/** + * Your MedianFinder object will be instantiated and called as such: + * $obj = MedianFinder(); + * $obj->addNum($num); + * $ret_2 = $obj->findMedian(); + */ + +$obj = new MedianFinder(); +$obj->addNum(1);var_dump($obj->arr); +var_dump($obj->findMedian()); +$obj->addNum(2);var_dump($obj->arr); +var_dump($obj->findMedian()); +$obj->addNum(3);var_dump($obj->arr); +var_dump($obj->findMedian()); +$obj->addNum(14);var_dump($obj->arr); +var_dump($obj->findMedian()); +$obj->addNum(35);var_dump($obj->arr); +var_dump($obj->findMedian()); +$obj->addNum(19);var_dump($obj->arr); +var_dump($obj->findMedian()); +$obj->addNum(34);var_dump($obj->arr); +var_dump($obj->findMedian()); \ No newline at end of file diff --git a/Week_03/id_6/LeetCode_320_6.php b/Week_03/id_6/LeetCode_320_6.php new file mode 100644 index 00000000..a0641687 --- /dev/null +++ b/Week_03/id_6/LeetCode_320_6.php @@ -0,0 +1,54 @@ + 2) { + $n -= count($leaves); + foreach ($leaves as $k => $leaf) { + $root = current($adj[$leaf]); + $key = array_search($leaf, $adj[$root]); + unset($adj[$root][$key]); + unset($leaves[$k]); + if (count($adj[$root]) == 1) { + $leaves[] = $root; + } + } + } + + return $leaves; + } +} + +$n = 4; +$edges = [[1, 0], [1, 2], [1, 3]]; +$n = 6; +$edges = [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]]; + +$n = 11; +$edges = [[0,1],[0,2],[2,3],[0,4],[2,5],[5,6],[3,7],[6,8],[8,9],[9,10]]; + +$sol = new Solution(); +var_dump($sol->findMinHeightTrees($n, $edges)); \ No newline at end of file diff --git a/Week_03/id_6/LeetCode_329_6.php b/Week_03/id_6/LeetCode_329_6.php new file mode 100644 index 00000000..3bd61ebc --- /dev/null +++ b/Week_03/id_6/LeetCode_329_6.php @@ -0,0 +1,55 @@ +dfs($matrix, $i, $j)); + } + } + + return $len; + } + + function dfs($m, $i, $j) + { + if (isset($this->visited[$i][$j])) return $this->visited[$i][$j]; + + $x = [$i - 1, $i, $i + 1, $i]; + $y = [$j, $j - 1, $j, $j + 1]; + $width = count($m); + $height = count($m[0]); + $len = 1; + + for ($k = 0; $k < 4; $k ++) { + if ($x[$k] < 0 || $y[$k] < 0 || $x[$k] > $width - 1 || $y[$k] > $height - 1 || $m[$x[$k]][$y[$k]] <= $m[$i][$j]) { + continue; + } + $len = max($len, $this->dfs($m, $x[$k], $y[$k]) + 1); + } + + $this->visited[$i][$j] = $len; + return $len; + } +} + +$m = [[9,9,4],[6,6,8],[2,1,1]]; +$m = [[0],[1],[5],[5]]; +$sol = new Solution(); +var_dump($sol->longestIncreasingPath($m)); \ No newline at end of file diff --git a/Week_03/id_6/LeetCode_547_6.php b/Week_03/id_6/LeetCode_547_6.php new file mode 100644 index 00000000..50839b73 --- /dev/null +++ b/Week_03/id_6/LeetCode_547_6.php @@ -0,0 +1,39 @@ +visited[$i])) { + $this->bfs($M, $i); + $sum ++; + } + } + + return $sum; + } + + function bfs($m, $i) + { + for ($j = 0; $j < count($m); $j ++) { + if ($m[$i][$j] == '1' && !isset($this->visited[$j])) { + $this->visited[$j] = 1; + $this->bfs($m, $j); + } + } + } +} + +$M = [[1,0,0,1],[0,1,1,0],[0,1,1,1],[1,0,1,1]]; +$sol = new Solution(); +var_dump($sol->findCircleNum($M)); \ No newline at end of file diff --git a/Week_03/id_6/LeetCode_703_6.php b/Week_03/id_6/LeetCode_703_6.php new file mode 100644 index 00000000..88c6532b --- /dev/null +++ b/Week_03/id_6/LeetCode_703_6.php @@ -0,0 +1,97 @@ +k = $k; + $this->nums = $this->quick_sort($nums); + } + + /** + * @param Integer $val + * @return Integer + */ + function add($val) { + if (count($this->nums) == 0) { + $this->nums[] = $val; + return $val; + } + + if ($val <= $this->nums[$this->k - 1]) { + return $this->nums[$this->k - 1]; + } + + $arr = array_slice($this->nums, 0, $this->k); + $this->nums = array_merge($this->binary_sort($arr, $val), array_slice($this->nums, $this->k - 1)); + return $this->nums[$this->k - 1]; + } + + function quick_sort($arr) { + $len = count($arr); + + if ($len <= 1) + return $arr; + + $left = $right = array(); + $mid_value = $arr[0]; + + for ($i = 1; $i < $len; $i++) + if ($arr[$i] > $mid_value) + $left[] = $arr[$i]; + else + $right[] = $arr[$i]; + + return array_merge($this->quick_sort($left), (array)$mid_value, $this->quick_sort($right)); + } + + function binary_sort($arr, $num) + { + $left = 0; + $right = count($arr) - 1; + + if ($arr[0] <= $num) { + array_unshift($arr, $num); + return $arr; + } + + if ($arr[$right] >= $num) { + $arr[] = $num; + return $arr; + } + + while ($left < $right) { + $mid = (int)($left + $right) / 2; + if ($num > $arr[$mid]) { + $right = $mid; + } else { + $left = $mid + 1; + } + } + + for ($i = count($arr); $i > $left; $i --) { + $arr[$i] = $arr[$i - 1]; + } + $arr[$left] = $num; + return $arr; + } +} + +/** + * Your KthLargest object will be instantiated and called as such: + * $obj = KthLargest($k, $nums); + * $ret_1 = $obj->add($val); + */ + +$obj = new KthLargest(3, [4,5,8,2]); +var_dump($obj->add(3)); +var_dump($obj->add(5)); +var_dump($obj->add(10)); +var_dump($obj->add(9)); +var_dump($obj->add(4)); \ No newline at end of file diff --git a/Week_03/id_6/LeetCode_802_6.php b/Week_03/id_6/LeetCode_802_6.php new file mode 100644 index 00000000..da363dae --- /dev/null +++ b/Week_03/id_6/LeetCode_802_6.php @@ -0,0 +1,47 @@ +dfs($graph, $i)) { + $ret[] = $i; + } + } + + return $ret; + + } + + function dfs($graph, $start) + { + if (isset($this->state[$start])) return $this->state[$start] == 1; + + $this->state[$start] = 0; + foreach ($graph[$start] as $next) { + if (!$this->dfs($graph, $next)) { + return false; + } + } + + $this->state[$start] = 1; + return true; + } +} + +$graph = [[1,2],[2,3],[5],[0],[5],[],[]]; +$sol = new Solution(); +var_dump($sol->eventualSafeNodes($graph)); \ No newline at end of file diff --git a/Week_03/id_6/NOTE.md b/Week_03/id_6/NOTE.md index 107ea7d6..94e6e2ed 100644 --- a/Week_03/id_6/NOTE.md +++ b/Week_03/id_6/NOTE.md @@ -1 +1,38 @@ # 学习笔记 + +### 200 +老师上课讲过了,思路有了,这次自己用代码实现了一遍。 + +### 295 +看上去很简单,使用二分查找,然后找到位置插入。但是实际写代码要考虑边界值,以及要考虑二分查找的写法,因为要拿到具体插入的位置,而不是只要没有找到就返回,所以这里卡了几次提交。 + +看到评论里用大根堆和小根堆来解决很巧妙,可惜PHP没有这种数据结构,所以还是使用二分查找插入的方法了。 + +### 210 +学习了典型的有向无环图的拓扑排序的解法。 + +> 1. 选择一个入度为0的顶点并输出之; +> 2. 从网中删除此顶点及所有出边。 +> 3. 循环结束后,若输出的顶点数小于网中的顶点数,则输出“有回路”信息,否则输出的顶点序列就是一种拓扑序列。 + +### 104 +递归dfs深度查询,拿到左右子树中最大深度,加上根节点就为最大深度。 + +### 547 +最开始想到这道题跟岛屿问题是一样的,代码写完之后测试发现我理解错了,这里不一样的地方在于当每一行存在一个"1"的时候,那么这一点所在的行和列都算作一个朋友圈子,这就无法用岛屿问题来解决了。其实这样也比岛屿问题更简单些,只需要一次遍历行或列,累加每一个未访问过的点,然后记录每一个访问过为"1"的点的坐标,对这个点的行和列进行递归,最后返回计数值。 + +### 329 +用到深度优先dfs算法,从0,0起点开始遍历数组,递归计算每一点邻接4个点的最长路径,并记录下每一点最终计算求得的最大深度作为记忆,因为后面的点递归必然会用到之前计算过的点,那么记忆下来提高效率。 +对于长度和宽度的计算一定要搞清,不然很容易搞混自己定义的二维数组的长度和宽度。 + +### 320 +构建图的hash表,以入度为1的节点为叶子节点,循环清除叶子节点,并从hash表中移除叶子节点的根节点关联数据,并判断根节点大小是否为1,为1则将根节点入叶子节点队列,继续bfs循环处理,最后结束条件是只剩下1个或2个节点,将叶子节点队列剩余的数据打印输出。 + +### 111 +dfs取树最小深度,同104题取最大深度的不同在于,当一个节点只有左子树或右子树时需要分别判断计算。 + +### 802 +使用深度优先dfs算法计算每一个起点是否有环,有环则此节点为不安全节点。因为每个节点可能会被多次访问,不用每次都重新计算当前节点的状态,那么存储每一个遍历过的节点的安全状态,避免多次重复计算同一节点。 + +### 703 +初始化的时候使用快速排序使数组由大到小有序,之后每次插入截取到取的位置做二分排序插入,最后得出所求。 \ No newline at end of file diff --git a/Week_03/id_7/LeetCode_200_7.cs b/Week_03/id_7/LeetCode_200_7.cs new file mode 100644 index 00000000..169c8462 --- /dev/null +++ b/Week_03/id_7/LeetCode_200_7.cs @@ -0,0 +1,71 @@ +/* + * @lc app=leetcode.cn id=200 lang=csharp + * + * [200] 岛屿数量 + */ +using System.Collections; +using System.Collections.Generic; + +public class Solution { + // 解法1:DFS + // char[][] m_g; + // public int NumIslands (char[][] grid) { + // int nLands = 0; + // m_g = grid; + // for (int i = 0; i < m_g.Length; i++) { + // for (int j = 0; j < m_g[i].Length; j++) { + // if (m_g[i][j].Equals ('1')) + // nLands += sink (i, j); + // } + // } + // return nLands; + // } + // public int sink (int i, int j) { + // if (i < 0 || i >= m_g.Length || j < 0 || j >= m_g[i].Length) { + // return 0; + // } + // if (m_g[i][j].Equals ('0')) { + // return 0; + // } + // m_g[i][j] = '0'; + // sink (i + 1, j); + // sink (i - 1, j); + // sink (i, j + 1); + // sink (i, j - 1); + // return 1; + // } + + // 解法2:BFS + int[] dx = new int[] {-1, 1, 0, 0 }; + int[] dy = new int[] { 0, 0, -1, 1 }; + public int NumIslands (char[][] grid) { + int nLands = 0; + + for (int i = 0; i < grid.Length; i++) { + for (int j = 0; j < grid[i].Length; j++) { + if (grid[i][j] == '0') { + continue; + } + + nLands++; + Queue que = new Queue (); + que.Enqueue (new KeyValuePair (i, j)); + while (que.Count > 0) { + KeyValuePair kvp = (KeyValuePair) que.Dequeue (); + if (grid[kvp.Key][kvp.Value] == '0') { + continue; + } + grid[kvp.Key][kvp.Value] = '0'; + for (int k = 0; k < dx.Length; k++) { + int x = kvp.Key + dx[k], y = kvp.Value + dy[k]; + if (x >= 0 && x < grid.Length && y >= 0 && y < grid[kvp.Key].Length && grid[x][y] == '1') { + que.Enqueue (new KeyValuePair (x, y)); + } + } + } + } + } + + return nLands; + } +} \ No newline at end of file diff --git a/Week_03/id_7/LeetCode_295_7.cs b/Week_03/id_7/LeetCode_295_7.cs new file mode 100644 index 00000000..7198f467 --- /dev/null +++ b/Week_03/id_7/LeetCode_295_7.cs @@ -0,0 +1,147 @@ +/* + * @lc app=leetcode.cn id=295 lang=csharp + * + * [295] 数据流的中位数 + */ +using System.Collections.Generic; + +// 方法1:暴力法,每插入一个数,就排序整个序列,一般排序时间复杂度为O(nlogn),取中位数为O(1),所以总的来说是O(nlogn) +// 这里就不写了,实测提交会超时 + +// 方法2:使用插入排序,插入排序的时间复杂度为O(logn),需要添加的n个数的话,遍历造成的时间复杂度为O(n),所以总的来说是O(n) +// public class MedianFinder1 { + +// private List m_lst; +// /** initialize your data structure here. */ +// public MedianFinder1 () { +// m_lst = new List (); +// } + +// public void AddNum (int num) { +// if (m_lst.Count == 0) { +// m_lst.Add (num); +// return; +// } +// m_lst.Insert (GetMedianIndex (0, m_lst.Count, num), num); +// } + +// public int GetMedianIndex (int start, int end, int num) { +// if (start == end) { +// return start; +// } +// int mid = (end - start) / 2 + start; +// if (m_lst[mid] > num) { +// return GetMedianIndex (start, mid, num); +// } else if (m_lst[mid] < num) { +// return GetMedianIndex (mid + 1, end, num); +// } else { +// return mid; +// } +// } + +// public double FindMedian () { +// if (m_lst.Count == 1) { +// return m_lst[0]; +// } +// if (m_lst.Count % 2 == 1) { +// return m_lst[m_lst.Count / 2]; +// } else { +// return (double) (m_lst[m_lst.Count / 2 - 1] + m_lst[m_lst.Count / 2]) / 2; +// } +// } +// } + +// 方法3:两个优先队列(自己使用sortedlist实现,效率不如二分法),一个降序,一个升序 +public class MedianFinder { + + PriorityQueue pqo = new PriorityQueue (true); + PriorityQueue pqi = new PriorityQueue (); + + /** initialize your data structure here. */ + public MedianFinder () { } + + public void AddNum (int num) { + pqo.Enqueue (num); + + pqi.Enqueue (pqo.Dequeue ()); + + if (pqo.Size () < pqi.Size ()) { + pqo.Enqueue (pqi.Dequeue ()); + } + } + + public double FindMedian () { + return pqo.Size () > pqi.Size () ? (double) pqo.Top () : (pqo.Top () + pqi.Top ()) * 0.5; + } +} + +class DescendedDateComparer : IComparer { + public int Compare (int x, int y) { + // use the default comparer to do the original comparison for int + int ascendingResult = Comparer.Default.Compare (x, y); + + // turn the result around + return 0 - ascendingResult; + } +} + +public class PriorityQueue { + private SortedList m_sortedlst; + private int m_nCount; + + public PriorityQueue (bool blDescending = false) { + if (blDescending) { + m_sortedlst = new SortedList (new DescendedDateComparer ()); + } else { + m_sortedlst = new SortedList (); + } + m_nCount = 0; + } + + public void Enqueue (int num) { + if (m_sortedlst.ContainsKey (num)) { + m_sortedlst[num]++; + } else { + m_sortedlst.Add (num, 1); + } + m_nCount++; + } + + public int Dequeue () { + + if (m_nCount == 0) { + return 0; + } + + int ans = m_sortedlst.Keys[0]; + + if (m_sortedlst.GetValueOrDefault (ans) > 1) { + m_sortedlst[ans] = m_sortedlst.Values[0] - 1; + } else { + m_sortedlst.Remove (ans); + } + + m_nCount--; + + return ans; + } + + public int Top () { + if (m_nCount == 0) { + return 0; + } + + return m_sortedlst.Keys[0]; + } + + public int Size () { + return m_nCount; + } +} + +/** + * Your MedianFinder object will be instantiated and called as such: + * MedianFinder obj = new MedianFinder(); + * obj.AddNum(num); + * double param_2 = obj.FindMedian(); + */ \ No newline at end of file diff --git a/Week_03/id_7/LeetCode_703_7.cs b/Week_03/id_7/LeetCode_703_7.cs new file mode 100644 index 00000000..55dd4f22 --- /dev/null +++ b/Week_03/id_7/LeetCode_703_7.cs @@ -0,0 +1,63 @@ +/* + * @lc app=leetcode.cn id=703 lang=csharp + * + * [703] 数据流中的第K大元素 + */ +using System; + +public class KthLargest { + int[] heap; + // 堆中已经存储的数据个数 + int count; + // 堆容量 + int capacity; + + public KthLargest (int k, int[] nums) { + heap = new int[k]; + capacity = k; + count = 0; + for (int i = 0; i < nums.Length; i++) { + Add (nums[i]); + } + } + + public int Add (int val) { + if (count < capacity) { + heap[count] = val; + int i = count; + while (i > 0) { + int nPIndex = (i - 1) / 2; + if (heap[i] < heap[nPIndex]) { + int temp = heap[i]; + heap[i] = heap[nPIndex]; + heap[nPIndex] = temp; + } + i = nPIndex; + } + count++; + } else if (val > heap[0]) { + heap[0] = val; + int i = 0; + while (i * 2 + 1 < count) { + i = i * 2 + 1; + if (i + 1 < count && heap[i] > heap[i + 1]) { + i++; + } + int nPIndex = (i - 1) / 2; + if (heap[nPIndex] > heap[i]) { + int temp = heap[nPIndex]; + heap[nPIndex] = heap[i]; + heap[i] = temp; + } + } + } + + return heap[0]; + } +} + +/** + * Your KthLargest object will be instantiated and called as such: + * KthLargest obj = new KthLargest(k, nums); + * int param_1 = obj.Add(val); + */ \ No newline at end of file diff --git a/Week_03/id_7/NOTE.md b/Week_03/id_7/NOTE.md index 107ea7d6..090285c3 100644 --- a/Week_03/id_7/NOTE.md +++ b/Week_03/id_7/NOTE.md @@ -1 +1,2 @@ # 学习笔记 +test diff --git a/Week_03/id_8/Leetcode_104_8.java b/Week_03/id_8/Leetcode_104_8.java new file mode 100644 index 00000000..e4e25805 --- /dev/null +++ b/Week_03/id_8/Leetcode_104_8.java @@ -0,0 +1,17 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +class Solution { + public int maxDepth(TreeNode root) { + if (root == null) { + return 0; + } + return Math.max(maxDepth(root.left), maxDepth(root.right))+1; + } +} \ No newline at end of file diff --git a/Week_03/id_8/Leetcode_703_8.java b/Week_03/id_8/Leetcode_703_8.java new file mode 100644 index 00000000..b5600b5c --- /dev/null +++ b/Week_03/id_8/Leetcode_703_8.java @@ -0,0 +1,29 @@ +class KthLargest { + + PriorityQueue q; + int k; + + public KthLargest(int k, int[] nums) { + this.k = k; + q = new PriorityQueue(k); + for(int i:nums) { + add(i); + } + } + + public int add(int val) { + if (q.size() < k) { + q.offer(val); + } else if(q.peek() < val) { + q.poll(); + q.offer(val); + } + return q.peek(); + } +} + +/** + * Your KthLargest object will be instantiated and called as such: + * KthLargest obj = new KthLargest(k, nums); + * int param_1 = obj.add(val); + */ \ No newline at end of file diff --git a/Week_03/id_8/NOTE.md b/Week_03/id_8/NOTE.md index 107ea7d6..6dadb86f 100644 --- a/Week_03/id_8/NOTE.md +++ b/Week_03/id_8/NOTE.md @@ -1 +1,77 @@ # 学习笔记 + +### 题目1 + +[Leetcode#104 二叉树的最大深度](https://leetcode-cn.com/problems/maximum-depth-of-binary-tree//) +### 难点分析 +递归的模板定义,终止条件的定义 + +### 解题思路 +> 终止条件:空节点的高度是1 + drill down条件:左右子树递归的返回值的max+1 + +### 参考代码AC +```Java +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +class Solution { + public int maxDepth(TreeNode root) { + if (root == null) { + return 0; + } + return Math.max(maxDepth(root.left), maxDepth(root.right))+1; + } +} +``` + + +### 题目2 +[Leetcode#703 数据流中的第K大元素](https://leetcode-cn.com/problems/kth-largest-element-in-a-stream/) + +### 难点分析 +这道题的难点在于怎样思考到使用小顶堆的模型来抽象这种场景 + +### 解题思路 +> 首先要想到使用堆这种数据结构来抽象这种第K大元素的场景,这种只有靠平时的积累。 +而且要想到使用小顶堆来管理,而小顶堆在java中可以使用一个容量为k的优先队列,就可以很好地 +解决这个问题。因为第K大元素,换句话说其实就是K个的优先队列里面最小的那个元素,就是头指针。 + +### 参考代码AC +```Java +class KthLargest { + + PriorityQueue q; + int k; + + public KthLargest(int k, int[] nums) { + this.k = k; + q = new PriorityQueue(k); + for(int i:nums) { + add(i); + } + } + + public int add(int val) { + if (q.size() < k) { + q.offer(val); + } else if(q.peek() < val) { + q.poll(); + q.offer(val); + } + return q.peek(); + } +} + +/** + * Your KthLargest object will be instantiated and called as such: + * KthLargest obj = new KthLargest(k, nums); + * int param_1 = obj.add(val); + */ +``` \ No newline at end of file diff --git a/Week_03/id_9/LeetCode_104_9.java b/Week_03/id_9/LeetCode_104_9.java new file mode 100644 index 00000000..848cacd9 --- /dev/null +++ b/Week_03/id_9/LeetCode_104_9.java @@ -0,0 +1,39 @@ +package com.github.lifelab.leetcode.problemset; + +/** + * 二叉树的最大深度 @https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/ + * + * @author Weichao Li (liweichao0102@gmail.com) + * @since 2019-06-09 + */ +public class Solution104 { + + public int maxDepth(TreeNode root) { + return depth(root, 0); + } + + private int depth(TreeNode node, int depth) { + + if (node == null) { + return 0; + } + + depth++; + + if (node.left == null && node.right == null) { + return depth; + } + + int l = 0, r = 0; + + if (node.left != null) { + l = depth(node.left, depth); + } + + if (node.right != null) { + r = depth(node.right, depth); + } + + return Math.max(l, r); + } +} diff --git a/Week_03/id_9/LeetCode_111_9.java b/Week_03/id_9/LeetCode_111_9.java new file mode 100644 index 00000000..a63dea9b --- /dev/null +++ b/Week_03/id_9/LeetCode_111_9.java @@ -0,0 +1,40 @@ +package com.github.lifelab.leetcode.problemset; + +import java.util.Objects; + +/** + * 二叉树的最小深度 @see https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/submissions/ + * + * @author Weichao Li (liweichao0102@gmail.com) + * @since 2019-07-07 + */ +public class Solution111 { + + public int minDepth(TreeNode root) { + return minDepth(root, 0); + } + + public int minDepth(TreeNode node, int currentDepth) { + + if (node == null) { + return currentDepth; + } + + currentDepth++; + + if (Objects.isNull(node.left) && Objects.isNull(node.right)) { + return currentDepth; + } else { + + int minDepth = Integer.MAX_VALUE; + if (node.left != null) { + minDepth = Math.min(minDepth(node.left, currentDepth), minDepth); + } + if (node.right != null) { + minDepth = Math.min(minDepth(node.right, currentDepth), minDepth); + } + return minDepth; + } + + } +} diff --git a/Week_03/id_9/LeetCode_547_9.java b/Week_03/id_9/LeetCode_547_9.java new file mode 100644 index 00000000..71182461 --- /dev/null +++ b/Week_03/id_9/LeetCode_547_9.java @@ -0,0 +1,50 @@ +package com.github.lifelab.leetcode.problemset; + +/** + * 朋友圈 @https://leetcode-cn.com/problems/friend-circles/ + * + * @author Weichao Li (liweichao0102@gmail.com) + * @since 2019-07-07 + */ +public class Solution547 { + + + public int findCircleNum(int[][] M) { + //二维数组长度,即所有人的个数 + int length = M.length; + //统计朋友圈个数 + int count = 0; + //访问标志 + boolean[] flag = new boolean[length]; + //对于每个人 + for (int i = 0; i < length; i++) { + //如果未被访问 + if (!flag[i]) { + //深度优先搜索,访问 + dfs(i, M, flag); + //朋友圈个数+1 + count++; + } + } + return count; + } + + /** + * 深度优先搜索 + * + * @param i 人的位置 + * @param M 朋友圈 + * @param flag 访问标识 + */ + public void dfs(int i, int[][] M, boolean[] flag) { + //当前位占位 + flag[i] = true; + + for (int j = 0; j < M[i].length; j++) { + + if (!flag[j] && M[i][j] == 1) { + dfs(j, M, flag); + } + } + } +} diff --git a/Week_04/id_1/LeetCode_169_1.java b/Week_04/id_1/LeetCode_169_1.java new file mode 100644 index 00000000..18cb8612 --- /dev/null +++ b/Week_04/id_1/LeetCode_169_1.java @@ -0,0 +1,32 @@ +package week01; + +import java.util.HashMap; +import java.util.Map; + +/** + * Auth:luoxiang + * Time:2019/6/30 5:31 PM + * Desc: 求众数 + */ +public class LeetCode_169_1 { + + public static void main(String[] args) { + System.out.println(new LeetCode_169_1().majorityElement(new int[]{3,2,3})); + System.out.println(new LeetCode_169_1().majorityElement(new int[]{2,2,1,1,1,2,2})); + } + + public int majorityElement(int[] nums) { + if (nums == null || nums.length == 0) return 0; + Map map = new HashMap<>(); + for (int num : nums) { + int temp = map.getOrDefault(num, 0) + 1; + if (temp <= (nums.length / 2)) { + map.put(num, map.getOrDefault(num, 0) + 1); + } else { + return num; + } + + } + throw new IllegalArgumentException("异常"); + } +} diff --git a/Week_04/id_1/LeetCode_198_1.java b/Week_04/id_1/LeetCode_198_1.java new file mode 100644 index 00000000..44637850 --- /dev/null +++ b/Week_04/id_1/LeetCode_198_1.java @@ -0,0 +1,25 @@ +package week04; + +/** + * Auth:luoxiang + * Time:2019/6/30 5:46 PM + * Desc: DP 打家劫舍 + */ +public class LeetCode_198_1 { + public static void main(String[] args) { + System.out.println(new LeetCode_198_1().rob(new int[]{1,2,3,1})); + System.out.println(new LeetCode_198_1().rob(new int[]{2,7,9,3,1})); + } + + public int rob(int[] nums) { + int len = nums.length; + if (len == 0 || len == 1) return len == 0 ? 0 : nums[0]; + int[] dp = new int[len]; + dp[0]=nums[0]; + dp[1]=Math.max(nums[0],nums[1]); + for(int i=2;i 0; i--) { + for (int j = 0; j < words.length; j++) { + if (words[j].length() == i) { + int temp = i; + for (int k = j - 1; k >= 0; k--) { + if (words[j].substring(0, temp - 1).equals(words[k])) { + temp--; + } + } + if (temp == 1) return words[j]; + } + } + } + return ""; + } +} diff --git a/Week_04/id_10/Leecode-123-10.go b/Week_04/id_10/Leecode-123-10.go new file mode 100644 index 00000000..5978b078 --- /dev/null +++ b/Week_04/id_10/Leecode-123-10.go @@ -0,0 +1,36 @@ +package leecode + +func maxProfit(prices []int) int { + if len(prices) == 0 { + return 0 + } + // dp[i][k][t] i 代表第几天 k 代表买入股票k次 t 是否持有股票 0 否 1 是 + dp := make([][][]int, len(prices)) + n := len(prices) + for i := 0; i < len(dp); i++ { + dp[i] = [][]int{[]int{0, 0}, []int{0, 0}, []int{0, 0}} + } + const INT_MIN = 0 - (1e9 + 7) + dp[0][1][1] = 0 - prices[0] + dp[0][1][0] = INT_MIN + dp[0][2][0] = INT_MIN + dp[0][2][1] = INT_MIN + for i := 1; i < len(prices); i++ { + dp[i][1][0] = max(dp[i-1][1][1]+prices[i], dp[i-1][1][0]) + dp[i][1][1] = max(0-prices[i], dp[i-1][1][1]) + dp[i][2][0] = max(dp[i-1][2][1]+prices[i], dp[i-1][2][0]) + dp[i][2][1] = max(dp[i-1][1][0]-prices[i], dp[i-1][2][1]) + } + return max(0, dp[n-1][1][0], dp[n-1][2][0]) + +} + +func max(arr ...int) int { + maxNum := arr[0] + for i := 1; i < len(arr); i++ { + if maxNum < arr[i] { + maxNum = arr[i] + } + } + return maxNum +} diff --git a/Week_04/id_10/Leecode-169-10.go b/Week_04/id_10/Leecode-169-10.go new file mode 100644 index 00000000..bd4aa71b --- /dev/null +++ b/Week_04/id_10/Leecode-169-10.go @@ -0,0 +1,62 @@ +package leecode + +func majorityElement(nums []int) int { + //分治法 + return helper(nums, 0, len(nums)-1) +} + +func helper(nums []int, low, high int) int { + if low == high { + return nums[low] + } + mid := (low + high) / 2 + left := helper(nums, low, mid) + right := helper(nums, mid+1, high) + if left == right { + return left + } + leftCount := 0 + rightCount := 0 + for i := low; i <= high; i++ { + if nums[i] == left { + leftCount++ + } else if nums[i] == right { + rightCount++ + } + } + if leftCount >= rightCount { + return left + } + return right +} + +func majorityElement3(nums []int) int { + // 题解 Boyer-Moore 投票算法 + count := 1 + num := nums[0] + for i := 1; i < len(nums); i++ { + if count == 0 { + num = nums[i] + count = 1 + } else if num == nums[i] { + count++ + } else { + count-- + } + } + return num +} + +func majorityElement2(nums []int) int { + //使用 map 记录个数 + numMap := make(map[int]int) + numLen := len(nums) + for i := 0; i < numLen; i++ { + num := nums[i] + numMap[num]++ + if numMap[num] > numLen/2 { + return num + } + } + return -1 +} diff --git a/Week_04/id_10/Leecode-208-10.go b/Week_04/id_10/Leecode-208-10.go new file mode 100644 index 00000000..b383e3f9 --- /dev/null +++ b/Week_04/id_10/Leecode-208-10.go @@ -0,0 +1,62 @@ +package leecode + +type Trie struct { + words []*Trie + val byte + is_end bool +} + +/** Initialize your data structure here. */ +func Constructor() Trie { + root := Trie{words: make([]*Trie, 26), is_end: false} + return root +} + +/** Inserts a word into the trie. */ +func (this *Trie) Insert(word string) { + root := this + for i := 0; i < len(word); i++ { + c := word[i] - 'a' + if root.words[c] == nil { + root.words[c] = &Trie{words: make([]*Trie, 26), val: word[i], is_end: false} + } + root = root.words[c] + } + root.is_end = true +} + +/** Returns if the word is in the trie. */ +func (this *Trie) Search(word string) bool { + root := this + for i := 0; i < len(word); i++ { + c := word[i] - 'a' + if root.words[c] != nil { + root = root.words[c] + } else { + return false + } + } + return root.is_end +} + +/** Returns if there is any word in the trie that starts with the given prefix. */ +func (this *Trie) StartsWith(prefix string) bool { + root := this + for i := 0; i < len(prefix); i++ { + c := prefix[i] - 'a' + if root.words[c] != nil { + root = root.words[c] + } else { + return false + } + } + return true +} + +/** + * Your Trie object will be instantiated and called as such: + * obj := Constructor(); + * obj.Insert(word); + * param_2 := obj.Search(word); + * param_3 := obj.StartsWith(prefix); + */ diff --git a/Week_04/id_10/Leecode-240-10.go b/Week_04/id_10/Leecode-240-10.go new file mode 100644 index 00000000..cfdeaa13 --- /dev/null +++ b/Week_04/id_10/Leecode-240-10.go @@ -0,0 +1,136 @@ +package leecode + +func searchMatrix(matrix [][]int, target int) bool { + //题解 + m := len(matrix) + if m == 0 { + return false + } + n := len(matrix[0]) + if n == 0 { + return false + } + i := 0 + j := n - 1 + for i < m && j >= 0 { + if matrix[i][j] == target { + return true + } else if matrix[i][j] < target { + i++ + } else { + j-- + } + } + return false +} + +func searchMatrix2(matrix [][]int, target int) bool { + //分治法 + m := len(matrix) + if m == 0 { + return false + } + n := len(matrix[0]) + if n == 0 { + return false + } + pos1 := []int{0, 0} + pos2 := []int{m - 1, n - 1} + return helper(matrix, pos1, pos2, target) +} + +func binary_search_hen(matrix [][]int, target int, x, y1, y2 int) bool { + // 横向二分查找 + if x >= len(matrix) { + return false + } + l := y1 + r := y2 + for l <= r { + mid := (l + r) / 2 + if matrix[x][mid] == target { + return true + } else if matrix[x][mid] < target { + l = mid + 1 + } else { + r = mid - 1 + } + } + return false +} + +func binary_search_shu(matrix [][]int, target int, y, x1, x2 int) bool { + // 竖向二分查找 + if y >= len(matrix[0]) { + return false + } + l := x1 + r := x2 + for l <= r { + mid := (l + r) / 2 + if matrix[mid][y] == target { + return true + } else if matrix[mid][y] < target { + l = mid + 1 + } else { + r = mid - 1 + } + } + return false +} + +func helper(matrix [][]int, pos1, pos2 []int, target int) bool { + if pos1[0] < 0 || pos1[1] < 0 || pos2[0] < pos1[0] || pos2[1] < pos1[1] { + return false + } + if pos1[0] == pos2[0] && pos1[1] == pos2[1] { + return matrix[pos1[0]][pos1[1]] == target + } + if pos1[0] == pos2[0] { + return binary_search_hen(matrix, target, pos1[0], pos1[1], pos2[1]) + } + if pos1[1] == pos2[1] { + return binary_search_shu(matrix, target, pos1[1], pos1[0], pos2[0]) + } + midx := (pos1[0] + pos2[0]) / 2 + midy := (pos1[1] + pos2[1]) / 2 + if matrix[midx][midy] == target { + return true + } + if matrix[midx][midy] < target { + ret := binary_search_hen(matrix, target, midx, midy+1, pos2[1]) + if ret { + return true + } + ret = binary_search_shu(matrix, target, midy, midx+1, pos2[0]) + if ret { + return true + } + ret = helper(matrix, []int{midx + 1, midy + 1}, pos2, target) + if ret { + return true + } + } else { + ret := binary_search_hen(matrix, target, midx, pos1[1], midy-1) + if ret { + return true + } + ret = binary_search_shu(matrix, target, midy, pos1[0], midx-1) + if ret { + return true + } + ret = helper(matrix, pos1, []int{midx - 1, midy - 1}, target) + if ret { + return true + } + } + ret := helper(matrix, []int{midx + 1, pos1[1]}, []int{pos2[0], midy - 1}, target) + if ret { + return true + } + ret = helper(matrix, []int{pos1[0], midy + 1}, []int{midx - 1, pos2[1]}, target) + if ret { + return true + } + return false +} diff --git a/Week_04/id_10/Leecode-455-10.go b/Week_04/id_10/Leecode-455-10.go new file mode 100644 index 00000000..5d1c09dd --- /dev/null +++ b/Week_04/id_10/Leecode-455-10.go @@ -0,0 +1,20 @@ +package leecode + +import "sort" + +func findContentChildren(g []int, s []int) int { + //贪心算法 饼干最大 配胃口最大的孩子 + sort.Ints(g) + sort.Ints(s) + gi := len(g) - 1 + si := len(s) - 1 + count := 0 + for gi >= 0 && si >= 0 { + if g[gi] <= s[si] { + si-- + count++ + } + gi-- + } + return count +} diff --git a/Week_04/id_10/Leecode-51-10.go b/Week_04/id_10/Leecode-51-10.go new file mode 100644 index 00000000..190ef3dc --- /dev/null +++ b/Week_04/id_10/Leecode-51-10.go @@ -0,0 +1,37 @@ +package leecode + +import "bytes" + +func solveNQueens(n int) [][]string { + // 回溯法 + result := make([][]string, 0) + pie := make([]bool, n*2) + na := make([]bool, n*2) + vlines := make([]bool, n) + qpos := make([]string, n) + var helper func(level int, qpos []string) + helper = func(level int, qpos []string) { + if level == n { + copystrs := make([]string, len(qpos)) + copy(copystrs, qpos) + result = append(result, copystrs) + return + } + for i := 0; i < n; i++ { + if !vlines[i] && !na[i-level+n] && !pie[i+level] { + vlines[i] = true + na[i-level+n] = true + pie[i+level] = true + s := bytes.Repeat([]byte("."), n) + s[i] = 'Q' + qpos[level] = string(s) + helper(level+1, qpos) + vlines[i] = false + na[i-level+n] = false + pie[i+level] = false + } + } + } + helper(0, qpos) + return result +} diff --git a/Week_04/id_10/Leecode-62-10.go b/Week_04/id_10/Leecode-62-10.go new file mode 100644 index 00000000..1b14b86c --- /dev/null +++ b/Week_04/id_10/Leecode-62-10.go @@ -0,0 +1,22 @@ +package leecode + +func uniquePaths(m int, n int) int { + if m == 0 || n == 0 { + return 0 + } + dp := make([][]int, n) + for i := 0; i < n; i++ { + dp[i] = make([]int, m) + dp[i][0] = 1 + } + for i := 0; i < m; i++ { + dp[0][i] = 1 + } + for i := 1; i < n; i++ { + for j := 1; j < m; j++ { + dp[i][j] = dp[i-1][j] + dp[i][j-1] + } + } + return dp[n-1][m-1] + +} diff --git a/Week_04/id_10/Leecode-70-10.go b/Week_04/id_10/Leecode-70-10.go new file mode 100644 index 00000000..c4f5bae2 --- /dev/null +++ b/Week_04/id_10/Leecode-70-10.go @@ -0,0 +1,24 @@ +package leecode + +func climbStairs2(n int) int { + // 递归方法 + if n == 1 || n == 2 { + return n + } + + return climbStairs(n-1) + climbStairs(n-2) +} + +func climbStairs(n int) int { + // dp方法 + if n == 1 || n == 2 { + return n + } + dp := make([]int, n) + dp[0] = 1 + dp[1] = 2 + for i := 2; i < n; i++ { + dp[i] = dp[i-1] + dp[i-2] + } + return dp[n-1] +} diff --git a/Week_04/id_10/Leecode-714-10.go b/Week_04/id_10/Leecode-714-10.go new file mode 100644 index 00000000..a37dee28 --- /dev/null +++ b/Week_04/id_10/Leecode-714-10.go @@ -0,0 +1,49 @@ +package leecode + +func maxProfit(prices []int, fee int) int { + if len(prices) == 0 { + return 0 + } + //dp解法 + dp := make([][]int, len(prices)) + for i := 0; i < len(dp); i++ { + dp[i] = make([]int, 2) + } + dp[0][0] = 0 // 第N天 手里没有股票 赚得最多的钱 + dp[0][1] = 0 - prices[0] // 第N天 手里有股票 赚得最多的钱 + for i := 1; i < len(prices); i++ { + dp[i][0] = max(dp[i-1][1]+prices[i]-fee, dp[i-1][0]) + dp[i][1] = max(dp[i-1][1], dp[i-1][0]-prices[i]) + } + return dp[len(prices)-1][0] +} + +func max(a, b int) int { + if a >= b { + return a + } + return b +} + +func maxProfit2(prices []int, fee int) int { + //贪心算法 + result := 0 + buytime := 0 + selltime := 0 + for i := 1; i < len(prices); i++ { + if selltime > buytime && prices[selltime]-prices[buytime] > fee && prices[selltime]-prices[i] > fee { + result += (prices[selltime] - prices[buytime]) - fee + buytime = i + selltime = i + } else if prices[buytime] > prices[i] { + buytime = i + selltime = i + } else if prices[selltime] < prices[i] { + selltime = i + } + } + if selltime > buytime && prices[selltime]-prices[buytime] > fee { + result += (prices[selltime] - prices[buytime]) - fee + } + return result +} diff --git a/Week_04/id_10/Leecode-78-10.go b/Week_04/id_10/Leecode-78-10.go new file mode 100644 index 00000000..47782f47 --- /dev/null +++ b/Week_04/id_10/Leecode-78-10.go @@ -0,0 +1,22 @@ +package leecode + +func subsets(nums []int) [][]int { + results := make([][]int, 0) + var helper func(nums []int, start int, result []int) + helper = func(nums []int, start int, result []int) { + if start >= len(nums) { + copyresult := make([]int, len(result)) + copy(copyresult, result) + results = append(results, copyresult) + return + } + // 每个数字两种选择 取 不取 + helper(nums, start+1, result) + result = append(result, nums[start]) + helper(nums, start+1, result) + result = result[0 : len(result)-1] + } + result := make([]int, 0) + helper(nums, 0, result) + return results +} diff --git a/Week_04/id_10/NOTE.md b/Week_04/id_10/NOTE.md index 107ea7d6..4c208467 100644 --- a/Week_04/id_10/NOTE.md +++ b/Week_04/id_10/NOTE.md @@ -1 +1,8 @@ # 学习笔记 +这次作业是算法课最后一次提交作业了,这一个月的训练很艰苦,但是对我的帮助很大,我本身工作压力也不小,要在工作之余,抽时间学习,不容易,坚持学习不松懈就更不容易了。越到后面,我越发现自己的热情在消退,一开始做算法题会仔细的分析,会做很详细的总结,做这些并不觉得辛苦。到了最后几周,多做一道题,多写几行字都变得很艰难,心中总有个声音:你的数量足够了,你写得够多了,可以完成作业了。 + +但是每次看到微信群中优秀同学之间的讨论、听到覃超老师直播中精彩的课程、每周review比我好得多的代码和学习总结。就觉得应该再努力努力,于是我又多做了几个题目,总结又多写了几行字。 + +现在回顾自己一个月里自己做的作业和总结,自己也感到骄傲,可能我的代码写得并不优秀,数量也不是那么多,我的总结也没什么技术含量,但是我尝试了,我努力了,我坚持了下来。同时我也看到了自己的不足,现在回头重新做之前的困难题,并不如想象的那么顺手,五毒神掌,我只练了两掌,刻意练习做起来真的很难。所以我还要继续努力。 + +一个月的时间很短暂,一眨眼就结束了,从这门课程中我不止学到了算法的知识,更学到了很多很有价值的方法和思想,很多是我需要继续努力精进的,课程的结束不是终点,而是一个新的起点,未来还需坚持下去,做更好的自己。 \ No newline at end of file diff --git a/Week_04/id_11/LeetCode_169_11.js b/Week_04/id_11/LeetCode_169_11.js new file mode 100644 index 00000000..c7e9c02a --- /dev/null +++ b/Week_04/id_11/LeetCode_169_11.js @@ -0,0 +1,27 @@ +/** + * @param {number[]} nums + * @return {number} + */ +var majorityElement = function(nums) { + + if(nums.length == 1){ + return nums[0] + } + + let maj = {} + let majNum + nums.forEach(num => { + if(maj[num] == null){ + maj[num] = 1 + } else { + maj[num] = maj[num] + 1 + if(maj[num] > nums.length/2){ + majNum = num + return + } + } + }) + + return majNum + +}; \ No newline at end of file diff --git a/Week_04/id_11/LeetCode_198_11.js b/Week_04/id_11/LeetCode_198_11.js new file mode 100644 index 00000000..20d25c1d --- /dev/null +++ b/Week_04/id_11/LeetCode_198_11.js @@ -0,0 +1,25 @@ +/** + * @param {number[]} nums + * @return {number} + */ +var rob = function(nums) { + + let _rob = [] + if(nums.length == 0){ + return 0 + } + if(nums.length == 1){ + return nums[0] + } + if(nums.length == 2){ + return Math.max(nums[0], nums[1]) + } + + _rob[0] = nums[0] + _rob[1] = Math.max(_rob[0], nums[1]) + for(let i = 2; i None: + """ + Inserts a word into the trie. + """ + curr = self.root + for ch in word: + if ch not in curr.child: + curr.child[ch] = Node(ch) + curr = curr.child.get(ch) + + curr.isWord = True + + + def search(self, word: str) -> bool: + """ + Returns if the word is in the trie. + """ + curr = self.root + for ch in word: + if ch in curr.child: + curr = curr.child.get(ch) + else: + return False + + return curr.isWord + + def startsWith(self, prefix: str) -> bool: + """ + Returns if there is any word in the trie that starts with the given prefix. + """ + curr = self.root + for ch in prefix: + if ch in curr.child: + curr = curr.child.get(ch) + else: + return False + + return True diff --git a/Week_04/id_15/LeetCode_211_015.py b/Week_04/id_15/LeetCode_211_015.py new file mode 100644 index 00000000..3021139a --- /dev/null +++ b/Week_04/id_15/LeetCode_211_015.py @@ -0,0 +1,13 @@ +class WordDictionary(object): + def __init__(self): + self.len2words = collections.defaultdict(list) + + def addWord(self, word): + self.len2words[len(word)].append(word) + + def search(self, word): + words = self.len2words[len(word)] + for i, char in enumerate(word): + words = [w for w in words if char in ('.', w[i])] + if not words: return False + return True diff --git a/Week_04/id_15/NOTE.md b/Week_04/id_15/NOTE.md index 107ea7d6..05855010 100644 --- a/Week_04/id_15/NOTE.md +++ b/Week_04/id_15/NOTE.md @@ -1 +1,8 @@ # 学习笔记 + +## 日常计划 + - 完成相对应的算法习题 + - 规划长期算法成长路线 + +## 下周计划 + - 争取通过算法考试 diff --git a/Week_04/id_18/LeetCode_169_18.java b/Week_04/id_18/LeetCode_169_18.java new file mode 100644 index 00000000..73252067 --- /dev/null +++ b/Week_04/id_18/LeetCode_169_18.java @@ -0,0 +1,61 @@ +package Week_04.id_18; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +/** + * @author LiveForExperience + * @date 2019/6/25 19:16 + */ +public class LeetCode_169_18 { + public int majorityElement(int[] nums) { + Map map = new HashMap<>(); + int len = nums.length / 2; + for (Integer num: nums) { + map.compute(num, (k, v) -> v == null ? 1 : v++); + if (map.get(num) > len) { + return num; + } + } + return 0; + } + + public int majorityElement1(int[] nums) { + Arrays.sort(nums); + return nums[nums.length / 2]; + } + + public int majorityElement2(int [] nums) { + return divideConquer(nums, 0, nums.length - 1); + } + + private int divideConquer(int[] nums, int left, int right) { + if (left == right) { + return nums[left]; + } + + int mid = (right - left) / 2 + left; + int leftMajorityNum = divideConquer(nums, left, mid); + int rightMajorityNum = divideConquer(nums, mid + 1, right); + + if (leftMajorityNum == rightMajorityNum) { + return leftMajorityNum; + } + + long leftCount = count(nums, leftMajorityNum, left, mid); + long rightCount = count(nums, rightMajorityNum, mid + 1, right); + + return leftCount > rightCount ? leftMajorityNum : rightMajorityNum; + } + + private int count(int[] nums, int num, int left, int right) { + int count = 0; + for (int i = left; i <= right; i++) { + if (nums[i] == num) { + count++; + } + } + return count; + } +} diff --git a/Week_04/id_18/LeetCode_208_18.java b/Week_04/id_18/LeetCode_208_18.java new file mode 100644 index 00000000..c9616a6f --- /dev/null +++ b/Week_04/id_18/LeetCode_208_18.java @@ -0,0 +1,87 @@ +package Week_04.id_18; + +/** + * @author LiveForExperience + * @date 2019/6/30 11:28 + */ +public class LeetCode_208_18 { + class Trie { + private static final int SIZE = 26; + private TrieNode root; + + public Trie() { + root = new TrieNode(); + } + + public void insert(String word) { + if (isEmpty(word)) { + return; + } + + char[] cs = word.toCharArray(); + TrieNode node = root; + for (char c: cs) { + int index = c - 'a'; + if (node.next[index] == null) { + node.next[index] = new TrieNode(); + node.next[index].data = c; + } + node = node.next[index]; + } + node.isWord = true; + } + + public boolean search(String word) { + if (isEmpty(word)) { + return false; + } + + char[] cs = word.toCharArray(); + TrieNode node = root; + for (char c: cs) { + int index = c - 'a'; + if (node.next[index] != null) { + node = node.next[index]; + } else { + return false; + } + } + + return node.isWord; + } + + public boolean startsWith(String prefix) { + if (isEmpty(prefix)) { + return false; + } + + TrieNode node = root; + char[] cs = prefix.toCharArray(); + for (char c: cs) { + int index = c - 'a'; + if (node.next[index] != null) { + node = node.next[index]; + } else { + return false; + } + } + + return true; + } + + private boolean isEmpty(String word) { + return word == null || word.length() == 0; + } + + private class TrieNode { + private char data; + private TrieNode[] next; + private boolean isWord; + + TrieNode() { + this.next = new TrieNode[SIZE]; + this.isWord = false; + } + } + } +} diff --git a/Week_04/id_18/LeetCode_455_18.java b/Week_04/id_18/LeetCode_455_18.java new file mode 100644 index 00000000..e23c2b40 --- /dev/null +++ b/Week_04/id_18/LeetCode_455_18.java @@ -0,0 +1,47 @@ +package Week_04.id_18; + +import java.util.Arrays; + +/** + * @author LiveForExperience + * @date 2019/6/26 12:59 + */ +public class LeetCode_455_18 { + public int findContentChildren(int[] g, int[] s) { + Arrays.sort(g); + Arrays.sort(s); + + int j = 0, count = 0, sl = s.length; + + for (int value : g) { + while (j < sl) { + if (value <= s[j++]) { + count++; + break; + } + } + + if (j == sl) { + break; + } + } + + return count; + } + + public int findContentChildren1(int[] g, int[] s) { + Arrays.sort(g); + Arrays.sort(s); + + int gi = 0, si = 0, gl = g.length, sl = s.length; + + while (gi < gl && si < sl) { + if (g[gi] <= s[si]) { + gi++; + } + + si++; + } + return gi; + } +} diff --git a/Week_04/id_18/LeetCode_53_18.java b/Week_04/id_18/LeetCode_53_18.java new file mode 100644 index 00000000..7791b992 --- /dev/null +++ b/Week_04/id_18/LeetCode_53_18.java @@ -0,0 +1,22 @@ +package Week_04.id_18; + +/** + * @author LiveForExperience + * @date 2019/6/30 16:35 + */ +public class LeetCode_53_18 { + public int maxSubArray(int[] nums) { + int result = nums[0]; + int sum = 0; + for (int num: nums) { + if (sum >= 0) { + sum += num; + } else { + sum = num; + } + result = Math.max(sum, result); + } + + return result; + } +} diff --git a/Week_04/id_18/LeetCode_70_18.java b/Week_04/id_18/LeetCode_70_18.java new file mode 100644 index 00000000..d4af3cd1 --- /dev/null +++ b/Week_04/id_18/LeetCode_70_18.java @@ -0,0 +1,61 @@ +package Week_04.id_18; + +/** + * @author LiveForExperience + * @date 2019/6/27 17:48 + */ +public class LeetCode_70_18 { + public int climbStairs(int n) { + return climbStairs(n, new int[n + 1]); + } + + private int climbStairs(int n, int[] nums) { + if (n <= 2) { + return n; + } + + if (nums[n] > 0) { + return nums[n]; + } + + int num = climbStairs(n - 1, nums) + climbStairs(n - 2, nums); + nums[n] = num; + + return num; + } + + public int climbStairs1(int n) { + if (n <= 2) { + return n; + } + + int[] dp = new int[n + 1]; + dp[1] = 1; + dp[2] = 2; + for (int i = 3; i <= n; i++) { + dp[i] = dp[i - 1] + dp[i - 2]; + } + return dp[n]; + } + + public int climbStairs2(int n) { + if (n <= 2) { + return n; + } + + int first = 1, second = 2; + for (int i = 3; i <= n; i++) { + int third = first + second; + first = second; + second = third; + } + + return second; + } + + public int climbStairs3(int n) { + double sqrt5 = Math.sqrt(5); + double fibn = Math.pow((1 + sqrt5) / 2, n + 1) - Math.pow((1 - sqrt5) / 2, n + 1); + return (int) (fibn / sqrt5); + } +} diff --git a/Week_04/id_18/LeetCode_720_18.java b/Week_04/id_18/LeetCode_720_18.java new file mode 100644 index 00000000..511c4916 --- /dev/null +++ b/Week_04/id_18/LeetCode_720_18.java @@ -0,0 +1,93 @@ +package Week_04.id_18; + +import java.util.*; + +/** + * @author LiveForExperience + * @date 2019/6/24 21:25 + */ +public class LeetCode_720_18 { + public String longestWord(String[] words) { + Arrays.sort(words); + String result = ""; + Set set = new HashSet<>(); + for (String word: words) { + if (word.length() == 1 || set.contains(word.substring(0, word.length() - 1))) { + set.add(word); + result = word.length() > result.length() ? word : result; + } + } + return result; + } + + public String longestWord1(String[] words) { + TrieTree trieTree = new TrieTree(); + for (String word: words) { + trieTree.insert(word); + } + + String result = ""; + int len = 0; + + for (String word: words) { + if (trieTree.isBuild(word) && word.length() > len) { + result = word; + len = result.length(); + } else if (trieTree.isBuild(word) && word.length() == len) { + char[] wordCs = word.toCharArray(); + char[] resultCs = result.toCharArray(); + for (int i = 0; i < len; i++) { + if (wordCs[i] < resultCs[i]) { + result = word; + break; + } else if (wordCs[i] > resultCs[i]) { + break; + } + } + } + } + + return result; + } + + private class TrieTreeNode { + private char data; + private boolean isWord; + private TrieTreeNode[] next; + + public TrieTreeNode(char data) { + this.data = data; + this.next = new TrieTreeNode[26]; + } + } + + private class TrieTree { + TrieTreeNode root = new TrieTreeNode('/'); + public void insert(String word) { + char[] cs = word.toCharArray(); + TrieTreeNode node = root; + for (char c: cs) { + int index = c - 'a'; + if (node.next[index] == null) { + node.next[index] = new TrieTreeNode(c); + } + node = node.next[index]; + } + + node.isWord = true; + } + + public boolean isBuild(String word) { + char[] cs = word.toCharArray(); + TrieTreeNode node = root; + for (char c: cs) { + int index = c - 'a'; + if (!node.next[index].isWord) { + return false; + } + node = node.next[index]; + } + return true; + } + } +} diff --git a/Week_04/id_18/LeetCode_784_18.java b/Week_04/id_18/LeetCode_784_18.java new file mode 100644 index 00000000..c3be7537 --- /dev/null +++ b/Week_04/id_18/LeetCode_784_18.java @@ -0,0 +1,60 @@ +package Week_04.id_18; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author LiveForExperience + * @date 2019/6/27 12:47 + */ +public class LeetCode_784_18 { + List list = new ArrayList<>(); + public List letterCasePermutation(String S) { + dfs(new StringBuilder(S), 0); + return list; + } + + private void dfs(StringBuilder sb, int index) { + if (index == sb.length()) { + list.add(sb.toString()); + return; + } + + if (Character.isDigit(sb.charAt(index))) { + dfs(sb, index + 1); + } else { + char c = sb.charAt(index); + sb.setCharAt(index, Character.toLowerCase(c)); + dfs(sb, index + 1); + sb.setCharAt(index, Character.toUpperCase(c)); + dfs(sb, index + 1); + } + } + + public List letterCasePermutation1(String S) { + dfs(S.toCharArray(), 0); + return list; + } + + private void dfs(char[] cs, int index) { + if (index == cs.length) { + list.add(new String(cs)); + return; + } + + if (cs[index] < 'A') { + dfs(cs, index + 1); + } else { + char c = cs[index]; + if (c > 64 && c < 91) { + dfs(cs, index + 1); + cs[index] = (char) (cs[index] + 'a' - 'A'); + dfs(cs, index + 1); + } else { + dfs(cs, index + 1); + cs[index] = (char) (cs[index] + 'A' - 'a'); + dfs(cs, index + 1); + } + } + } +} diff --git a/Week_04/id_18/NOTE.md b/Week_04/id_18/NOTE.md index 107ea7d6..d169ee72 100644 --- a/Week_04/id_18/NOTE.md +++ b/Week_04/id_18/NOTE.md @@ -1 +1,767 @@ # 学习笔记 +## LeetCode_720_词典中最长的单词 +### 题目 +给出一个字符串数组words组成的一本英语词典。从中找出最长的一个单词,该单词是由words词典中其他单词逐步添加一个字母组成。若其中有多个可行的答案,则返回答案中字典序最小的单词。 + +若无答案,则返回空字符串。 + +示例 1: +``` +输入: +words = ["w","wo","wor","worl", "world"] +输出: "world" +解释: +单词"world"可由"w", "wo", "wor", 和 "worl"添加一个字母组成。 +``` +示例 2: +``` +输入: +words = ["a", "banana", "app", "appl", "ap", "apply", "apple"] +输出: "apple" +解释: +"apply"和"apple"都能由词典中的单词组成。但是"apple"得字典序小于"apply"。 +``` +注意: +``` +所有输入的字符串都只包含小写字母。 +words数组长度范围为[1,1000]。 +words[i]的长度范围为[1,30]。 +``` +### 解法一 +#### 思路 +使用字符串排序的方法,原因: +- 长的单词必定需要由短的单词扩展而来,所以按照字符长度遍历的顺序和解题的要求符合 +- 如果结果长度相同,按照字符ASCII大小排序 + +过程: +1. 有一个**Set set**存储符合要求的word,有一个**result**变量存储最终结果 +2. 对**String数组 words**排序 +3. 遍历数组,判断word,如果**长度==1**或者**set里面有当前word去掉最后一个字符的字**(因为是排序过的,所以比当前word短的word都判断过了,排序后的好处),就存到set里 +4. 通过字符的长度决定result是哪个 + - 如果遍历到的字比结果长度长,就替换result + - 如果遍历到的字比结果长度短,result不变 + - 如果遍历到的字和结果长度相同,result也不变,因为它的ASCII码肯定比result大,排序的好处 +5. 遍历结束,返回result +#### 代码 +```java +class Solution { + public String longestWord(String[] words) { + Arrays.sort(words); + String result = ""; + Set set = new HashSet<>(); + for (String word: words) { + if (word.length() == 1 || set.contains(word.substring(0, word.length() - 1))) { + set.add(word); + result = word.length() > result.length() ? word : result; + } + } + return result; + } +} +``` +### 解法二 +#### 思路 +构建一个字典树来解这道题。 +- 字典树节点属性: + - 当前节点的字符内容**data** + - 当前节点是否有效**isWord** + - 保存下层节点指针的数组**next** +- 字典树函数: + - 插入**insert()**: + 1. 把字符串中每个字符按顺序生成字典树节点放入字典树中 + 2. 将最有一个节点的isWord属性设置为true(起初在自己思考时,一直想不清如果我把每个字符串的字符都放入字典树中,怎么判断这个字符串是有效的,后来才想通,因为这个单词是依赖整个数组中所有单词衍生而来,所以只要标记最后一个字符,在后面检查的阶段中,只要这个单词的前几个字符所对应的字典树节点的isWord属性没有设置为true,就说明不符合题意) + - 判断是否是符合要求的字符串**isBuild()** + 1. 遍历整个字符数组 + 2. 从根节点出发依次必对字符对应的节点isWord属性是否为true +- 主方法: + 1. 遍历整个字符串数组,依次insert,生成字典树 + 2. 再遍历字符串数组,获得符合题目要求同时字符串长度最长的单词 + 3. 如果有若干单词长度一样的,就再依次比对字符,获得最后的结果 +#### 代码 +```java +class Solution { + public String longestWord(String[] words) { + TrieTree trieTree = new TrieTree(); + for (String word: words) { + trieTree.insert(word); + } + + String result = ""; + int len = 0; + + for (String word: words) { + if (trieTree.isBuild(word) && word.length() > len) { + result = word; + len = result.length(); + } else if (trieTree.isBuild(word) && word.length() == len) { + char[] wordCs = word.toCharArray(); + char[] resultCs = result.toCharArray(); + for (int i = 0; i < len; i++) { + if (wordCs[i] < resultCs[i]) { + result = word; + break; + } else if (wordCs[i] > resultCs[i]) { + break; + } + } + } + } + + return result; + } + + private class TrieTreeNode { + private char data; + private boolean isWord; + private TrieTreeNode[] next; + + public TrieTreeNode(char data) { + this.data = data; + this.next = new TrieTreeNode[26]; + } + } + + private class TrieTree { + TrieTreeNode root = new TrieTreeNode('/'); + public void insert(String word) { + char[] cs = word.toCharArray(); + TrieTreeNode node = root; + for (char c: cs) { + int index = c - 'a'; + if (node.next[index] == null) { + node.next[index] = new TrieTreeNode(c); + } + node = node.next[index]; + } + + node.isWord = true; + } + + public boolean isBuild(String word) { + char[] cs = word.toCharArray(); + TrieTreeNode node = root; + for (char c: cs) { + int index = c - 'a'; + if (!node.next[index].isWord) { + return false; + } + node = node.next[index]; + } + return true; + } + } +} +``` +### 收获 +熟悉和练习了字典树结构及使用的解法。 +## LeetCode_169_求众数 +### 题目 +给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。 + +你可以假设数组是非空的,并且给定的数组总是存在众数。 + +示例 1: +``` +输入: [3,2,3] +输出: 3 +``` +示例 2: +``` +输入: [2,2,1,1,1,2,2] +输出: 2 +``` +### 解法一 +#### 思路 +暴力解法,直接用哈希表统计num的个数,当超过n/2的时候就返回。 +- 时间复杂度:O(N),最坏情况遍历整个数组 +- 空间复杂度:O(N),最坏情况保存n/2个元素 +#### 代码 +```java +class Solution { + public int majorityElement(int[] nums) { + Map map = new HashMap<>(); + int len = nums.length / 2; + for (Integer num: nums) { + map.compute(num, (k, v) -> v == null ? 1 : ++v); + if (map.get(num) > len) { + return num; + } + } + return 0; + } +} +``` +### 解法二 +#### 思路 +对数组排序,因为众数的定义是大于n/2个,所以在对数组排序后,下标n/2对应的元素一定是众数 +#### 代码 +```java +class Solution { + public int majorityElement(int[] nums) { + Arrays.sort(nums); + return nums[nums.length / 2]; + } +} +``` +### 解法三 +#### 思路 +使用分治算法: +1. 不断切分整个数组,直到数组长度为1 +2. 切下的左右两个子区间,去求它们的众数 + - 如果众数是一样的,那么就返回这个数 + - 如果众数不同,谁众数的数量多,那个就是众数,返回 +3. 回溯到最后,返回那个值 +#### 代码 +```java +class Solution { + public int majorityElement(int[] nums) { + return divideConquer(nums, 0, nums.length - 1); + } + + private int divideConquer(int[] nums, int left, int right) { + if (left == right) { + return nums[left]; + } + + int mid = (right - left) / 2 + left; + int leftMajorityNum = divideConquer(nums, left, mid); + int rightMajorityNum = divideConquer(nums, mid + 1, right); + + if (leftMajorityNum == rightMajorityNum) { + return leftMajorityNum; + } + + long leftCount = count(nums, leftMajorityNum, left, mid); + long rightCount = count(nums, rightMajorityNum, mid + 1, right); + + return leftCount > rightCount ? leftMajorityNum : rightMajorityNum; + } + + private int count(int[] nums, int num, int left, int right) { + int count = 0; + for (int i = left; i <= right; i++) { + if (nums[i] == num) { + count++; + } + } + return count; + } +} +``` +### 收获 +熟悉和练习了分治算法 +## LeetCode_455_分饼干 +### 题目 +假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j ,都有一个尺寸 sj 。如果 sj >= gi ,我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。 + +注意: +``` +你可以假设胃口值为正。 +一个小朋友最多只能拥有一块饼干。 +``` +示例 1: +``` +输入: [1,2,3], [1,1] + +输出: 1 +``` +``` +解释: +你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。 +虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。 +所以你应该输出1。 +``` +示例 2: +``` +输入: [1,2], [1,2,3] + +输出: 2 +``` +``` +解释: +你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。 +你拥有的饼干数量和尺寸都足以让所有孩子满足。 +所以你应该输出2. +``` +### 解法一 +#### 思路 +1. 对两个数组从小到大排序 +2. 使用两个循环,外面的循环遍历小孩的胃口值数组 +3. 里面的循环遍历饼干分量 +4. 区别是里面的循环不不需要每次都从头开始遍历,记录迭代的下标位置,每次都从那个位置继续,等同于这块饼干无论符不符合要求,要么被放弃了,要么被吃掉了 +5. 判断当前的饼干是否满足当前小孩的胃口,如果满足就计数+1,否则就找下一块饼干 +6. 直到饼干找完,或小孩找完为止,返回count。 +#### 代码 +```java +class Solution { + public int findContentChildren(int[] g, int[] s) { + Arrays.sort(g); + Arrays.sort(s); + + int j = 0, count = 0, sl = s.length; + + for (int value : g) { + while (j < sl) { + if (value <= s[j++]) { + count++; + break; + } + } + + if (j == sl) { + break; + } + } + + return count; + } +} +``` +#### 代码优化 +```java +class Solution { + public int findContentChildren(int[] g, int[] s) { + Arrays.sort(g); + Arrays.sort(s); + + int gi = 0, si = 0, gl = g.length, sl = s.length; + + while (gi < gl && si < sl) { + if (g[gi] <= s[si]) { + gi++; + } + + si++; + } + return gi; + } +} +``` +- 直接移动两个下标,循环时任意一个越界就停止。 +- 孩子胃口的下标移动条件是满足饼干满足,同时移动的下标也代表了有多少个孩子吃饱了 +- 无论是否满足要求,都移动饼干下标,要么吃掉了,要么遗弃了 + +时间复杂度:O(NlogN),孩子胃口N,饼干logN +空间复杂度:O(1) +### 收获 +熟悉和练习的贪心算法,在简化代码过程中也得到了学习 +## LeetCode_784_字母大小写全排列 +### 题目 +给定一个字符串S,通过将字符串S中的每个字母转变大小写,我们可以获得一个新的字符串。返回所有可能得到的字符串集合。 + +示例: +``` +输入: S = "a1b2" +输出: ["a1b2", "a1B2", "A1b2", "A1B2"] +``` +``` +输入: S = "3z4" +输出: ["3z4", "3Z4"] +``` +``` +输入: S = "12345" +输出: ["12345"] +``` +注意: +``` +S 的长度不超过12。 +S 仅由数字和字母组成。 +``` +### 解法一 +#### 思路 +使用回溯算法进行搜索 +1. 定义一个函数进行回溯,需要如下两个参数 + - 被遍历的字符串(补充:因String对象为final修饰的不可变类型,所以每次修改字符串会额外创建一个新的String对象,改为使用StringBuilder对象) + - 当前层需处理的字符下标 +2. 类似递归,以字符下标作为层数,一层层的下钻处理逻辑 +3. 处理逻辑: + - 当前要处理的字符是数字就继续下钻 + - 否则就分别改变当前字符为大小写,分别下钻。 +4. 当字符串被搜索完毕,就将字符串放入一个list中,同时返回上一层 +5. 整个过程结束后,将list返回 +#### 代码 +```java +class Solution { + List list = new ArrayList<>(); + public List letterCasePermutation(String S) { + dfs(new StringBuilder(S), 0); + return list; + } + + private void dfs(StringBuilder sb, int index) { + if (index == sb.length()) { + list.add(sb.toString()); + return; + } + + if (Character.isDigit(sb.charAt(index))) { + dfs(sb, index + 1); + } else { + char c = sb.charAt(index); + sb.setCharAt(index, Character.toLowerCase(c)); + dfs(sb, index + 1); + sb.setCharAt(index, Character.toUpperCase(c)); + dfs(sb, index + 1); + } + } +} +``` +#### 优化代码 +参考了国内站的另一种回溯解法,其中讨论了为什么在步骤类似的情况下,这种算法的时间会更短,他的结论是在做判断字符是否为数字的动作时,直接使用ASCII码进行比较比**Character.isDigit**方法更快。 + +我也进行了尝试。而我的另一个不同是,我使用的是StringBuilder对象,而其使用的是字符数组。在使用优化的方法后,代码的执行时间果然减少了,同时空间占用的大小也减小了,原因应该是StringBuilder类型的对象中还维护了一些题目中不需要的属性。 +```java +class Solution { + List list = new ArrayList<>(); + public List letterCasePermutation(String S) { + dfs(S.toCharArray(), 0); + return list; + } + + private void dfs(char[] cs, int index) { + if (index == cs.length) { + list.add(new String(cs)); + return; + } + + if (cs[index] < 'A') { + dfs(cs, index + 1); + } else { + char c = cs[index]; + if (c > 64 && c < 91) { + dfs(cs, index + 1); + cs[index] = (char) (cs[index] + 'a' - 'A'); + dfs(cs, index + 1); + } else { + dfs(cs, index + 1); + cs[index] = (char) (cs[index] + 'A' - 'a'); + dfs(cs, index + 1); + } + } + } +} +``` +### 收获 +熟悉和练习了回溯算法 +## LeetCode_70_爬楼梯 +### 题目 +假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 + +每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? + +注意:给定 n 是一个正整数。 + +示例 1: +``` +输入: 2 +输出: 2 +解释: 有两种方法可以爬到楼顶。 +1. 1 阶 + 1 阶 +2. 2 阶 +``` +示例 2: +``` +输入: 3 +输出: 3 +解释: 有三种方法可以爬到楼顶。 +1. 1 阶 + 1 阶 + 1 阶 +2. 1 阶 + 2 阶 +3. 2 阶 + 1 阶 +``` +### 失败解法 +#### 思路 +使用递归的方法,和之前做的一个求斐波那契数列的题目类似,代码和思路都很直观、简单,但超时了。 +时间复杂度:O(2^n) +#### 代码 +```java +class Solution { + public int climbStairs(int n) { + return n <= 2 ? n : climbStairs(n - 1) + climbStairs(n - 2); + } +} +``` +### 解法一 +#### 思路 +求助国内站的官方解法二,其对解法一(思路和我的失败解法类似)进行了优化,用到了记忆化递归。因为每次下钻的过程中,会有重复的步数,把已经计算过的部署放在数组里记录,就可以省去很多的步骤。 +#### 代码 +```java +class Solution { + public int climbStairs(int n) { + return climbStairs(n, new int[n + 1]); + } + + private int climbStairs(int n, int[] nums) { + if (n <= 2) { + return n; + } + + if (nums[n] > 0) { + return nums[n]; + } + + int num = climbStairs(n - 1, nums) + climbStairs(n - 2, nums); + nums[n] = num; + + return num; + } +} +``` +### 解法二 +#### 思路 +看了国内站官方解法三对于动态规划解法的讲解,发现其思路和我解法一二的思路有部分是基本一致的:**dp[i] = dp[i - 1] + dp[i - 2]**。 + +从覃老师周三一开始对动态规划的讲解中了解到,这题是属于一维的动态规划的,使用一维数组dp[] +- 数组下标对应的是台阶数 +- 下标对应的元素代表的是走当前台阶数有的解法 + +因为题目定义每次只能是1或者2步,所以到达当前台阶i的必由路径一定是 +- i - 1级台阶直接走1级 +- i - 2级台阶直接走2级 + +于是到达i级台阶的方法数dp[i]就是dp[i - 1] + dp[i - 2],也就是从第3级开始,每一级的结果就是前一两级结果之和。 +- 时间复杂度:O(N) +- 空间复杂度:O(N) +#### 代码 +```java +class Solution { + public int climbStairs(int n) { + if (n <= 2) { + return n; + } + + int[] dp = new int[n + 1]; + dp[1] = 1; + dp[2] = 2; + for (int i = 3; i <= n; i++) { + dp[i] = dp[i - 1] + dp[i - 2]; + } + return dp[n]; + } +} +``` +#### 优化代码 +在写如上代码时发现,其实整个过程主要出现的就是三个变量 +- 当前的数 +- 前一位的数 +- 前二位的数 + +所以不需要使用一个n+1位的数组来保存当前值,只需要3个变量就可以了。于是对解法二的代码进行了优化 +```java +class Solution { + public int climbStairs(int n) { + if (n <= 2) { + return n; + } + + int first = 1, second = 2; + for (int i = 3; i <= n; i++) { + int third = first + second; + first = second; + second = third; + } + + return second; + } +} +``` +但执行结果显示,空间没有减少,没办法解释,希望有人解惑。 +### 解法三 +#### 思路 +使用数学公式解,真的快。 +#### 代码 +```java +class Solution { + public int climbStairs(int n) { + double sqrt5=Math.sqrt(5); + double fibn=Math.pow((1+sqrt5)/2,n+1)-Math.pow((1-sqrt5)/2,n+1); + return (int)(fibn/sqrt5); + } +} +``` +### 收获 +练习和熟悉了动态规划及递归,还学了点数学。 +## LeetCode_208_实现Trie(前缀树) +### 题目 +实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作。 + +示例: +``` +Trie trie = new Trie(); + +trie.insert("apple"); +trie.search("apple"); // 返回 true +trie.search("app"); // 返回 false +trie.startsWith("app"); // 返回 true +trie.insert("app"); +trie.search("app"); // 返回 true +``` +说明: +``` +你可以假设所有的输入都是由小写字母 a-z 构成的。 +保证所有输入均为非空字符串。 +``` +### 解法 +#### 思路 +和720题构建Trie树的思路基本一致。 +#### 代码 +```java +class Trie { + private static final int SIZE = 26; + private TrieNode root; + + public Trie() { + root = new TrieNode(); + } + + public void insert(String word) { + if (isEmpty(word)) { + return; + } + + char[] cs = word.toCharArray(); + TrieNode node = root; + for (char c: cs) { + int index = c - 'a'; + if (node.next[index] == null) { + node.next[index] = new TrieNode(); + node.next[index].data = c; + } + node = node.next[index]; + } + node.isWord = true; + } + + public boolean search(String word) { + if (isEmpty(word)) { + return false; + } + + char[] cs = word.toCharArray(); + TrieNode node = root; + for (char c: cs) { + int index = c - 'a'; + if (node.next[index] != null) { + node = node.next[index]; + } else { + return false; + } + } + + return node.isWord; + } + + public boolean startsWith(String prefix) { + if (isEmpty(prefix)) { + return false; + } + + TrieNode node = root; + char[] cs = prefix.toCharArray(); + for (char c: cs) { + int index = c - 'a'; + if (node.next[index] != null) { + node = node.next[index]; + } else { + return false; + } + } + + return true; + } + + private boolean isEmpty(String word) { + return word == null || word.length() == 0; + } + + private class TrieNode { + private char data; + private TrieNode[] next; + private boolean isWord; + + TrieNode() { + this.next = new TrieNode[SIZE]; + this.isWord = false; + } + } +} +``` +### 收获 +再次熟悉了Trie树的构建代码。同时在构建过程中,发现startWith和search有一部分代码是重复的,在想要抽出这部分代码复用的过程中,没有考虑到函数中的引用指针的问题。 +```java +class Problem { + boolean search(String word) { + TrieNode node = root; + boolean hasStr = hasStr(word, node); + return hasStr ? node.isWord : hasStr; + } + + private boolean hasStr(String word, TrieNode node) { + for (char c: word.toCharArray()) { + //...... + if (node.next[index] == null) { + return false; + } + node = node.next[index]; + } + return true; + } +} +``` +这里的node其实还是指向的root。最后只能老实的继续在两个函数中写类似的代码。 +## LeetCode_53_最大子序和 +### 题目 +给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 + +示例: +``` +输入: [-2,1,-3,4,-1,2,1,-5,4], +输出: 6 +解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。 +``` +进阶: +``` +如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。 +``` +### 解法一 +#### 思路 +因为题目求的是子序列的最大和,在求和的过程中,可以定义两个变量: +- 最终的结果result +- 求和过程中临时的和sum + +对于result来说,它不用管sum是通过多少个元素相加得来的,它只需要管这个sum对自身是有益还是无益的,而有益无益的定义也很简单,是否大于等于0。 + +所以整个过程: +- 定义一个变量记录结果 +- 定义一个变量记录求和过程中临时的和 +- 迭代数组,在迭代过程中判断sum>=0 + - 如果是:result就接受这个sum,result += sum + - 如果不是:result就舍弃这个sum,sum的累加从当前num重新开始 +- 在循环体里,对result和sum进行大小判断 + - result大,不变 + - sum大,result = sum +- 迭代结束,返回result +#### 代码 +```java +class Solution { + public int maxSubArray(int[] nums) { + int result = nums[0]; + int sum = 0; + for (int num: nums) { + if (sum >= 0) { + sum += num; + } else { + sum = num; + } + result = Math.max(sum, result); + } + + return result; + } +} +``` +### 解法二 +#### 思路 + +#### 代码 + +### 收获 \ No newline at end of file diff --git a/Week_04/id_2/LeetCode_198_2.java b/Week_04/id_2/LeetCode_198_2.java new file mode 100644 index 00000000..8661c5ff --- /dev/null +++ b/Week_04/id_2/LeetCode_198_2.java @@ -0,0 +1,68 @@ +//You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night. +// +// Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police. +// +// Example 1: +// +// +//Input: [1,2,3,1] +//Output: 4 +//Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3). +//  Total amount you can rob = 1 + 3 = 4. +// +// Example 2: +// +// +//Input: [2,7,9,3,1] +//Output: 12 +//Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1). +//  Total amount you can rob = 2 + 9 + 1 = 12. +// +// + +package com.llz.algorithm.algorithm2019.fourthweek; + +public class LeetCode_198_2 { + + /** + * Time complexity and space complexity are both O(n). + * + * @param nums + * @return + */ + public int rob(int[] nums) { + if (nums.length == 0) return 0; + if (nums.length == 1) return nums[0]; + if (nums.length == 2) return Math.max(nums[0], nums[1]); + int[] max = new int[nums.length]; + max[0] = nums[0]; + max[1] = Math.max(nums[0], nums[1]); + for (int i = 2; i < nums.length; i++) { + max[i] = Math.max(max[i - 2] + nums[i], max[i - 1]); + } + return max[nums.length - 1]; + } + + /** + * Time complexity is O(n), space complexity is O(1). + * + * @param nums + * @return + */ + public int robOptimized(int[] nums) { + if (nums.length == 0) return 0; + int prev1 = 0, prev2 = 0; + for (int i = 0; i < nums.length; i++) { + int temp = prev1; + prev1 = Math.max(prev2 + nums[i], prev1); + prev2 = temp; + } + return prev1; + } + + public static void main(String[] args) { + LeetCode_198_2 l = new LeetCode_198_2(); + int[] nums = {1, 2, 3, 1}; + System.out.println(l.rob(nums)); + } +} diff --git a/Week_04/id_2/LeetCode_213_2.java b/Week_04/id_2/LeetCode_213_2.java new file mode 100644 index 00000000..42b36adf --- /dev/null +++ b/Week_04/id_2/LeetCode_213_2.java @@ -0,0 +1,62 @@ +//You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed. All houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night. +// +// Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police. +// +// Example 1: +// +// +//Input: [2,3,2] +//Output: 3 +//Explanation: You cannot rob house 1 (money = 2) and then rob house 3 (money = 2), +//  because they are adjacent houses. +// +// +// Example 2: +// +// +//Input: [1,2,3,1] +//Output: 4 +//Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3). +//  Total amount you can rob = 1 + 3 = 4. +// + +package com.llz.algorithm.algorithm2019.fourthweek; + +public class LeetCode_213_2 { + + /** + * My original version. The code is not clean enough, However it definitely solves this problem. + * The time complexity and space complexity are both O(n). + * @param nums + * @return + */ + public int rob(int[] nums) { + int length = nums.length; + if (length == 0) return 0; + if (length == 1) return nums[0]; + if (length == 2) return Math.max(nums[0], nums[1]); + //0...n-2 + int[] max1 = new int[length - 1]; + max1[0] = nums[0]; + max1[1] = Math.max(nums[0], nums[1]); + for (int i = 2; i < length - 1; i++) { + max1[i] = Math.max(max1[i - 2] + nums[i], max1[i - 1]); + } + int maxA = max1[length - 2]; + + //1...n-1 + max1[0] = nums[1]; + max1[1] = Math.max(nums[1], nums[2]); + for (int i = 2; i <= length - 2; i++) { + max1[i] = Math.max(max1[i - 2] + nums[i + 1], max1[i - 1]); + } + int maxB = max1[length - 2]; + return Math.max(maxA, maxB); + } + + public static void main(String[] args) { + int[] nums = {4, 1, 2, 7, 5, 3, 1}; + LeetCode_213_2 l = new LeetCode_213_2(); + System.out.println(l.rob(nums)); + } +} diff --git a/Week_04/id_2/LeetCode_309_2.java b/Week_04/id_2/LeetCode_309_2.java new file mode 100644 index 00000000..b2038383 --- /dev/null +++ b/Week_04/id_2/LeetCode_309_2.java @@ -0,0 +1,80 @@ +//Say you have an array for which the ith element is the price of a given stock on day i. +// +// Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times) with the following restrictions: +// +// +// You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again). +// After you sell your stock, you cannot buy stock on next day. (ie, cooldown 1 day) +// +// +// Example: +// +// +//Input: [1,2,3,0,2] +//Output: 3 +//Explanation: transactions = [buy, sell, cooldown, buy, sell] +// + +package com.llz.algorithm.algorithm2019.fourthweek; + +public class LeetCode_309_2 { + + /** + * Referenced from discussion. + * buy[i] means before day i what is the maxProfit for any sequence end with buy. + * sell[i] means before day i what is the maxProfit for any sequence end with sell. + * Where price is the price of day i. + * buy[i]=Max(buy[i-1],sell[i-2]-price) + * sell[i]=Max(sell[i-1],buy[i-1]+price) + * Reduce space complexity O(n) to O(1) + * + * @param prices + * @return + */ + public int maxProfit(int[] prices) { + int length = prices.length; + if (length < 2) return 0; + int preBuy = -prices[0], buy = -prices[0], sell = 0, preSell = 0, prePreSell = 0; + for (int i = 1; i < length; i++) { + buy = Math.max(prePreSell - prices[i], preBuy); + sell = Math.max(preSell, preBuy + prices[i]); + prePreSell = preSell; + preSell = sell; + preBuy = buy; + } + return sell; + } + + /** + * Referenced from discussion. + * buy[i] means before day i what is the maxProfit for any sequence end with buy. + * sell[i] means before day i what is the maxProfit for any sequence end with sell. + * Where price is the price of day i. + * buy[i]=Max(buy[i-1],sell[i-2]-price) + * sell[i]=Max(sell[i-1],buy[i-1]+price) + * + * @param prices + * @return + */ + public int maxProfitOptimised(int[] prices) { + int length = prices.length; + if (length < 2) return 0; + int[] buy = new int[length]; + int[] sell = new int[length]; + buy[0] = -prices[0]; + sell[0] = 0; + buy[1] = Math.max(buy[0], -prices[1]); + for (int i = 1; i < length; i++) { + if (i > 1) + buy[i] = Math.max(sell[i - 2] - prices[i], buy[i - 1]); + sell[i] = Math.max(sell[i - 1], buy[i - 1] + prices[i]); + } + return Math.max(buy[length - 1], sell[length - 1]); + } + + public static void main(String[] args) { + int[] prices = {1, 2, 3, 0, 2}; + LeetCode_309_2 l = new LeetCode_309_2(); + System.out.println(l.maxProfit(prices)); + } +} diff --git a/Week_04/id_2/LeetCode_337_2.java b/Week_04/id_2/LeetCode_337_2.java new file mode 100644 index 00000000..79fdfa97 --- /dev/null +++ b/Week_04/id_2/LeetCode_337_2.java @@ -0,0 +1,159 @@ +//The thief has found himself a new place for his thievery again. There is only one entrance to this area, called the "root." Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that "all houses in this place forms a binary tree". It will automatically contact the police if two directly-linked houses were broken into on the same night. +// +// Determine the maximum amount of money the thief can rob tonight without alerting the police. +// +// Example 1: +// +// +//Input: [3,2,3,null,3,null,1] +// +// 3 +// / \ +// 2 3 +// \ \ +// 3 1 +// +//Output: 7 +//Explanation: Maximum amount of money the thief can rob = 3 + 3 + 1 = 7. +// +// Example 2: +// +// +//Input: [3,4,5,1,3,null,1] +// +//  3 +// / \ +// 4 5 +// / \ \ +// 1 3 1 +// +//Output: 9 +//Explanation: Maximum amount of money the thief can rob = 4 + 5 = 9. +// + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +package com.llz.algorithm.algorithm2019.fourthweek; + +import apple.laf.JRSUIUtils; +import com.llz.algorithm.algorithm2019.firstweek.TreeNode; + +import java.util.ArrayDeque; +import java.util.HashMap; +import java.util.Queue; + +public class LeetCode_337_2 { + + + /** + * Easily get the DP equation as below. + * Max(n) = Math.Max(Max(n-1), Max(n-2)+sum) + * To minimise the space complexity by using two variables instead of one-dimensional array. + * However, the solution is not right where get the [2,1,3,null,4] input. + * + * @param root + * @return + */ +// public int rob(TreeNode root) { +// if (root == null) return 0; +// int pre = 0, prePre = 0, max = 0; +// Queue queue = new ArrayDeque<>(); +// queue.offer(root); +// while (!queue.isEmpty()) { +// int size = queue.size(); +// int sum = 0; +// for (int i = 0; i < size; i++) { +// TreeNode node = queue.poll(); +// sum += node.val; +// if (node.left != null) +// queue.offer(node.left); +// if (node.right != null) +// queue.offer(node.right); +// } +// max = Math.max(pre, prePre + sum); +// prePre = pre; +// pre = max; +// } +// return max; +// } + + /** + * Referenced from discussion + * + * @param root + * @return + */ + public int robByRecursion(TreeNode root) { + if (root == null) + return 0; + int val = 0; + if (root.left != null) + val += robByRecursion(root.left.left) + robByRecursion(root.left.right); + if (root.right != null) + val += robByRecursion(root.right.left) + robByRecursion(root.right.right); + return Math.max(root.val + val, robByRecursion(root.left) + robByRecursion(root.right)); + } + + public int rob(TreeNode root) { + // return robByRecurOptimised(root, new HashMap()); + int[] res = robByDP(root); + return Math.max(res[0], res[1]); + } + + public int[] robByDP(TreeNode root) { + if (root == null) return new int[2]; + int[] res = new int[2]; //0:robbed; 1:not robbed + int[] left = robByDP(root.left); + int[] right = robByDP(root.right); + res[0] = root.val + left[1] + right[1]; + res[1] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]); + return res; + } + + + public int rob1(TreeNode root) { + return robByRecurOptimised(root, new HashMap()); + } + + /** + * By using memo to reduce times of recursion. + * + * @param root + * @param map + * @return + */ + public int robByRecurOptimised(TreeNode root, HashMap map) { + if (root == null) return 0; + if (map.containsKey(root)) return map.get(root); + int val = 0; + if (root.left != null) + val += robByRecurOptimised(root.left.left, map) + robByRecurOptimised(root.left.right, map); + if (root.right != null) + val += robByRecurOptimised(root.right.left, map) + robByRecurOptimised(root.right.right, map); + val = Math.max(root.val + val, robByRecurOptimised(root.left, map) + robByRecurOptimised(root.right, map)); + map.put(root, val); + return val; + } + + public static void main(String[] args) { + /** + * 2 + * 1 3 + * 4 + */ + + TreeNode root = new TreeNode(2); + root.left = new TreeNode(1); + root.right = new TreeNode(3); + root.left.right = new TreeNode(4); + LeetCode_337_2 l = new LeetCode_337_2(); + System.out.println(l.rob(root)); + } +} diff --git a/Week_04/id_2/LeetCode_51_2.java b/Week_04/id_2/LeetCode_51_2.java new file mode 100644 index 00000000..631458e1 --- /dev/null +++ b/Week_04/id_2/LeetCode_51_2.java @@ -0,0 +1,107 @@ +//The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other. +// +// +// +// Given an integer n, return all distinct solutions to the n-queens puzzle. +// +// Each solution contains a distinct board configuration of the n-queens' placement, where 'Q' and '.' both indicate a queen and an empty space respectively. +// +// Example: +// +// +//Input: 4 +//Output: [ +// [".Q..", // Solution 1 +// "...Q", +// "Q...", +// "..Q."], +// +// ["..Q.", // Solution 2 +// "Q...", +// "...Q", +// ".Q.."] +//] +//Explanation: There exist two distinct solutions to the 4-queens puzzle as shown above. +// +// + +package com.llz.algorithm.algorithm2019.fourthweek; + +import java.util.ArrayList; +import java.util.List; + +public class LeetCode_51_2 { + List> list = new ArrayList<>(); + + public List> solveNQueens(int n) { + int[] queens = new int[n]; + for (int i = 0; i < queens.length; i++) { + queens[i] = -1; + } + dfs(queens, 0, n); + return list; + } + + /** + * My first solution + * @param queens + * @param row + * @param maxRow + */ + public void dfs(int[] queens, int row, int maxRow) { + if (row == maxRow) { + createList(queens, maxRow); + return; + } else { + for (int col = 0; col < maxRow; col++) { + if (isOK(queens, row, col, maxRow)) { + queens[row] = col; + dfs(queens, row + 1, maxRow); + } + } + } + } + + public boolean isOK(int[] queens, int row, int col, int maxRow) { + int leftUp = col; + int rightUp = col; + for (int i = row - 1; i >= 0; i--) { + if (queens[i] == col) + return false; + if (--leftUp >= 0 && leftUp == queens[i]) + return false; + if (++rightUp < maxRow && rightUp == queens[i]) + return false; + } + return true; + } + + public void createList(int[] queens, int maxRow) { + List innerList = new ArrayList<>(); + for (int i = 0; i < maxRow; i++) { + StringBuilder sb = new StringBuilder(); + int col = queens[i]; + for (int j = 0; j < maxRow; j++) { + if (j != col) + sb.append("."); + else + sb.append("Q"); + } + innerList.add(sb.toString()); + } + list.add(innerList); + } + + public void print(List> temp) { + int index = 1; + for (List tempInner : temp) { + System.out.println(index++); + System.out.println(tempInner); + } + } + + public static void main(String[] args) { + LeetCode_51_2 l = new LeetCode_51_2(); + l.print(l.solveNQueens(8)); + } +} diff --git a/Week_04/id_2/LeetCode_62_2.java b/Week_04/id_2/LeetCode_62_2.java new file mode 100644 index 00000000..7fcdb4c7 --- /dev/null +++ b/Week_04/id_2/LeetCode_62_2.java @@ -0,0 +1,60 @@ +//A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). +// +// The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below). +// +// How many possible unique paths are there? +// +// +//Above is a 7 x 3 grid. How many possible unique paths are there? +// +// Note: m and n will be at most 100. +// +// Example 1: +// +// +//Input: m = 3, n = 2 +//Output: 3 +//Explanation: +//From the top-left corner, there are a total of 3 ways to reach the bottom-right corner: +//1. Right -> Right -> Down +//2. Right -> Down -> Right +//3. Down -> Right -> Right +// +// +// Example 2: +// +// +//Input: m = 7, n = 3 +//Output: 28 +// + +package com.llz.algorithm.algorithm2019.fourthweek; + +public class LeetCode_62_2 { + /** + * The time complexity and space complexity are both O(m*n). + * + * @param m + * @param n + * @return + */ + public int uniquePaths(int m, int n) { + if (m < 1 || n < 1) { + return 0; + } + if (m == 1 && n == 1) + return 1; + int[][] pathArray = new int[n][m]; + pathArray[0][0] = 0; + for (int i = 1; i < n; i++) + pathArray[i][0] = 1; + for (int i = 1; i < m; i++) + pathArray[0][i] = 1; + for (int i = 1; i < n; i++) { + for (int j = 1; j < m; j++) { + pathArray[i][j] = pathArray[i - 1][j] + pathArray[i][j - 1]; + } + } + return pathArray[n - 1][m - 1]; + } +} diff --git a/Week_04/id_2/LeetCode_63_2.java b/Week_04/id_2/LeetCode_63_2.java new file mode 100644 index 00000000..629e309a --- /dev/null +++ b/Week_04/id_2/LeetCode_63_2.java @@ -0,0 +1,105 @@ +//A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). +// +// The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below). +// +// Now consider if some obstacles are added to the grids. How many unique paths would there be? +// +// +// +// An obstacle and empty space is marked as 1 and 0 respectively in the grid. +// +// Note: m and n will be at most 100. +// +// Example 1: +// +// +//Input: +//[ +//  [0,0,0], +//  [0,1,0], +//  [0,0,0] +//] +//Output: 2 +//Explanation: +//There is one obstacle in the middle of the 3x3 grid above. +//There are two ways to reach the bottom-right corner: +//1. Right -> Right -> Down -> Down +//2. Down -> Down -> Right -> Right +// +// + +package com.llz.algorithm.algorithm2019.fourthweek; + +public class LeetCode_63_2 { + + /** + * My first version. + * Time complexity and space complexity are both O(m*n). + * + * @param obstacleGrid + * @return + */ + public int uniquePathsWithObstacles(int[][] obstacleGrid) { + if (obstacleGrid[0][0] == 1) + return 0; + if (obstacleGrid.length == 1 && obstacleGrid[0].length == 1) + return 1; + int[][] dpArray = new int[obstacleGrid.length][obstacleGrid[0].length]; + dpArray[0][0] = 0; + for (int i = 1; i < dpArray.length; i++) { + if (obstacleGrid[i][0] == 1) { + dpArray[i][0] = 0; + break; + } else + dpArray[i][0] = 1; + } + for (int i = 1; i < dpArray[0].length; i++) { + if (obstacleGrid[0][i] == 1) { + dpArray[0][i] = 0; + break; + } else + dpArray[0][i] = 1; + } + for (int i = 1; i < dpArray.length; i++) { + for (int j = 1; j < dpArray[0].length; j++) + if (obstacleGrid[i][j] == 1) + dpArray[i][j] = 0; + else + dpArray[i][j] = dpArray[i - 1][j] + dpArray[i][j - 1]; + } + return dpArray[obstacleGrid.length - 1][obstacleGrid[0].length - 1]; + } + + /** + * My second version. + * Reduce space complexity to O(1). + * + * @param obstacleGrid + * @return + */ + public int uniquePathsWithObstaclesOptimised(int[][] obstacleGrid) { + if (obstacleGrid[0][0] == 1) + return 0; + int row = obstacleGrid.length; + int col = obstacleGrid[0].length; + obstacleGrid[0][0] = 1; + for (int i = 1; i < row; i++) + obstacleGrid[i][0] = obstacleGrid[i][0] == 0 && obstacleGrid[i - 1][0] == 1 ? 1 : 0; + for (int j = 1; j < col; j++) + obstacleGrid[0][j] = obstacleGrid[0][j] == 0 && obstacleGrid[0][j - 1] == 1 ? 1 : 0; + for (int i = 1; i < row; i++) { + for (int j = 1; j < col; j++) { + obstacleGrid[i][j] = obstacleGrid[i][j] == 1 ? 0 : obstacleGrid[i - 1][j] + obstacleGrid[i][j - 1]; + } + } + return obstacleGrid[row - 1][col - 1]; + } + + + public static void main(String[] args) { + int[][] obstacles = {{0, 0, 0}, {0, 1, 0}, {0, 0, 0}}; + LeetCode_63_2 l = new LeetCode_63_2(); + System.out.println(l.uniquePathsWithObstacles(obstacles)); + System.out.println(l.uniquePathsWithObstaclesOptimised(obstacles)); + } +} diff --git a/Week_04/id_2/LeetCode_70_2.java b/Week_04/id_2/LeetCode_70_2.java new file mode 100644 index 00000000..14e93414 --- /dev/null +++ b/Week_04/id_2/LeetCode_70_2.java @@ -0,0 +1,79 @@ +//You are climbing a stair case. It takes n steps to reach to the top. +// +// Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top? +// +// Note: Given n will be a positive integer. +// +// Example 1: +// +// +//Input: 2 +//Output: 2 +//Explanation: There are two ways to climb to the top. +//1. 1 step + 1 step +//2. 2 steps +// +// +// Example 2: +// +// +//Input: 3 +//Output: 3 +//Explanation: There are three ways to climb to the top. +//1. 1 step + 1 step + 1 step +//2. 1 step + 2 steps +//3. 2 steps + 1 step +// +// + +package com.llz.algorithm.algorithm2019.fourthweek; + +public class LeetCode_70_2 { + + private int count = 0; + + public int climbStairs(int n) { + int[] mem = new int[n + 1]; + return climbStairsByTraverseOptimised(n, mem); + //return climbStairsByDP(n); + } + + /** + * Time complexity and space complexity are both O(n). + * + * @param n + * @return + */ + public int climbStairsByDP(int n) { + if (n < 2) return 1; + int[] ans = new int[n + 1]; + ans[0] = 0; + ans[1] = 1; + ans[2] = 2; + for (int i = 3; i <= n; i++) { + ans[i] = ans[i - 1] + ans[i - 2]; + } + return ans[n]; + } + + public void climbStairsByTraverse(int cur, int n) { + if (cur >= n) { + if (cur == n) + count++; + return; + } + climbStairsByTraverse(cur + 1, n); + climbStairsByTraverse(cur + 2, n); + } + + public int climbStairsByTraverseOptimised(int n, int[] mem) { + if (n == 1) + return 1; + if (n == 2) + return 2; + if (mem[n] > 0) + return mem[n]; + mem[n] = climbStairsByTraverseOptimised(n - 1, mem) + climbStairsByTraverseOptimised(n - 2, mem); + return mem[n]; + } +} diff --git a/Week_04/id_2/LeetCode_720_2.java b/Week_04/id_2/LeetCode_720_2.java new file mode 100644 index 00000000..2eeb69a1 --- /dev/null +++ b/Week_04/id_2/LeetCode_720_2.java @@ -0,0 +1,106 @@ +//Given a list of strings words representing an English Dictionary, find the longest word in words that can be built one character at a time by other words in words. If there is more than one possible answer, return the longest word with the smallest lexicographical order. If there is no answer, return the empty string. +// +// Example 1: +// +//Input: +//words = ["w","wo","wor","worl", "world"] +//Output: "world" +//Explanation: +//The word "world" can be built one character at a time by "w", "wo", "wor", and "worl". +// +// +// +// Example 2: +// +//Input: +//words = ["a", "banana", "app", "appl", "ap", "apply", "apple"] +//Output: "apple" +//Explanation: +//Both "apply" and "apple" can be built from other words in the dictionary. However, "apple" is lexicographically smaller than "apply". +// +// +// +// Note: +// All the strings in the input will only contain lowercase letters. +// The length of words will be in the range [1, 1000]. +// The length of words[i] will be in the range [1, 30]. +// + +package com.llz.algorithm.algorithm2019.fourthweek; + +import java.util.Arrays; + +/** + * My original version. Use Arrays.sort(words[]) to know whether the current word + * is built by the former word. + */ +class TrieTree { + TrieNode root; + + public TrieTree() { + this.root = new TrieNode(' '); + } + + /** + * Build word by last single character and return the length of the word. + * If the word is not build by former word then return -1. + * @param str word + * @return length of the word + */ + public int addWordBySingleChar(String str) { + char[] charArray = str.toLowerCase().toCharArray(); + TrieNode cur = root; + for (int i = 0; i < charArray.length - 1; i++) { + int index = charArray[i] - 'a'; + if (cur.childNodes[index] == null) + return -1; + else + cur = cur.childNodes[index]; + + } + int targetIndex = charArray[charArray.length - 1] - 'a'; + cur.childNodes[targetIndex] = new TrieNode(charArray[charArray.length - 1]); + cur.childNodes[targetIndex].nums = charArray.length; + return charArray.length; + } +} + +class TrieNode { + char c; + TrieNode[] childNodes = new TrieNode[26]; + int nums; + + public TrieNode(char c) { + this.c = c; + } +} + +public class LeetCode_720_2 { + + /** + * Time complexity is O(nlogn)+O(Sum(wi)). + * Because the method requires a sorted array (O(nlogn)). + * Space complexity is O(Sum(wi)) as build trie tree for every word. + * @param words + * @return + */ + public String longestWord(String[] words) { + Arrays.sort(words); + TrieTree trie = new TrieTree(); + int maxIndex = 0; + int maxLength = 0; + for (int i = 0; i < words.length; i++) { + if (trie.addWordBySingleChar(words[i]) > maxLength) { + maxIndex = i; + maxLength = words[i].length(); + } + } + return words[maxIndex]; + } + + public static void main(String[] args) { + LeetCode_720_2 l = new LeetCode_720_2(); + String[] words = {"a", "banana", "app", "appl", "ap", "apply", "apple", "az"}; + System.out.println(l.longestWord(words)); + } +} diff --git a/Week_04/id_2/LeetCode_784_2.java b/Week_04/id_2/LeetCode_784_2.java new file mode 100644 index 00000000..51d27887 --- /dev/null +++ b/Week_04/id_2/LeetCode_784_2.java @@ -0,0 +1,102 @@ +//Given a string S, we can transform every letter individually to be lowercase or uppercase to create another string. Return a list of all possible strings we could create. +// +// +//Examples: +//Input: S = "a1b2" +//Output: ["a1b2", "a1B2", "A1b2", "A1B2"] +// +//Input: S = "3z4" +//Output: ["3z4", "3Z4"] +// +//Input: S = "12345" +//Output: ["12345"] +// +// +// Note: +// +// +// S will be a string with length between 1 and 12. +// S will consist only of letters or digits. +// +// + +package com.llz.algorithm.algorithm2019.fourthweek; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +public class LeetCode_784_2 { + + private List list = new ArrayList<>(); + + /** + * My first method using backtrack. + * + * @param S + * @return + */ + public List letterCasePermutation(String S) { + char[] chars = S.toCharArray(); + backTrack(chars, 0); + return list; + } + + /** + * The time and space complexity is O(2^n) + * + * @param chars + * @param index + */ + public void backTrack(char[] chars, int index) { + if (index > chars.length - 1) { + list.add(String.valueOf(chars)); + return; + } + if (chars[index] > 57) { //letter + backTrack(chars, index + 1); // no change + chars[index] = chars[index] < 91 ? Character.toLowerCase(chars[index]) : Character.toUpperCase(chars[index]); + backTrack(chars, index + 1); // change + } else + backTrack(chars, index + 1); // number + } + + /** + * Using BFS. + * @param S + * @return + */ + public List letterCasePermutationByBFS(String S) { + Queue queue = new LinkedList<>(); + queue.offer(S); + for (int j = 0; j < S.length(); j++) { + int size = queue.size(); + for (int i = 0; i < size; i++) { + String sTemp = queue.poll(); + char[] chars = sTemp.toCharArray(); + if (Character.isDigit(chars[j])) { + queue.offer(String.valueOf(chars)); + continue; + } + chars[j] = Character.toUpperCase(chars[j]); + queue.offer(String.valueOf(chars)); + chars[j] = Character.toLowerCase(chars[j]); + queue.offer(String.valueOf(chars)); + } + } + return new LinkedList<>(queue); + } + + public void print(List list) { + for (String s : list) { + System.out.println(s); + } + } + + public static void main(String[] args) { + String S = "a1b2"; + LeetCode_784_2 l = new LeetCode_784_2(); + l.print(l.letterCasePermutationByBFS(S)); + } +} diff --git "a/Week_04/id_2/\347\254\254\345\233\233\345\221\250\346\200\273\347\273\223.md" "b/Week_04/id_2/\347\254\254\345\233\233\345\221\250\346\200\273\347\273\223.md" new file mode 100644 index 00000000..b0ad7b8a --- /dev/null +++ "b/Week_04/id_2/\347\254\254\345\233\233\345\221\250\346\200\273\347\273\223.md" @@ -0,0 +1,12 @@ +第四周总结 +第四周基本上题目类型都属于比较难的,所以我从简单题目开始刷起。 +720:快速写完,代码量有点多,实现了一个修改版的trie,为什么说是修改版,因为我对传进来的word数组进行了排序,所以后面的单词肯定包含前面的单词。那我就进行个排序将前面的单词先build。 +70:快速使用三种方法写完,一个回溯,一个递推,一个dp。然后把使用递归的方法通过加备忘录的方式优化了时间复杂度和空间复杂度。降低到和dp一样的O(n)。 +198:快速写完,后来看了discuss,人家进一步降低了空间复杂度,用了两个变量prev1,和prev2来代表max(n-1)和max(n-2),将空间复杂度降低为O(1)。值得学习。 +309:参考了reference,难点是动态转移方程的建立,这道题用到了两个动态转移数组,比较难想到,也算一种题型和思路,下次碰到类似提醒,可以想想多种状态,每种状态也有时间顺序变化,状态之间又互相影响,可以通过使用不同的动态转移数组来表示。 +213:是198的变形,快速写完,但是我的代码不够简洁,我将其分为0-n-2和1-n-1两段,然后取其最大值。 +62:这道题印象太深刻了,我面试的时候遇到过,直接DP写出,当然也可以用回溯用递推,很多种方法,dp是最好的方法。我面试的时候做出来了吗,答案是我做出来了,我用了两种回溯和DP,不过DP的递推公式是面试官提示的。 +63:老师上课讲过类似的题型,所以也很快做出来了,这类型题目我觉得都可以通过画图的方式来解决。是同一类型套路题。区别在于有障碍的你只要将那个坐标点设置为0即可。需要注意的是注意初始化的时候dpArray[i][0]和dpArray[0][j]的值,当存在obstacle的话后续的i和j增值所在的位置都为0. 看了discussion后自己尝试了再进一步缩减空间复杂度,将空间复杂度降低为O(1). +784:使用回溯,快速做完,看了下解法有人使用bfs,尝试用bfs再解了一遍。 +337:很快想到用BFS,动态转移方程是Max(n)=Math.max(Max(n-1),sum+Max(n-2))。 + diff --git a/Week_04/id_24/LeetCode_169_024.py b/Week_04/id_24/LeetCode_169_024.py new file mode 100644 index 00000000..84b57c85 --- /dev/null +++ b/Week_04/id_24/LeetCode_169_024.py @@ -0,0 +1,18 @@ +class Solution(object): + def majorityElement(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + nums_dict = {} + for i in range(len(nums)): + if nums[i] in nums_dict: + nums_dict[nums[i]] += 1 + else: + nums_dict[nums[i]] = 1 + if nums_dict[nums[i]] > len(nums)/2: + return nums[i] + +test = [3,2,3,2] + +print(Solution().majorityElement(test)) \ No newline at end of file diff --git a/Week_04/id_24/LeetCode_169_024_v2.py b/Week_04/id_24/LeetCode_169_024_v2.py new file mode 100644 index 00000000..60f0c696 --- /dev/null +++ b/Week_04/id_24/LeetCode_169_024_v2.py @@ -0,0 +1,20 @@ +class Solution(object): + def majorityElement(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + nums.sort() + majority = nums[0] + majority_times = 1 + majority_flag = 0 + for i in range(1, len(nums)): + if nums[i] == majority: + majority_times += 1 + elif nums[i] > nums[i-1]: + majority_flag = i + if i - majority_flag + 1 > majority_times: + majority = nums[i] + majority_times = i - majority_flag - 1 + if majority_times > len(nums) / 2: break + return majority \ No newline at end of file diff --git a/Week_04/id_24/LeetCode_198_024.py b/Week_04/id_24/LeetCode_198_024.py new file mode 100644 index 00000000..5331b8eb --- /dev/null +++ b/Week_04/id_24/LeetCode_198_024.py @@ -0,0 +1,15 @@ +class Solution: + def rob(self, nums: List[int]) -> int: + if not nums: + return 0 + if len(nums) == 1: + return nums[0] + if len(nums) == 2: + return max(nums[0], nums[1]) + dn_2 = nums[0] + dn_1 = max(nums[0], nums[1]) + for i in range(2, len(nums)): + dn = max(dn_1, dn_2 + nums[i]) + dn_2 = dn_1 + dn_1 = dn + return dn \ No newline at end of file diff --git a/Week_04/id_24/LeetCode_309_024.py b/Week_04/id_24/LeetCode_309_024.py new file mode 100644 index 00000000..bba4db0a --- /dev/null +++ b/Week_04/id_24/LeetCode_309_024.py @@ -0,0 +1,18 @@ +class Solution(object): + def maxProfit(self, prices): + """ + :type prices: List[int] + :type fee: int + :rtype: int + """ + if not prices: + return 0 + n = len(prices) + # 0: 卖,1:买, 2:冷冻 + dp = [[0 for _ in range(n)] for _ in range(3)] + dp[1][0] = -prices[0] + for i in range(1,n): + dp[0][i] = max(dp[0][i-1], dp[1][i-1] + prices[i], dp[2][i-1]) + dp[1][i] = max(dp[1][i-1], dp[2][i-1] - prices[i]) + dp[2][i] = dp[0][i-1] + return dp[0][n-1] \ No newline at end of file diff --git a/Week_04/id_24/LeetCode_455_024.py b/Week_04/id_24/LeetCode_455_024.py new file mode 100644 index 00000000..deff1bdf --- /dev/null +++ b/Week_04/id_24/LeetCode_455_024.py @@ -0,0 +1,23 @@ +class Solution(object): + def findContentChildren(self, g, s): + """ + :type g: List[int] + :type s: List[int] + :rtype: int + """ + childs = 0 # 注意:复数是 children + cookies = 0 + g.sort() + s.sort() + for _ in range(len(g) + len(s)): + if childs >= len(g) or cookies >= len(s): break + if g[childs] <= s[cookies]: + childs += 1 + cookies += 1 + return childs + + +g = [1,2,3] +s = [3] + +print(Solution().findContentChildren(g, s)) \ No newline at end of file diff --git a/Week_04/id_24/LeetCode_70_024.py b/Week_04/id_24/LeetCode_70_024.py new file mode 100644 index 00000000..bd01e090 --- /dev/null +++ b/Week_04/id_24/LeetCode_70_024.py @@ -0,0 +1,9 @@ +class Solution: + def climbStairs(self, n: int) -> int: + f = [0 for i in range(n + 1)] + for i in range(n+1): + if i <= 1: + f[i] = 1 + else: + f[i] = f[i-1] + f[i-2] + return f[n] \ No newline at end of file diff --git a/Week_04/id_24/LeetCode_70_024_v2.py b/Week_04/id_24/LeetCode_70_024_v2.py new file mode 100644 index 00000000..1a71d60c --- /dev/null +++ b/Week_04/id_24/LeetCode_70_024_v2.py @@ -0,0 +1,13 @@ +class Solution: + def climbStairs(self, n: int) -> int: + fn_2 = 1 + fn_1 = 1 + fn = 0 + for i in range(n+1): + if i <= 1: + fn = 1 + else: + fn = fn_1 + fn_2 + fn_2 = fn_1 + fn_1 = fn + return fn \ No newline at end of file diff --git a/Week_04/id_24/LeetCode_714_024.py b/Week_04/id_24/LeetCode_714_024.py new file mode 100644 index 00000000..c3762234 --- /dev/null +++ b/Week_04/id_24/LeetCode_714_024.py @@ -0,0 +1,20 @@ +class Solution(object): + def maxProfit(self, prices, fee): + """ + :type prices: List[int] + :type fee: int + :rtype: int + """ + n = len(prices) + # 0: 卖,1:买, + dp = [[0 for _ in range(n)] for _ in range(2)] + dp[1][0] = -prices[0] + for i in range(1,n): + dp[0][i] = max(dp[0][i-1], dp[1][i-1] + prices[i] - fee) + dp[1][i] = max(dp[1][i-1], dp[0][i-1] - prices[i]) + return max(dp[0][n-1], dp[1][n-1]) + +prices = [1,3,2,8,4,9] +fee = 2 + +print(Solution().maxProfit(prices, fee)) \ No newline at end of file diff --git a/Week_04/id_24/LeetCode_714_024_v2.py b/Week_04/id_24/LeetCode_714_024_v2.py new file mode 100644 index 00000000..bda94b63 --- /dev/null +++ b/Week_04/id_24/LeetCode_714_024_v2.py @@ -0,0 +1,16 @@ +class Solution(object): + def maxProfit(self, prices, fee): + """ + :type prices: List[int] + :type fee: int + :rtype: int + """ + n = len(prices) + dp = [[0 for _ in range(2)] for _ in range(2)] + dp[1] = -prices[0] + for i in range(1,n): + dp[0][1] = max(dp[0][0], dp[1][0] + prices[i] - fee) + dp[1][1] = max(dp[1][0], dp[0][0] - prices[i]) + dp[0][0] = dp[0][1] + dp[1][0] = dp[1][1] + return dp[0][1] \ No newline at end of file diff --git a/Week_04/id_24/LeetCode_784_024.py b/Week_04/id_24/LeetCode_784_024.py new file mode 100644 index 00000000..4138f1a1 --- /dev/null +++ b/Week_04/id_24/LeetCode_784_024.py @@ -0,0 +1,23 @@ +import re +class Solution(object): + def letterCasePermutation(self, S): + """ + :type S: str + :rtype: List[str] + """ + s = S.lower() + results = [''] + f = [] + + for i in range(0, len(s)): + for j in range(len(results)): + if re.match('[a-z]', s[i]): + f.append(results[j] + s[i].upper()) + results[j] = results[j] + s[i] + results = results + f + f = [] + return results + +test = "a1B2" + +print(Solution().letterCasePermutation(test)) \ No newline at end of file diff --git a/Week_04/id_25/LeetCode_198_025.java b/Week_04/id_25/LeetCode_198_025.java new file mode 100644 index 00000000..f107bb62 --- /dev/null +++ b/Week_04/id_25/LeetCode_198_025.java @@ -0,0 +1,58 @@ +package com.mootal.algo.month_1.week_1.day5_198; + +/** + * Easy + * (注解文档查看快捷键 选中类名或方法名 按ctrl + Q) + *

+ * 思维全过程记录方案:

+ * 1 背基础结构和算法 | 记录在课程笔记

+ * 2 看题 -> 悟题 思考过程 | 记录在wiki

+ * 3 悟题 -> 写题 实现难点 | 记录在代码注解

+ * 4 写题 -> 优化 多种解法 | 记录在leetcode提交 + *

+ * 问题: + * You are a professional robber planning to rob houses along a street. + * Each house has a certain amount of money stashed, the only constraint stopping you + * from robbing each of them is that adjacent houses have security system connected and + * it will automatically contact the police if two adjacent houses were broken into on the same night. + * Given a list of non-negative integers representing the amount of money of each house, + * determine the maximum amount of money you can rob tonight without alerting the police. + *

+ * 题解方案topics: + * dp + * + * @author li tong + * @date 2019/6/7 9:41 + * @see Object + * @since 1.0 + */ +public class LeetCode_198_025 { + + public static void main(String[] args) { + int[] test = new int[]{2, 7, 1, 4, 9, 3}; + System.out.println(rob(test)); + } + + /** + * 解法1 dp

+ * + * @param nums + * @return + */ + static int rob(int[] nums) { + int res = 0; + if (nums.length == 0) { + return 0; + } else if (nums.length == 1) { + return nums[0]; + } + int[] dp = new int[nums.length]; + dp[0] = nums[0]; + dp[1] = Math.max(nums[0], nums[1]); + for (int i = 2; i < nums.length; i++) { + dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]); + } + return dp[nums.length - 1]; + } + +} diff --git a/Week_04/id_25/LeetCode_403_025.java b/Week_04/id_25/LeetCode_403_025.java new file mode 100644 index 00000000..04de1d91 --- /dev/null +++ b/Week_04/id_25/LeetCode_403_025.java @@ -0,0 +1,66 @@ +package com.mootal.algo.month_1.week_4.day_23; + +/** + * Hard + * (注解文档查看快捷键 选中类名或方法名 按ctrl + Q) + *

+ * 思维全过程记录方案:

+ * 1 背基础结构和算法 | 记录在课程笔记

+ * 2 看题 -> 悟题 思考过程 | 记录在wiki

+ * 3 悟题 -> 写题 实现难点 | 记录在代码注解

+ * 4 写题 -> 优化 多种解法 | 记录在leetcode提交 + *

+ * 问题: + * A frog is crossing a river. + * The river is divided into x units and at each unit there may or may not exist a stone. + * The frog can jump on a stone, but it must not jump into the water. + *

+ * Given a list of stones' positions (in units) in sorted ascending order, + * determine if the frog is able to cross the river by landing on the last stone. + * Initially, the frog is on the first stone and assume the first jump must be 1 unit. + *

+ * If the frog's last jump was k units, then its next jump must be either k - 1, k, or k + 1 units. + * Note that the frog can only jump in the forward direction. + *

+ * Note: + *

  • The number of stones is ≥ 2 and is < 1,100.
  • + *
  • Each stone's position will be a non-negative integer < 231.
  • + *
  • The first stone's position is always 0.
  • + *

    + * 题解方案topics: + * dp + * + * @author li tong + * @date 2019/6/25 11:41 + * @see Object + * @since 1.0 + */ +public class LeetCode_403_025 { + + public static void main(String[] args) { + int[] stones = new int[]{0, 1, 3, 5, 6, 8, 12, 17, 2147483647}; + System.out.println(canCross1(stones)); + } + + public static boolean canCross1(int[] stones) { + if (stones == null || stones.length == 0) { + return false; + } + boolean[][] dp = new boolean[stones.length][stones.length + 1]; + dp[0][1] = true; + for (int i = 1; i < stones.length; i++) { + for (int j = 0; j < i; j++) { + int jump = stones[i] - stones[j]; + if (jump < 0 || jump > stones.length || !dp[j][jump]) continue; + if (jump - 1 >= 0) dp[i][jump - 1] = true; + dp[i][jump] = true; + if (jump + 1 <= stones.length) dp[i][jump + 1] = true; + if (i == stones.length - 1) { + return true; + } + } + } + return false; + } + +} diff --git a/Week_04/id_26/LeetCode_169_26.py b/Week_04/id_26/LeetCode_169_26.py new file mode 100644 index 00000000..c54a30c6 --- /dev/null +++ b/Week_04/id_26/LeetCode_169_26.py @@ -0,0 +1,78 @@ +# +# @lc app=leetcode.cn id=169 lang=python +# +# [169] 求众数 +# +# https://leetcode-cn.com/problems/majority-element/description/ +# +# algorithms +# Easy (59.48%) +# Likes: 261 +# Dislikes: 0 +# Total Accepted: 49.3K +# Total Submissions: 82.6K +# Testcase Example: '[3,2,3]' +# +# 给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。 +# +# 你可以假设数组是非空的,并且给定的数组总是存在众数。 +# +# 示例 1: +# +# 输入: [3,2,3] +# 输出: 3 +# +# 示例 2: +# +# 输入: [2,2,1,1,1,2,2] +# 输出: 2 +# +# +# + + +class Solution(object): + def majorityElement1(self, nums): + """ + :type nums: List[int] + :rtype: int + 解法1:排序 + """ + nums.sort() + return nums[len(nums)//2] + + def majorityElement(self, nums): + """ + :type nums: List[int] + :rtype: int + 解法2: 递归+分治 + 分治问题模板步骤: + 1.结束条件 + 2.拆分子问题 + 3.递归处理子问题 + 4.处理子问题的结果 + """ + def helper(left, right): + + if left == right: + return nums[left] + + mid = (right+left) // 2 + + leftNum = helper(left, mid) + rightNum = helper(mid+1, right) + + if leftNum == rightNum: + return leftNum + leftCount, rightCount = 0, 0 + for i in range(left, right+1): + if nums[i] == leftNum: + leftCount += 1 + elif nums[i] == rightNum: + rightCount += 1 + return leftNum if leftCount >= rightCount else rightNum + + return helper(0, len(nums)-1) + + +# print(Solution().majorityElement([1, 2, 1, 3, 1, 2, 1])) diff --git a/Week_04/id_26/LeetCode_208_26.py b/Week_04/id_26/LeetCode_208_26.py new file mode 100644 index 00000000..b1765ecb --- /dev/null +++ b/Week_04/id_26/LeetCode_208_26.py @@ -0,0 +1,101 @@ +# +# @lc app=leetcode.cn id=208 lang=python +# +# [208] 实现 Trie (前缀树) +# +# https://leetcode-cn.com/problems/implement-trie-prefix-tree/description/ +# +# algorithms +# Medium (58.88%) +# Likes: 77 +# Dislikes: 0 +# Total Accepted: 8K +# Total Submissions: 13.5K +# Testcase Example: '["Trie","insert","search","search","startsWith","insert","search"]\n[[],["apple"],["apple"],["app"],["app"],["app"],["app"]]' +# +# 实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作。 +# +# 示例: +# +# Trie trie = new Trie(); +# +# trie.insert("apple"); +# trie.search("apple"); // 返回 true +# trie.search("app"); // 返回 false +# trie.startsWith("app"); // 返回 true +# trie.insert("app"); +# trie.search("app"); // 返回 true +# +# 说明: +# +# +# 你可以假设所有的输入都是由小写字母 a-z 构成的。 +# 保证所有输入均为非空字符串。 +# +# +# + + +class TireNode(object): + def __init__(self): + self.children = {} + self.end = False + + +class Trie(object): + + def __init__(self): + """ + Initialize your data structure here. + """ + self.root = TireNode() + + def insert(self, word): + """ + Inserts a word into the trie. + :type word: str + :rtype: None + """ + node = self.root + for c in word: + if c not in node.children: + node.children[c] = TireNode() + node = node.children[c] + node.end = True + + def search(self, word): + """ + Returns if the word is in the trie. + :type word: str + :rtype: bool + """ + node = self.root + for c in word: + if c not in node.children: + return False + node = node.children[c] + return node.end + + def startsWith(self, prefix): + """ + Returns if there is any word in the trie that starts with the given prefix. + :type prefix: str + :rtype: bool + """ + node = self.root + for c in prefix: + if c not in node.children: + return False + node = node.children[c] + return True + + +# Your Trie object will be instantiated and called as such: +# trie = Trie() +# print(trie.insert("apple")) +# print(trie.search("apple")) +# print(trie.search("app")) +# print(trie.startsWith("app")) +# print(trie.insert("app")) +# print(trie.search("app")) + diff --git a/Week_04/id_26/LeetCode_211_26.py b/Week_04/id_26/LeetCode_211_26.py new file mode 100644 index 00000000..4166d498 --- /dev/null +++ b/Week_04/id_26/LeetCode_211_26.py @@ -0,0 +1,89 @@ +# +# @lc app=leetcode.cn id=211 lang=python +# +# [211] 添加与搜索单词 - 数据结构设计 +# +# https://leetcode-cn.com/problems/add-and-search-word-data-structure-design/description/ +# +# algorithms +# Medium (38.92%) +# Likes: 51 +# Dislikes: 0 +# Total Accepted: 2.8K +# Total Submissions: 7.3K +# Testcase Example: '["WordDictionary","addWord","addWord","addWord","search","search","search","search"]\n[[],["bad"],["dad"],["mad"],["pad"],["bad"],[".ad"],["b.."]]' +# +# 设计一个支持以下两种操作的数据结构: +# +# void addWord(word) +# bool search(word) +# +# +# search(word) 可以搜索文字或正则表达式字符串,字符串只包含字母 . 或 a-z 。 . 可以表示任何一个字母。 +# +# 示例: +# +# addWord("bad") +# addWord("dad") +# addWord("mad") +# search("pad") -> false +# search("bad") -> true +# search(".ad") -> true +# search("b..") -> true +# +# +# 说明: +# +# 你可以假设所有单词都是由小写字母 a-z 组成的。 +# +# + + +class TrieNode(object): + def __init__(self): + self.children = {} + self.end = False + + +class WordDictionary(object): + + def __init__(self): + """ + Initialize your data structure here. + """ + self.root = TrieNode() + + def addWord(self, word): + """ + Adds a word into the data structure. + :type word: str + :rtype: None + """ + node = self.root + for c in word: + if c not in node.children: + node.children[c] = TrieNode() + node = node.children[c] + node.end = True + + def search(self, word): + """ + Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. + :type word: str + :rtype: bool + """ + self.ans = False + self._match(self.root, word) + return self.ans + + def _match(self, root, word): + if not word: + if root.end: + self.ans = root.end + return + if word[0] == '.': + for node in root.children.values(): + self._match(node, word[1:]) + if word[0] not in root.children: + return + self._match(root.children[word[0]], word[1:]) diff --git a/Week_04/id_26/LeetCode_240_26.py b/Week_04/id_26/LeetCode_240_26.py new file mode 100644 index 00000000..9426a00a --- /dev/null +++ b/Week_04/id_26/LeetCode_240_26.py @@ -0,0 +1,69 @@ +# +# @lc app=leetcode.cn id=240 lang=python +# +# [240] 搜索二维矩阵 II +# +# https://leetcode-cn.com/problems/search-a-2d-matrix-ii/description/ +# +# algorithms +# Medium (36.82%) +# Likes: 111 +# Dislikes: 0 +# Total Accepted: 17.8K +# Total Submissions: 48.2K +# Testcase Example: '[[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]]\n5' +# +# 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该矩阵具有以下特性: +# +# +# 每行的元素从左到右升序排列。 +# 每列的元素从上到下升序排列。 +# +# +# 示例: +# +# 现有矩阵 matrix 如下: +# +# [ +# ⁠ [1, 4, 7, 11, 15], +# ⁠ [2, 5, 8, 12, 19], +# ⁠ [3, 6, 9, 16, 22], +# ⁠ [10, 13, 14, 17, 24], +# ⁠ [18, 21, 23, 26, 30] +# ] +# +# +# 给定 target = 5,返回 true。 +# +# 给定 target = 20,返回 false。 +# +# + + +class Solution(object): + def searchMatrix(self, matrix, target): + """ + :type matrix: List[List[int]] + :type target: int + :rtype: bool + 思路:从左下角开始,相等直接返回 + 若大于目标值,则不可能在这一列,指针向左 + 若小于目标值,则不可能在这一排,指针向上 + 时间复杂度O(m+n) + """ + if not matrix or not matrix[0]: + return False + m, n = len(matrix)-1, 0 + + while m >= 0 and n < len(matrix[0]): + if matrix[m][n] == target: + return True + if matrix[m][n] < target: + n += 1 + else: + m -= 1 + return False + + +# print(Solution().searchMatrix([[1, 4, 7, 11, 15], [2, 5, 8, 12, 19], [ + # 3, 6, 9, 16, 22], [10, 13, 14, 17, 24], [18, 21, 23, 26, 30]], 333)) diff --git a/Week_04/id_26/LeetCode_46_26.py b/Week_04/id_26/LeetCode_46_26.py new file mode 100644 index 00000000..73b4df32 --- /dev/null +++ b/Week_04/id_26/LeetCode_46_26.py @@ -0,0 +1,54 @@ +# +# @lc app=leetcode.cn id=46 lang=python +# +# [46] 全排列 +# +# https://leetcode-cn.com/problems/permutations/description/ +# +# algorithms +# Medium (69.33%) +# Likes: 291 +# Dislikes: 0 +# Total Accepted: 28.6K +# Total Submissions: 41.1K +# Testcase Example: '[1,2,3]' +# +# 给定一个没有重复数字的序列,返回其所有可能的全排列。 +# +# 示例: +# +# 输入: [1,2,3] +# 输出: +# [ +# ⁠ [1,2,3], +# ⁠ [1,3,2], +# ⁠ [2,1,3], +# ⁠ [2,3,1], +# ⁠ [3,1,2], +# ⁠ [3,2,1] +# ] +# +# + + +class Solution(object): + def permute(self, nums): + """ + :type nums: List[int] + :rtype: List[List[int]] + 时间复杂度:O(n^2) + """ + ans = [] + n = len(nums) + + def helper(path=[], invited=set()): + if len(path) == n: + return ans.append(path) + for j in nums: + if j not in invited: + invited.add(j) + helper(path+[j], invited) + invited.remove(j) + + helper() + return ans diff --git a/Week_04/id_26/LeetCode_51_26.py b/Week_04/id_26/LeetCode_51_26.py new file mode 100644 index 00000000..45652f1a --- /dev/null +++ b/Week_04/id_26/LeetCode_51_26.py @@ -0,0 +1,96 @@ +# +# @lc app=leetcode.cn id=51 lang=python +# +# [51] N皇后 +# +# https://leetcode-cn.com/problems/n-queens/description/ +# +# algorithms +# Hard (62.79%) +# Likes: 181 +# Dislikes: 0 +# Total Accepted: 9K +# Total Submissions: 14.2K +# Testcase Example: '4' +# +# n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。 +# +# +# +# 上图为 8 皇后问题的一种解法。 +# +# 给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。 +# +# 每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。 +# +# 示例: +# +# 输入: 4 +# 输出: [ +# ⁠[".Q..", // 解法 1 +# ⁠ "...Q", +# ⁠ "Q...", +# ⁠ "..Q."], +# +# ⁠["..Q.", // 解法 2 +# ⁠ "Q...", +# ⁠ "...Q", +# ⁠ ".Q.."] +# ] +# 解释: 4 皇后问题存在两个不同的解法。 +# +# +# + + +class Solution(object): + + def solveNQueens1(self, n): + """ + :type n: int + :rtype: List[List[str]] + 解法1:深度遍历,用set记录和、差、列 + """ + ans = [] + + def dfs(i, col=set(), add=set(), minus=set(), grid=[]): + if i == n: + return ans.append(grid) + for j in range(n): + if j not in col and i + j not in add and i - j not in minus: + col.add(j) + add.add(i+j) + minus.add(i-j) + line = ''.join(['Q' if m == j else '.' for m in range(n)]) + dfs(i+1, col, add, minus, grid + [line]) + col.remove(j) + add.remove(i+j) + minus.remove(i-j) + dfs(0) + return ans + + def solveNQueens(self, n): + """ + :type n: int + :rtype: List[List[str]] + 解法2:深度遍历,用位记录和、差、列 + """ + ans = [] + + def dfs(pos=[], row=0, col=0, pie=0, na=0): + if row == n: + ans.append(pos) + return + bits = ~(col | pie | na) & ((1 << n) - 1) + while bits > 0: + p = bits & -bits + line = ''.join(['Q' if p >> i & 1 else '.' for i in range(n)]) + dfs(pos + [line], row + 1, col | p, + (pie | p) << 1, (na | p) >> 1) + bits &= bits - 1 + + dfs() + return ans + + +print(Solution().solveNQueens(4)) diff --git a/Week_04/id_26/LeetCode_53_26.py b/Week_04/id_26/LeetCode_53_26.py new file mode 100644 index 00000000..8e8c8391 --- /dev/null +++ b/Week_04/id_26/LeetCode_53_26.py @@ -0,0 +1,56 @@ +# +# @lc app=leetcode.cn id=53 lang=python +# +# [53] 最大子序和 +# +# https://leetcode-cn.com/problems/maximum-subarray/description/ +# +# algorithms +# Easy (45.36%) +# Likes: 995 +# Dislikes: 0 +# Total Accepted: 64.5K +# Total Submissions: 141.4K +# Testcase Example: '[-2,1,-3,4,-1,2,1,-5,4]' +# +# 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 +# +# 示例: +# +# 输入: [-2,1,-3,4,-1,2,1,-5,4], +# 输出: 6 +# 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。 +# +# +# 进阶: +# +# 如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。 +# +# + + +class Solution(object): + def maxSubArray1(self, nums): + """ + :type nums: List[int] + :rtype: int + 解法1:动态规划,dp[i]表示包含i的最大连续子数组和 + """ + dp = [i for i in nums] + for i in range(1, len(nums)): + dp[i] = max(dp[i-1], 0) + nums[i] + return max(dp) + + def maxSubArray(self, nums): + """ + 解法2:跟动态规划的思路类似,只需要记录包含当前节点的最大子数组和 + """ + ret, _max = nums[0], nums[0] + for i in range(1, len(nums)): + _max = max(_max, 0) + nums[i] + ret = max(ret, _max) + return ret + + +print(Solution().maxSubArray1([1])) +print(Solution().maxSubArray1([-2, 1, -3, 4, -1, 2, 1, -5, 4])) diff --git a/Week_04/id_26/LeetCode_70_26.py b/Week_04/id_26/LeetCode_70_26.py new file mode 100644 index 00000000..71457fb8 --- /dev/null +++ b/Week_04/id_26/LeetCode_70_26.py @@ -0,0 +1,72 @@ +# +# @lc app=leetcode.cn id=70 lang=python +# +# [70] 爬楼梯 +# +# https://leetcode-cn.com/problems/climbing-stairs/description/ +# +# algorithms +# Easy (45.50%) +# Likes: 513 +# Dislikes: 0 +# Total Accepted: 54.7K +# Total Submissions: 119.8K +# Testcase Example: '2' +# +# 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 +# +# 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? +# +# 注意:给定 n 是一个正整数。 +# +# 示例 1: +# +# 输入: 2 +# 输出: 2 +# 解释: 有两种方法可以爬到楼顶。 +# 1. 1 阶 + 1 阶 +# 2. 2 阶 +# +# 示例 2: +# +# 输入: 3 +# 输出: 3 +# 解释: 有三种方法可以爬到楼顶。 +# 1. 1 阶 + 1 阶 + 1 阶 +# 2. 1 阶 + 2 阶 +# 3. 2 阶 + 1 阶 +# +# +# + + +class Solution(object): + def climbStairs1(self, n): + """ + :type n: int + :rtype: int + """ + if not n: + return n + dp = [0] * (n+1) + dp[0] = dp[1] = 1 + for i in range(2, n+1): + dp[i] = dp[i-1]+dp[i-2] + return dp[n] + + def climbStairs2(self, n): + """ + :type n: int + :rtype: int + """ + if not n: + return n + a, b = 1, 1 + for i in range(2, n+1): + b, a = a + b, b + return b + + +# print(Solution().climbStairs2(1)) +# print(Solution().climbStairs2(3)) +# print(Solution().climbStairs2(4)) diff --git a/Week_04/id_26/LeetCode_720_26.py b/Week_04/id_26/LeetCode_720_26.py new file mode 100644 index 00000000..e25c4487 --- /dev/null +++ b/Week_04/id_26/LeetCode_720_26.py @@ -0,0 +1,151 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- +# @lc app=leetcode.cn id=720 lang=python +# +# [720] 词典中最长的单词 +# +# https://leetcode-cn.com/problems/longest-word-in-dictionary/description/ +# +# algorithms +# Easy (42.52%) +# Likes: 36 +# Dislikes: 0 +# Total Accepted: 2.7K +# Total Submissions: 6.3K +# Testcase Example: '["w","wo","wor","worl","world"]' +# +# +# 给出一个字符串数组words组成的一本英语词典。从中找出最长的一个单词,该单词是由words词典中其他单词逐步添加一个字母组成。若其中有多个可行的答案,则返回答案中字典序最小的单词。 +# +# 若无答案,则返回空字符串。 +# +# 示例 1: +# +# +# 输入: +# words = ["w","wo","wor","worl", "world"] +# 输出: "world" +# 解释: +# 单词"world"可由"w", "wo", "wor", 和 "worl"添加一个字母组成。 +# +# +# 示例 2: +# +# +# 输入: +# words = ["a", "banana", "app", "appl", "ap", "apply", "apple"] +# 输出: "apple" +# 解释: +# "apply"和"apple"都能由词典中的单词组成。但是"apple"得字典序小于"apply"。 +# +# +# 注意: +# +# +# 所有输入的字符串都只包含小写字母。 +# words数组长度范围为[1,1000]。 +# words[i]的长度范围为[1,30]。 +# +# +# + + +import collections + + +class Solution(object): + def longestWord1(self, words): + """ + :type words: List[str] + :rtype: str + 解法1: 先排序,后面的单词去掉最后一个字母在前面出现过则添加入集合,找出最长的即可,相同长度取前面的 + """ + words.sort() + visited, ans = set(), '' + for word in words: + if len(word) == 1 or word[:-1] in visited: + visited.add(word) + if len(ans) < len(word): + ans = word + return ans + + def longestWord(self, words): + """ + :type words: List[str] + :rtype: str + 解法2: 字典树 + 使用两种不同的遍历方式 + """ + trie = Trie() + for word in words: + trie.insert(word) + # return trie.longest2() + return trie.longest1() + + +class TrieNode: + def __init__(self): + self.children = {} + self.word = '' + self.end = False + + +class Trie: + def __init__(self): + self.root = TrieNode() + + def insert(self, word): + node = self.root + for c in word: + if c not in node.children: + node.children[c] = TrieNode() + node = node.children[c] + node.end = True + node.word = word + + def longest1(self): + import collections + queue = collections.deque([self.root]) + ans = '' + + while queue: + node = queue.pop() + for c, n in node.children.items(): + if n.end: + queue.append(n) + if len(ans) < len(n.word) or n.word < ans: + ans = n.word + return ans + + def longest2(self): + self.ans = '' + + def dfs(node): + for c, n in node.children.items(): + if n.end: + dfs(n) + if len(self.ans) < len(n.word) or (len(self.ans) == len(n.word) and self.ans > n.word): + self.ans = n.word + + dfs(self.root) + return self.ans + + +# print(Solution().longestWord( + # ["a", "banana", "app", "appl", "ap", "apply", "apple"])) +# print(Solution().longestWord(["w", "wo", "wor", "worl", "world"])) +# print(Solution().longestWord(["m", "mo", "moc", "moch", "mocha", + # "l", "la", "lat", "latt", "latte", "c", "ca", "cat"])) +# print(Solution().longestWord(["rac", "rs", "ra", "on", "r", +# "otif", "o", "onpdu", "rsf", "rs", "ot", "oti", "racy", "onpd"])) +# print(Solution().longestWord(["yo", "ew", "fc", "zrc", "yodn", +# "fcm", "qm", "qmo", "fcmz", "z", "ewq", "yod", "ewqz", "y"])) +# print(Solution().longestWord(["m", "mo", "moc", "moch", "mocha", +# "l", "la", "lat", "latt", "latte", "c", "ca", "cat"])) + + +# queue = collections.deque() +# for i in [1, 2, 3, 4, 5, 6, 7, 8]: +# queue.append(i) +# while queue: +# print(queue.pop()) diff --git a/Week_04/id_26/LeetCode_77_26.py b/Week_04/id_26/LeetCode_77_26.py new file mode 100644 index 00000000..a9f6c0f8 --- /dev/null +++ b/Week_04/id_26/LeetCode_77_26.py @@ -0,0 +1,53 @@ +# +# @lc app=leetcode.cn id=77 lang=python +# +# [77] 组合 +# +# https://leetcode-cn.com/problems/combinations/description/ +# +# algorithms +# Medium (68.18%) +# Likes: 125 +# Dislikes: 0 +# Total Accepted: 12.9K +# Total Submissions: 18.8K +# Testcase Example: '4\n2' +# +# 给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。 +# +# 示例: +# +# 输入: n = 4, k = 2 +# 输出: +# [ +# ⁠ [2,4], +# ⁠ [3,4], +# ⁠ [2,3], +# ⁠ [1,2], +# ⁠ [1,3], +# ⁠ [1,4], +# ] +# +# + + +class Solution(object): + def combine(self, n, k): + """ + :type n: int + :type k: int + :rtype: List[List[int]] + """ + ans = [] + + def helper(path=[]): + if len(path) == k: + return ans.append(path) + for i in range(path[-1] + 1 if path else 1, n+1): + helper(path+[i]) + helper() + return ans + + +# print(Solution().combine(4, 2)) +# print(Solution().combine(0, 0)) diff --git a/Week_04/id_26/LeetCode_784_26.py b/Week_04/id_26/LeetCode_784_26.py new file mode 100644 index 00000000..70a1a5d6 --- /dev/null +++ b/Week_04/id_26/LeetCode_784_26.py @@ -0,0 +1,62 @@ +# +# @lc app=leetcode.cn id=784 lang=python +# +# [784] 字母大小写全排列 +# +# https://leetcode-cn.com/problems/letter-case-permutation/description/ +# +# algorithms +# Easy (55.43%) +# Likes: 76 +# Dislikes: 0 +# Total Accepted: 5.3K +# Total Submissions: 9.5K +# Testcase Example: '"a1b2"' +# +# 给定一个字符串S,通过将字符串S中的每个字母转变大小写,我们可以获得一个新的字符串。返回所有可能得到的字符串集合。 +# +# +# 示例: +# 输入: S = "a1b2" +# 输出: ["a1b2", "a1B2", "A1b2", "A1B2"] +# +# 输入: S = "3z4" +# 输出: ["3z4", "3Z4"] +# +# 输入: S = "12345" +# 输出: ["12345"] +# +# +# 注意: +# +# +# S 的长度不超过12。 +# S 仅由数字和字母组成。 +# +# +# + + +class Solution(object): + def letterCasePermutation(self, S): + """ + :type S: str + :rtype: List[str] + """ + paths = [] + + def helper(i, path=''): + if i == len(S): + return paths.append(path) + if S[i].isdigit(): + return helper(i+1, path+S[i]) + helper(i+1, path + S[i].lower()) + helper(i+1, path + S[i].upper()) + helper(0) + return paths + + +# print(Solution().letterCasePermutation('3z4')) +# print(Solution().letterCasePermutation('12345')) +# print(Solution().letterCasePermutation('a1b2')) +# print(Solution().letterCasePermutation('')) diff --git a/Week_04/id_26/LeetCode_78_26.py b/Week_04/id_26/LeetCode_78_26.py new file mode 100644 index 00000000..6953c202 --- /dev/null +++ b/Week_04/id_26/LeetCode_78_26.py @@ -0,0 +1,57 @@ +# +# @lc app=leetcode.cn id=78 lang=python +# +# [78] 子集 +# +# https://leetcode-cn.com/problems/subsets/description/ +# +# algorithms +# Medium (73.61%) +# Likes: 264 +# Dislikes: 0 +# Total Accepted: 22.9K +# Total Submissions: 31K +# Testcase Example: '[1,2,3]' +# +# 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。 +# +# 说明:解集不能包含重复的子集。 +# +# 示例: +# +# 输入: nums = [1,2,3] +# 输出: +# [ +# ⁠ [3], +# [1], +# [2], +# [1,2,3], +# [1,3], +# [2,3], +# [1,2], +# [] +# ] +# +# + + +class Solution(object): + def subsets(self, nums): + """ + :type nums: List[int] + :rtype: List[List[int]] + """ + paths = set() + + def helper(i, path=()): + paths.add(path) + if i == len(nums): + return + helper(i+1, path + (nums[i],)) + helper(i+1, path) + + helper(0) + return [list(i) for i in paths] + + +# print(Solution().subsets([1, 2, 3])) diff --git a/Week_04/id_28/LeetCode_198_28.java b/Week_04/id_28/LeetCode_198_28.java new file mode 100644 index 00000000..ebada7e0 --- /dev/null +++ b/Week_04/id_28/LeetCode_198_28.java @@ -0,0 +1,29 @@ +public class LeetCode_198_28 { + public int rob(int[] nums) { + + + Integer[] arr=new Integer[nums.length]; + //Integer max=Integer.MIN_VALUE; + return nums.length==0 ? 0 : dp(nums,arr,nums.length-1); + + } + + public int dp(int[] nums,Integer[] arr,int i){ + if(arr[i] == null){ + if (i==0){ + arr[i] = nums[0]; + }else if(i==1){ + arr[i] = Math.max(nums[0],nums[1]); + }else { + arr[i]=Math.max(dp(nums,arr,i-2)+nums[i],dp(nums,arr,i-1)); + } + } + return arr[i]; + } + + public static void main(String[] args) { + int[] arr= {1,2,3,1}; + System.out.println(new LeetCode_198_28().rob(arr)); + System.out.println("hello"); + } +} diff --git a/Week_04/id_28/LeetCode_213_28.java b/Week_04/id_28/LeetCode_213_28.java new file mode 100644 index 00000000..c1b5639a --- /dev/null +++ b/Week_04/id_28/LeetCode_213_28.java @@ -0,0 +1,47 @@ +public class LeetCode_213_28 { + public int rob(int[] nums) { + + + Integer[] arr1=new Integer[nums.length]; + Integer[] arr2=new Integer[nums.length]; + + return nums.length==0 ? 0 : Math.max(dp1(nums,arr1,nums.length-1),dp2(nums,arr2,nums.length-1)); + + } + + public int dp1(int[] nums,Integer[] arr,int i){ + if(arr[i] == null){ + if (i==0){ + arr[i] = nums[0]; + }else if(i==1){ + arr[i] = nums[0]; + }else if(i map=new HashMap(); + return dp(root,map); + + } + + public Integer dp(TreeNode node,Map map){ + if (node==null){ + return 0; + } + if(!map.containsKey(node) ){ + int left=dp(node.left,map); + int right=dp(node.right,map); + int left_left=(node.left==null? 0:dp(node.left.left,map)); + int left_right=(node.left==null? 0:dp(node.left.right,map)); + int right_left=(node.right==null? 0:dp(node.right.left,map)); + int right_right=(node.right==null? 0:dp(node.right.right,map)); + map.put(node,Math.max(Math.max(Math.max(left+right, + (node.left==null? 0:node.left.val)+right_left+right_right), + (node.right==null? 0:node.right.val)+left_left+left_right), + node.val+left_left+left_right+right_left+right_right)); + } + System.out.println(map.get(node)); + return map.get(node); + } + + public static void main(String[] args) { + TreeNode root=new TreeNode(1); + root.left=new TreeNode(2); + root.right=new TreeNode(3); + System.out.println(new LeetCode_337_28().rob(root)); + } +} diff --git a/Week_04/id_28/LeetCode_53_28.java b/Week_04/id_28/LeetCode_53_28.java new file mode 100644 index 00000000..90a2e3ac --- /dev/null +++ b/Week_04/id_28/LeetCode_53_28.java @@ -0,0 +1,34 @@ +public class LeetCode_53_28 { + + public int maxSubArray(int[] nums) { + + int maxArrayLength=Integer.MIN_VALUE; + Integer[] arr=new Integer[nums.length]; + for (int i=0;i b { + return a + } + return b +} diff --git a/Week_04/id_29/LeetCode_169_29.go b/Week_04/id_29/LeetCode_169_29.go new file mode 100644 index 00000000..dda58671 --- /dev/null +++ b/Week_04/id_29/LeetCode_169_29.go @@ -0,0 +1,19 @@ +package week4 + +func majorityElement(nums []int) int { + x, t := nums[0], 1 + + for i := 1; i < len(nums); i++ { + switch { + case x == nums[i]: + t++ + case t > 0: + t-- + default: + x = nums[i] + t = 1 + } + } + + return x +} diff --git a/Week_04/id_29/LeetCode_208_29.go b/Week_04/id_29/LeetCode_208_29.go new file mode 100644 index 00000000..51abdc04 --- /dev/null +++ b/Week_04/id_29/LeetCode_208_29.go @@ -0,0 +1,58 @@ +package week4 + +type Trie struct { + val byte + sons [26]*Trie + end int +} + +func Constructor() Trie { + return Trie{} +} + +func (this *Trie) Insert(word string) { + node := this + size := len(word) + for i := 0; i < size; i++ { + idx := word[i] - 'a' + if node.sons[idx] == nil { + node.sons[idx] = &Trie{val: word[i]} + } + + node = node.sons[idx] + } + + node.end++ +} + +func (this *Trie) Search(word string) bool { + node := this + size := len(word) + for i := 0; i < size; i++ { + idx := word[i] - 'a' + if node.sons[idx] == nil { + return false + } + node = node.sons[idx] + } + + if node.end > 0 { + return true + } + + return false +} + +func (this *Trie) StartsWith(prefix string) bool { + node := this + size := len(prefix) + for i := 0; i < size; i++ { + idx := prefix[i] - 'a' + if node.sons[idx] == nil { + return false + } + node = node.sons[idx] + } + + return true +} diff --git a/Week_04/id_29/LeetCode_211_29.go b/Week_04/id_29/LeetCode_211_29.go new file mode 100644 index 00000000..3c48eb26 --- /dev/null +++ b/Week_04/id_29/LeetCode_211_29.go @@ -0,0 +1,64 @@ +package week4 + +type WordDictionary struct { + sons [26]*WordDictionary + end int +} + +/** Initialize your data structure here. */ +func Constructor() WordDictionary { + return WordDictionary{} +} + +/** Adds a word into the data structure. */ +func (this *WordDictionary) AddWord(word string) { + for _, b := range word { + idx := b - 'a' + if this.sons[idx] == nil { + this.sons[idx] = &WordDictionary{} + } + this = this.sons[idx] + } + + this.end++ +} + +/** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */ +func (this *WordDictionary) Search(word string) bool { + for i, b := range word { + if b != '.' { + idx := b - 'a' + if this.sons[idx] == nil { + return false + } + + this = this.sons[idx] + } else { + for _, son := range this.sons { + if son == nil { + continue + } + + this = son + if i == len(word)-1 { + if this.end > 0 { + return true + } + continue + } + + if this.Search(word[i+1:]) { + return true + } + } + + return false + } + } + + if this.end > 0 { + return true + } + + return false +} diff --git a/Week_04/id_29/LeetCode_212_29.go b/Week_04/id_29/LeetCode_212_29.go new file mode 100644 index 00000000..1daebdff --- /dev/null +++ b/Week_04/id_29/LeetCode_212_29.go @@ -0,0 +1,81 @@ +package week4 + +func findWords(board [][]byte, words []string) []string { + var results []string + + m := len(board) + if m == 0 { + return results + } + + n := len(board[0]) + if n == 0 { + return results + } + + trie := buildTrie(words) + + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + dfs(board, i, j, trie, &results) + } + } + + return results +} + +func dfs(board [][]byte, i int, j int, trie *TrieNode, results *[]string) { + c := board[i][j] + if c == '#' || trie.next[int(c-'a')] == nil { + return + } + + trie = trie.next[int(c-'a')] + if len(trie.word) > 0 { + // Found one + *results = append(*results, trie.word) + trie.word = "" + } + + board[i][j] = '#' + if i > 0 { + dfs(board, i-1, j, trie, results) + } + + if i < len(board)-1 { + dfs(board, i+1, j, trie, results) + } + + if j > 0 { + dfs(board, i, j-1, trie, results) + } + + if j < len(board[0])-1 { + dfs(board, i, j+1, trie, results) + } + + board[i][j] = c +} + +func buildTrie(words []string) *TrieNode { + root := new(TrieNode) + for _, word := range words { + cur := root + for _, c := range word { + cidx := int(c - 'a') + if cur.next[cidx] == nil { + cur.next[cidx] = new(TrieNode) + } + cur = cur.next[cidx] + } + cur.word = word + } + + return root +} + +// TrieNode 是 trie 的节点 +type TrieNode struct { + next [26]*TrieNode + word string +} diff --git a/Week_04/id_29/LeetCode_240_29.go b/Week_04/id_29/LeetCode_240_29.go new file mode 100644 index 00000000..2de6952a --- /dev/null +++ b/Week_04/id_29/LeetCode_240_29.go @@ -0,0 +1,31 @@ +package week4 + +func searchMatrix(matrix [][]int, target int) bool { + m := len(matrix) + if m == 0 { + return false + } + n := len(matrix[0]) + if n == 0 { + return false + } + + i, j := m-1, 0 + for 0 <= i && j < n { + if matrix[i][j] == target { + return true + } + + if matrix[i][j] < target { + j++ + // 排除了 (i,j) 上方的所有比 matrix[i][j] 小的元素 + } else { + i-- + // 排除了 (i,j) 右方的所有比 matrix[i][j] 大的元素 + } + } + // 这种方法的效率,取决于 m 与 n 的相对大小关系 + // 当 m == n 时,效率最高 + // 当 m == 1 或 n ==1 时,效率最低 + return false +} diff --git a/Week_04/id_29/LeetCode_720_29.go b/Week_04/id_29/LeetCode_720_29.go new file mode 100644 index 00000000..49ffb37e --- /dev/null +++ b/Week_04/id_29/LeetCode_720_29.go @@ -0,0 +1,24 @@ +package week4 + +import "sort" + +func longestWord(words []string) string { + sort.Strings(words) + m := make(map[string]bool, len(words)) + + res := words[0] + + for _, w := range words { + n := len(w) + if n == 1 { + m[w] = true + } else if m[w[:n-1]] { + m[w] = true + if len(res) < len(w) { + res = w + } + } + } + + return res +} diff --git a/Week_04/id_3/backtracking/LeetCode_46_3_v1.py b/Week_04/id_3/backtracking/LeetCode_46_3_v1.py new file mode 100644 index 00000000..4bda7a7b --- /dev/null +++ b/Week_04/id_3/backtracking/LeetCode_46_3_v1.py @@ -0,0 +1,31 @@ +""" +全排列 O(n^n) 似乎没啥悬念 +====== 但是我居然没通过 +两点问题 +1 递归的退出条件不能忘了return +2 set在迭代到时候要小心插入和删除,还是list复制一份更为稳妥 +""" + + +class Solution: + def permute(self, nums): + results = [] + if not nums: + return results + self.recursion([], set(nums), results) + return results + + def recursion(self, curr, num_set, results): + if len(num_set) == 0: + results.append(curr) + return + + for n in list(num_set): + num_set.remove(n) + self.recursion(curr + [n], num_set, results) + num_set.add(n) + + +s = Solution() +print(s.permute([1, 2, 3])) +print(s.permute([6, 2, -1, 8])) diff --git a/Week_04/id_3/backtracking/LeetCode_51_3.py b/Week_04/id_3/backtracking/LeetCode_51_3.py new file mode 100644 index 00000000..883945a4 --- /dev/null +++ b/Week_04/id_3/backtracking/LeetCode_51_3.py @@ -0,0 +1,45 @@ +""" +最原始回溯解决n皇后方法 +每一行判断是否可行,对角线方向用set可以简易实现 +""" + + +class Solution: + def solveNQueens(self, n): + results = [] + if n == 0: + return [] + self.recursion(n, [], [0]*n, set(), set(), results) + return results + + def recursion(self, n, curr, dis_col, dis_pie, dis_na, results): + row = len(curr) - 1 + if n == (row + 1): + results.append(curr) + return + for i in range(n): + if dis_col[i] == 1: + continue + pie = i + row + if pie in dis_pie: + continue + na = i - row + if na in dis_na: + continue + + line = ['.'] * n + line[i] = 'Q' + + dis_col[i] = 1 + dis_pie.add(pie) + dis_na.add(na) + + self.recursion(n, curr + [''.join(line)], dis_col, dis_pie, dis_na, results) + + dis_col[i] = 0 + dis_pie.remove(pie) + dis_na.remove(na) + + +s = Solution() +print(s.solveNQueens(4)) diff --git a/Week_04/id_3/backtracking/LeetCode_77_3_v1.py b/Week_04/id_3/backtracking/LeetCode_77_3_v1.py new file mode 100644 index 00000000..1589cae1 --- /dev/null +++ b/Week_04/id_3/backtracking/LeetCode_77_3_v1.py @@ -0,0 +1,25 @@ +""" +全组合 避免重复元素出现 +使用下标过滤掉已经组合过的是一个常用的技巧 +""" + + +class Solution: + def combine(self, n, k): + results = [] + if n == 0: + return results + self.recursion([], 1, n+1, k, results) + return results + + def recursion(self, curr, index, n, k, results): + if len(curr) == k: + results.append(curr) + return + + for i in range(index, n): + self.recursion(curr + [i], i + 1, n, k, results) + + +s = Solution() +print(s.combine(4, 2)) diff --git a/Week_04/id_3/backtracking/LeetCode_784_3_v1.py b/Week_04/id_3/backtracking/LeetCode_784_3_v1.py new file mode 100644 index 00000000..0ca13a4a --- /dev/null +++ b/Week_04/id_3/backtracking/LeetCode_784_3_v1.py @@ -0,0 +1,25 @@ +class Solution: + def letterCasePermutation(self, ss): + results = [] + if not ss: + return results + self.recursion(ss, 0, [], results) + return results + + def recursion(self, ss, i, curr_arr, results): + if i == len(ss): + results.append(''.join(curr_arr)) + return + + c = ss[i] + self.recursion(ss, i + 1, curr_arr + [c], results) + if c.isupper(): + self.recursion(ss, i + 1, curr_arr + [c.lower()], results) + elif c.islower(): + self.recursion(ss, i + 1, curr_arr + [c.upper()], results) + + +s = Solution() +print(s.letterCasePermutation('a1b2')) +print(s.letterCasePermutation('3z4')) +print(s.letterCasePermutation('12345')) diff --git a/Week_04/id_3/backtracking/LeetCode_784_3_v2.py b/Week_04/id_3/backtracking/LeetCode_784_3_v2.py new file mode 100644 index 00000000..3272efab --- /dev/null +++ b/Week_04/id_3/backtracking/LeetCode_784_3_v2.py @@ -0,0 +1,28 @@ +""" +尝试非递归解决 +""" + + +class Solution: + def letterCasePermutation(self, ss): + if not ss: + return [] + + results = [''] + for c in ss: + _results = [] + for r in results: + if c.islower() or c.isupper(): + _results.append(r + c.upper()) + _results.append(r + c.lower()) + else: + _results.append(r + c) + + results = _results + return results + + +s = Solution() +print(s.letterCasePermutation('a1b2')) +print(s.letterCasePermutation('3z4')) +print(s.letterCasePermutation('12345')) diff --git a/Week_04/id_3/backtracking/LeetCode_78_3_v1.py b/Week_04/id_3/backtracking/LeetCode_78_3_v1.py new file mode 100644 index 00000000..a3d47992 --- /dev/null +++ b/Week_04/id_3/backtracking/LeetCode_78_3_v1.py @@ -0,0 +1,23 @@ +""" +经典全组合 +""" + + +class Solution: + def subsets(self, nums): + results = [] + if not nums: + return results + self.recursion([], nums, results) + return results + + def recursion(self, cur, nums, results): + results.append(cur) + if not nums: + return + for i in range(len(nums)): + self.recursion(cur + [nums[i]], nums[i+1:], results) + + +s = Solution() +print(s.subsets([1, 2, 3])) diff --git a/Week_04/id_3/backtracking/LeetCode_78_3_v2.py b/Week_04/id_3/backtracking/LeetCode_78_3_v2.py new file mode 100644 index 00000000..22033acd --- /dev/null +++ b/Week_04/id_3/backtracking/LeetCode_78_3_v2.py @@ -0,0 +1,17 @@ +""" +经典全组合 直接调用库函数 其实为了点进去看看他的实现代码 +""" +import itertools + + +class Solution: + def subsets(self, nums): + results = [] + for i in range(len(nums) + 1): + for r in itertools.combinations(nums, i): + results.append(list(r)) + return results + + +s = Solution() +print(s.subsets([1, 2, 3])) diff --git a/Week_04/id_3/backtracking/LeetCode_78_3_v3.py b/Week_04/id_3/backtracking/LeetCode_78_3_v3.py new file mode 100644 index 00000000..66a426bb --- /dev/null +++ b/Week_04/id_3/backtracking/LeetCode_78_3_v3.py @@ -0,0 +1,19 @@ +""" +经典全组合 非递归 +""" +import itertools + + +class Solution: + def subsets(self, nums): + results = [[]] + for n in nums: + _results = [] + for pn in results: + _results.append(pn + [n]) + results += _results + return results + + +s = Solution() +print(s.subsets([1, 2, 3])) diff --git a/Week_04/id_3/division/LeetCode_169_3_v1.py b/Week_04/id_3/division/LeetCode_169_3_v1.py new file mode 100644 index 00000000..d4a598b6 --- /dev/null +++ b/Week_04/id_3/division/LeetCode_169_3_v1.py @@ -0,0 +1,65 @@ +""" +既然是分治专题的,那么估计用hash的玩法是没啥意义了 +看答案 分治有点儿勉强 算是学习个思路吧 +O(nlogn) + +似乎分治总会比暴力要好,只要从n^2变成nlogn,如果找不到最优的O(n),那么先用nlogn也不错。 +""" + + +class Solution: + def majorityElement(self, nums): + if not nums: + return None + # return self._division1(nums) + return self._division2(nums, 0, len(nums) - 1) + + def _division1(self, nums): + if len(nums) == 1: + return nums[0] + + mid = len(nums) // 2 + left = self._division1(nums[:mid]) + right = self._division1(nums[mid:]) + if left == right: + return left + + lc = 0 + rc = 0 + for n in nums: + if n == left: + lc += 1 + continue + if n == right: + rc += 1 + continue + return left if lc > rc else right + + def _division2(self, nums, low, high): + if low == high: + return nums[low] + + mid = low + (high-low)//2 + left = self._division2(nums, low, mid) + right = self._division2(nums, mid+1, high) + + if left == right: + return left + + lc = 0 + rc = 0 + for i in range(low, high+1): + n = nums[i] + if left == n: + lc += 1 + continue + if right == n: + rc += 1 + continue + + return left if lc > rc else right + + +s = Solution() +# print(s.majorityElement([2, 2, 1, 1, 1, 2, 2])) +print(s.majorityElement([3, 3, 4])) diff --git a/Week_04/id_3/division/LeetCode_169_3_v2.py b/Week_04/id_3/division/LeetCode_169_3_v2.py new file mode 100644 index 00000000..c4b19801 --- /dev/null +++ b/Week_04/id_3/division/LeetCode_169_3_v2.py @@ -0,0 +1,23 @@ +""" +似乎是最优解 时间O(n) 空间O(1) +投票法 +假设一个数是众数 在遍历过程中遇到该数则投票+1,不是该数则-1。 +如果票数为0,则从新开始投票,并将下一个数设为架设众数。 +因为众数多于一半,所以最终一定会耗尽其他数的票数并最终占有票数 +""" + + +class Solution: + def majorityElement(self, nums): + vote = 0 + for n in nums: + if vote == 0: + result = n + vote += 1 + continue + if result == n: + vote += 1 + else: + vote -= 1 + + return result diff --git a/Week_04/id_3/division/LeetCode_240_3_v1.py b/Week_04/id_3/division/LeetCode_240_3_v1.py new file mode 100644 index 00000000..6217b09f --- /dev/null +++ b/Week_04/id_3/division/LeetCode_240_3_v1.py @@ -0,0 +1,46 @@ +""" +一时没太想到分治咋整,先按我最朴素的思路试试。 +行列都是升序,只要分别在行列中找到小于等于目标值的下标,然后访问判断即可。 +====我想错了 还是换回分治琢磨琢磨 + +我懂了,目前的思路是,尝试把矩阵先分成2份, 先行后列,每份最大值和最小值都容易确定。然后分治并剪除不符合要求的矩阵 +""" + + +class Solution: + def searchMatrix(self, matrix, target): + if not matrix or not matrix[0]: + return False + return self.division(matrix, target) + + def division(self, matrix, target): + if not matrix or not matrix[0]: + return False + + if matrix[0][0] == target: + return True + + rows = len(matrix) + cols = len(matrix[0]) + if matrix[0][0] > target or target > matrix[rows-1][cols-1]: + return False + + if rows > 1: + index = rows//2 + return self.division(matrix[:index], target) or self.division(matrix[index:], target) + else: + index = cols//2 + return self.division([matrix[0][:index]], target) or self.division([matrix[0][index:]], target) + + +s = Solution() +matrix = [ + [1, 4, 7, 11, 15], + [2, 5, 8, 12, 19], + [3, 6, 9, 16, 22], + [10, 13, 14, 17, 24], + [18, 21, 23, 26, 30] +] + +print(s.searchMatrix(matrix, 5)) +print(s.searchMatrix(matrix, 20)) diff --git a/Week_04/id_3/division/LeetCode_53_3_v1.py b/Week_04/id_3/division/LeetCode_53_3_v1.py new file mode 100644 index 00000000..f6a64d3b --- /dev/null +++ b/Week_04/id_3/division/LeetCode_53_3_v1.py @@ -0,0 +1,29 @@ +""" +额,这题分治能做吗,我还是先按朴素的想法来一下 +暴力方法最差是O(n^3)优化是O(n^2) + +利用经典的当前累加值,减去历史最小值的方法 +例如 [1,-2,1,2,3] +当迭代i=4时,当前累加值5,历史最小值-1,所以最大值5-(-1)=6 +""" + + +class Solution: + def maxSubArray(self, nums): + if not nums: + return 0 + min_value = 0 + result = nums[0] + sum_value = 0 + + for n in nums: + sum_value += n + result = max(result, sum_value - min_value) + min_value = min(sum_value, min_value) + + return result + + +s = Solution() +print(s.maxSubArray([-2, 1, -3, 4, -1, 2, 1, -5, 4])) +print(s.maxSubArray([-1])) diff --git a/Week_04/id_3/division/LeetCode_53_3_v2.py b/Week_04/id_3/division/LeetCode_53_3_v2.py new file mode 100644 index 00000000..c34a384c --- /dev/null +++ b/Week_04/id_3/division/LeetCode_53_3_v2.py @@ -0,0 +1,80 @@ +""" +容我思考一下怎么分治 +====== +有点儿费劲啊 +====== +看了网上的一些答案,大体思路如下: +如果加入限制条件,经过下标i的最大连续子数组解决就非常容易了,只需要i向两边延伸即可找到最大值。 +控制i是中间节点,则有三种情况, +1 解包含i +2 解在i左侧 +3 解在i右侧 + +_max1方法是创建新数组 +_max2方法是玩弄下标 + +反正不管怎么整,速度都不行,勉强通过 + +时间复杂度 O(nlogn) +""" + + +class Solution: + def maxSubArray(self, nums): + if not nums: + return 0 + + # return self._max1(nums) + return self._max2(nums, 0, len(nums) - 1) + + def _max1(self, nums): + if len(nums) == 1: + return nums[0] + + if len(nums) == 2: + return max(nums[0], nums[1], sum(nums)) + + mid = len(nums) // 2 + + sum_value = 0 + left_max = 0 + for i in range(mid - 1, -1, -1): + sum_value += nums[i] + left_max = max(left_max, sum_value) + + sum_value = 0 + right_max = 0 + for i in range(mid + 1, len(nums)): + sum_value += nums[i] + right_max = max(right_max, sum_value) + + return max(nums[mid] + left_max + right_max, self._max1(nums[:mid]), self._max1(nums[mid + 1:])) + + def _max2(self, nums, left, right): + if left == right: + return nums[left] + if (left + 1) == right: + return max(nums[left], nums[right], nums[left] + nums[right]) + mid = left + (right - left) // 2 + + sum_value = 0 + left_max = 0 + for i in range(mid - 1, left-1, -1): + sum_value += nums[i] + left_max = max(left_max, sum_value) + + sum_value = 0 + right_max = 0 + for i in range(mid + 1, right+1): + sum_value += nums[i] + right_max = max(right_max, sum_value) + + return max(nums[mid] + left_max + right_max, self._max2(nums, left, mid - 1), self._max2(nums, mid + 1, right)) + + +s = Solution() +print(s.maxSubArray([-2, 1, -3, 4, -1, 2, 1, -5, 4])) +print(s.maxSubArray([-2, 3, -1, 3, -3, 2, 1, -5, 4])) +print(s.maxSubArray([-1])) +print(s.maxSubArray([-2, -1])) +print(s.maxSubArray([-2, -3, -1])) diff --git a/Week_04/id_3/division/LeetCode_53_3_v3.py b/Week_04/id_3/division/LeetCode_53_3_v3.py new file mode 100644 index 00000000..56b3e3d8 --- /dev/null +++ b/Week_04/id_3/division/LeetCode_53_3_v3.py @@ -0,0 +1,48 @@ +""" +我想到了一个诡异的方案 +假设数组nums为解,则nums大于包含它的所有父数组,和它包含的所有子数组。 +暴力解法浪费时间之处在于累加是一个浪费时间的过程,而如果数组的和,求比之长度小1位的子数组则很容易,只需要分别减去左右两边节点即可。 + +[1,2,3,4,5] sum=15 +[1,2,3,4] sum=15-5 [2,3,4,5] sum=15-1 +result=max(sum(nums), sum(nums[1:]...) + +=============================== +失败了,我真是吃饱撑的 本质上还是个O(n^2)的方案 +首次sum是n 然后减法的次数是 2+4+8+..+n 非常的尴尬 +""" + + +class Solution: + def maxSubArray(self, nums): + if not nums: + return 0 + return self._max2(nums, sum(nums), 0, len(nums) - 1) + + def _max(self, nums, sum_value): + if len(nums) == 1: + return nums[0] + if len(nums) == 2: + return max(nums[0], nums[1], nums[0] + nums[1]) + + return max(sum_value, + self._max(nums[1:], sum_value - nums[0]), + self._max(nums[:-1], sum_value - nums[-1])) + + def _max2(self, nums, sum_value, left, right): + if left == right: + return nums[left] + if len(nums) == 2: + return max(nums[left], nums[right], nums[left] + nums[right]) + + return max(sum_value, + self._max2(nums, sum_value - nums[left], left + 1, right), + self._max2(nums, sum_value - nums[right], left, right - 1)) + + +s = Solution() +print(s.maxSubArray([-2, 1, -3, 4, -1, 2, 1, -5, 4])) +print(s.maxSubArray([-2, 3, -1, 3, -3, 2, 1, -5, 4])) +print(s.maxSubArray([-1])) +print(s.maxSubArray([-2, -1])) +print(s.maxSubArray([-2, -3, -1])) diff --git a/Week_04/id_3/dp/LeetCode_120_3_v1.py b/Week_04/id_3/dp/LeetCode_120_3_v1.py new file mode 100644 index 00000000..53b5cfb2 --- /dev/null +++ b/Week_04/id_3/dp/LeetCode_120_3_v1.py @@ -0,0 +1,49 @@ +""" +给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。 + +例如,给定三角形: + +[ + [2], + [3,4], + [6,5,7], + [4,1,8,3] +] +自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。 + +说明: + +如果你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题,那么你的算法会很加分。 +================================ +递归+缓存 +""" + + +class Solution: + def minimumTotal(self, triangle) -> int: + if not triangle: + return 0 + + def rec(level, idx, triangle, cache): + v = triangle[level][idx] + if level == len(triangle) - 1: + return v + + if cache[level][idx] is None: + cache[level][idx] = v + min( + rec(level + 1, idx, triangle, cache), + rec(level + 1, idx + 1, triangle, cache) + ) + + return cache[level][idx] + + return rec(0, 0, triangle, [[None] * len(triangle[row]) for row in range(len(triangle) - 1)]) + + +s = Solution() +print(s.minimumTotal([ + [2], + [3, 4], + [6, 5, 7], + [4, 1, 8, 3] +]) == 11) diff --git a/Week_04/id_3/dp/LeetCode_120_3_v2.py b/Week_04/id_3/dp/LeetCode_120_3_v2.py new file mode 100644 index 00000000..a87c90b5 --- /dev/null +++ b/Week_04/id_3/dp/LeetCode_120_3_v2.py @@ -0,0 +1,43 @@ +""" +给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。 + +例如,给定三角形: + +[ + [2], + [3,4], + [6,5,7], + [4,1,8,3] +] +自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。 + +说明: + +如果你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题,那么你的算法会很加分。 +================================ +DP +""" + + +class Solution: + def minimumTotal(self, triangle) -> int: + if not triangle: + return 0 + + for level in range(len(triangle)-2, -1, -1): + current = triangle[level] + downstairs = triangle[level + 1] + for idx in range(len(current)): + current[idx] += min(downstairs[idx], downstairs[idx+1]) + + return triangle[0][0] + + +s = Solution() +print(s.minimumTotal([ + [2], + [3, 4], + [6, 5, 7], + [4, 1, 8, 3] +]) == 11) + diff --git a/Week_04/id_3/dp/LeetCode_188_3_v1.py b/Week_04/id_3/dp/LeetCode_188_3_v1.py new file mode 100644 index 00000000..d7b33956 --- /dev/null +++ b/Week_04/id_3/dp/LeetCode_188_3_v1.py @@ -0,0 +1,100 @@ +""" +给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。 + +设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。 + +注意: 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 + +示例 1: + +输入: [2,4,1], k = 2 +输出: 2 +解释: 在第 1 天 (股票价格 = 2) 的时候买入,在第 2 天 (股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2 。 +示例 2: + +输入: [3,2,6,5,0,3], k = 2 +输出: 7 +解释: 在第 2 天 (股票价格 = 2) 的时候买入,在第 3 天 (股票价格 = 6) 的时候卖出, 这笔交易所能获得利润 = 6-2 = 4 。 +  随后,在第 5 天 (股票价格 = 0) 的时候买入,在第 6 天 (股票价格 = 3) 的时候卖出, 这笔交易所能获得利润 = 3-0 = 3 。 + +============================= +这个题依然是经典DP 状态编程了 天/操作状态/剩余次数 +状态 0无操作 1买入 2卖出 +先用递归暴力实现 +============================= +这回缓存空间变大了不少 引入了k +汗,这东西没有冻结期 状态也只需要两个 0 1 +============================= +如果把k纳入状态空间,那么有点儿太大了 +目前的思路是用dict存储 +============================= 可惜超时了 +现在代码已经有点乱了 +尝试在查询缓存后做一些剪枝操作 如果明显目前操作次数已经多于缓存,但是当前值又很少就可以剪掉了。 +============================= 依然超时 +只能对明显k太大的部分做特殊处理了 +""" + + +class Solution: + def maxProfit(self, k: int, prices) -> int: + if not k or not prices: + return 0 + if k >= len(prices)//2: + return self.simplify(0, 0, prices, [[None, None] for _ in range(len(prices))]) + return self.recursion(k, 0, 0, 0, prices, [[{}, {}] for _ in range(len(prices))]) + + def simplify(self, idx, status, prices, cache): + if idx >= len(prices): + return 0 + if cache[idx][status] is not None: + return cache[idx][status] + next_idx = idx + 1 + if status == 0: + r = max( + self.simplify(next_idx, 0, prices, cache), + self.simplify(next_idx, 1, prices, cache) + ) + else: + r = prices[idx] - prices[idx-1] + max( + self.simplify(next_idx, 0, prices, cache), + self.simplify(next_idx, 1, prices, cache) + ) + cache[idx][status] = r + return r + + def recursion(self, k, curr, idx, status, prices, cache): + if idx >= len(prices) or k == -1: + return 0 + tc = cache[idx][status] + + if k in tc: + return tc[k][0] + + for tk in tc.keys(): + arr = tc[tk] + if k < tk and curr <= arr[1]: + return 0 + + next_idx = idx + 1 + if status == 0: + r = max( + self.recursion(k, curr, next_idx, 0, prices, cache), + self.recursion(k - 1, curr, next_idx, 1, prices, cache) + ) + else: + d = prices[idx] - prices[idx - 1] + next_curr = curr + d + r = d + max( + self.recursion(k, next_curr, next_idx, 0, prices, cache), + self.recursion(k, next_curr, next_idx, 1, prices, cache), + ) + tc[k] = (r, curr) + return r + + +s = Solution() +print(s.maxProfit(2, [2, 1, 2, 0, 1])) +print(s.maxProfit(2, [2, 4, 1])) +print(s.maxProfit(2, [1, 4, 2, 7])) +print(s.maxProfit(2, [3, 2, 6, 5, 0, 3])) +print(s.maxProfit(2, [3, 3, 5, 0, 0, 3, 1, 4])) diff --git a/Week_04/id_3/dp/LeetCode_188_3_v2.py b/Week_04/id_3/dp/LeetCode_188_3_v2.py new file mode 100644 index 00000000..f72ce0fd --- /dev/null +++ b/Week_04/id_3/dp/LeetCode_188_3_v2.py @@ -0,0 +1,72 @@ +""" +给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。 + +设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。 + +注意: 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 + +示例 1: + +输入: [2,4,1], k = 2 +输出: 2 +解释: 在第 1 天 (股票价格 = 2) 的时候买入,在第 2 天 (股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2 。 +示例 2: + +输入: [3,2,6,5,0,3], k = 2 +输出: 7 +解释: 在第 2 天 (股票价格 = 2) 的时候买入,在第 3 天 (股票价格 = 6) 的时候卖出, 这笔交易所能获得利润 = 6-2 = 4 。 +  随后,在第 5 天 (股票价格 = 0) 的时候买入,在第 6 天 (股票价格 = 3) 的时候卖出, 这笔交易所能获得利润 = 3-0 = 3 。 + +============================= +试试DP方式 +日期/操作状态/k 三个状态 O(n*k) +============================= +勉强通过 只打败 50% 而且没办法优雅的解决k巨大的时候 只能两种解法 +""" + + +class Solution: + def maxProfit(self, k: int, prices) -> int: + if not k or not prices: + return 0 + + if k >= len(prices)//2: + r = 0 + for idx in range(1, len(prices)): + d = prices[idx] - prices[idx - 1] + r = max(r, r + d) + return r + + cache = [[0, 0], [0, 0], [0, 0]] + for idx in range(1, len(prices)): + max_k = min(idx//2 + 1, k) + 1 + new_cache = [[0] * (k+1), [0] * (k+1), [0] * (k+1)] + d = prices[idx] - prices[idx-1] + for i in range(1, max_k): + # 无操作 + new_cache[0][i] = (max( + cache[0][i], + cache[2][i], + )) + + # 买入 + new_cache[1][i] = (max( + cache[0][i - 1], + cache[1][i] + d, + cache[2][i - 1], + )) + + # 卖出 + new_cache[2][i] = max(cache[1][i] + d, 0) + + cache = new_cache + + return max(cache[0] + cache[1] + cache[2]) + + +s = Solution() +print(s.maxProfit(2, [2, 1, 2, 0, 1])) +print(s.maxProfit(2, [2, 4, 1])) +print(s.maxProfit(2, [1, 4, 2, 7])) +print(s.maxProfit(2, [3, 2, 6, 5, 0, 3])) +print(s.maxProfit(2, [3, 3, 5, 0, 0, 3, 1, 4])) diff --git a/Week_04/id_3/dp/LeetCode_188_3_v3.py b/Week_04/id_3/dp/LeetCode_188_3_v3.py new file mode 100644 index 00000000..cd81b442 --- /dev/null +++ b/Week_04/id_3/dp/LeetCode_188_3_v3.py @@ -0,0 +1,73 @@ +""" +给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。 + +设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。 + +注意: 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 + +示例 1: + +输入: [2,4,1], k = 2 +输出: 2 +解释: 在第 1 天 (股票价格 = 2) 的时候买入,在第 2 天 (股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2 。 +示例 2: + +输入: [3,2,6,5,0,3], k = 2 +输出: 7 +解释: 在第 2 天 (股票价格 = 2) 的时候买入,在第 3 天 (股票价格 = 6) 的时候卖出, 这笔交易所能获得利润 = 6-2 = 4 。 +  随后,在第 5 天 (股票价格 = 0) 的时候买入,在第 6 天 (股票价格 = 3) 的时候卖出, 这笔交易所能获得利润 = 3-0 = 3 。 + +============================= +试试找波峰波谷的方式 +============================= +这么做是不行的,如果是不限次数,那么没有问题,如果限制次数,这种方式就无法使用了。 +1,2,4,2,9 如果只能交易一次,那么1-9是最优解。如果可以交易2次,那么1-4,2-9是最优解。 +只能用于k>len(prices)//2的情况 而且用小顶堆优化也还没有dp的解法快 +============================= +失败!! +""" +import heapq + + +class Solution: + def maxProfit(self, k: int, prices) -> int: + if not k or not prices: + return 0 + + last = prices[0] + status = 0 + last_min = None + heap = [] + for price in prices: + if last == price: + continue + if price > last: + if status != 1: + last_min = last + status = 1 + else: + if status != -1: + if last_min is not None: + self.push(heap, k, last - last_min) + status = -1 + + last = price + if status == 1: + self.push(heap, k, last - last_min) + + return sum(sorted(heap[-k:])) + + def push(self, heap, k, value): + if len(heap) >= k: + heapq.heapreplace(heap, value) + else: + heapq.heappush(heap, value) + + +s = Solution() +# print(s.maxProfit(2, [2, 1, 2, 0, 1])) +# print(s.maxProfit(2, [2, 4, 1])) +# print(s.maxProfit(2, [1, 4, 2, 7])) +# print(s.maxProfit(2, [3, 2, 6, 5, 0, 3])) +# print(s.maxProfit(2, [3, 3, 5, 0, 0, 3, 1, 4])) +# print(s.maxProfit(2, [1, 2, 4, 2, 5, 7, 2, 4, 9, 0])) diff --git a/Week_04/id_3/dp/LeetCode_188_3_v4.py b/Week_04/id_3/dp/LeetCode_188_3_v4.py new file mode 100644 index 00000000..315d0801 --- /dev/null +++ b/Week_04/id_3/dp/LeetCode_188_3_v4.py @@ -0,0 +1,8 @@ +""" +反复练习版本 +""" + + +class Solution: + def maxProfit(self, k: int, prices) -> int: + pass diff --git a/Week_04/id_3/dp/LeetCode_198_3_v1.py b/Week_04/id_3/dp/LeetCode_198_3_v1.py new file mode 100644 index 00000000..df7b2a54 --- /dev/null +++ b/Week_04/id_3/dp/LeetCode_198_3_v1.py @@ -0,0 +1,31 @@ +""" +第一直观的解法还是dfs,先试试 +=============== +超时了 要加上缓存 +=============== +超过97.8% +""" + + +class Solution: + def rob(self, nums): + if not nums: + return 0 + return self.dfs(False, 0, nums, [None]*len(nums)) + + def dfs(self, prev_steal, index, nums, cache): + if index >= len(nums): + return 0 + + if not cache[index]: + r1 = self.dfs(False, index+1, nums, cache) + r2 = nums[index] + self.dfs(True, index+1, nums, cache) + cache[index] = (r1, max(r1, r2)) + + results = cache[index] + return results[0] if prev_steal else results[1] + + +s = Solution() +print(s.rob([1, 2, 3, 1]), s.rob([1, 2, 3, 1]) == 4) +print(s.rob([2, 7, 9, 3, 1]), s.rob([2, 7, 9, 3, 1]) == 12) diff --git a/Week_04/id_3/dp/LeetCode_198_3_v2.py b/Week_04/id_3/dp/LeetCode_198_3_v2.py new file mode 100644 index 00000000..88f01930 --- /dev/null +++ b/Week_04/id_3/dp/LeetCode_198_3_v2.py @@ -0,0 +1,40 @@ +""" +使用非递归方式解决 +======= +套路 递归+缓存 可以解决的问题,容易直接推出递推公式 + +递归的思路一般是从大到小,n问题依赖n-1问题的解决(也有例外) + +递推是从底部开始推导最优解 自底向上 将原来缓存中的值计算出来 + +======= +本题的解法就 n下标 的最优解是 nums[n] + cache[n-2] 与 cache[n-1] 之间的比较 +""" + + +class Solution: + def rob(self, nums): + if not nums: + return 0 + + length = len(nums) + if length == 1: + return nums[0] + + cache = [nums[0], max(nums[0], nums[1])] + index = 2 + while index < length: + cache.append( + max( + nums[index] + cache[index - 2], + cache[index - 1] + ) + ) + index += 1 + + return cache[index - 1] + + +s = Solution() +print(s.rob([1, 2, 3, 1]), s.rob([1, 2, 3, 1]) == 4) +print(s.rob([2, 7, 9, 3, 1]), s.rob([2, 7, 9, 3, 1]) == 12) diff --git a/Week_04/id_3/dp/LeetCode_213_3_v1.py b/Week_04/id_3/dp/LeetCode_213_3_v1.py new file mode 100644 index 00000000..b05e7867 --- /dev/null +++ b/Week_04/id_3/dp/LeetCode_213_3_v1.py @@ -0,0 +1,38 @@ +""" +先按自己的方法试试 +回溯 + 2状态缓存 第一家偷不偷 本家偷不偷 +""" + + +class Solution: + def rob(self, nums) -> int: + if not nums: + return 0 + if len(nums) == 1: + return nums[0] + return self.rec(0, 0, 0, nums, [[None, None] for _ in range(len(nums)-1)]) + + def rec(self, idx, prev, first, nums, cache): + if idx == len(nums) - 1: + return nums[idx] if not prev and not first else 0 + + next_x = idx + 1 + if idx == 0: + return max( + self.rec(next_x, 0, 0, nums, cache), + nums[0] + self.rec(next_x, 1, 1, nums, cache) + ) + + if not cache[idx][first]: + r1 = self.rec(next_x, 0, first, nums, cache) + r2 = nums[idx] + self.rec(next_x, 1, first, nums, cache) + cache[idx][first] = [r1, r2] + + r1, r2 = cache[idx][first] + return r1 if prev == 1 else max(r1, r2) + + +s = Solution() +# print(s.rob([2, 3, 2]) == 3) +# print(s.rob([1, 2, 3, 2]) == 4) +print(s.rob([1, 2, 3, 1]) == 4) diff --git a/Week_04/id_3/dp/LeetCode_213_3_v2.py b/Week_04/id_3/dp/LeetCode_213_3_v2.py new file mode 100644 index 00000000..60896bc7 --- /dev/null +++ b/Week_04/id_3/dp/LeetCode_213_3_v2.py @@ -0,0 +1,35 @@ +""" +DP思路 缓存依然是两个状态 首家偷不偷 本家偷不偷 +cache = [首不偷本不偷, 首不偷本偷, 首偷本不偷, 首偷本偷] +在初始状态和最后结果状态容易下标判断错误 +""" + + +class Solution: + def rob(self, nums) -> int: + if not nums: + return 0 + if len(nums) == 1: + return nums[0] + if len(nums) == 2: + return max(nums) + + # 初始状态从下标2开始比较容易实现 + cache = [0, nums[1], nums[0], nums[0]] + for i in range(2, len(nums) - 1): + v = nums[i] + cache = [ + max(cache[0], cache[1]), + v + cache[0], + max(cache[2], cache[3]), + v + cache[2], + ] + + last = nums[len(nums) - 1] + return max(last + cache[0], cache[1], cache[2], cache[3]) + + +s = Solution() +print(s.rob([2, 3, 2]) == 3) +print(s.rob([1, 2, 3, 2]) == 4) +print(s.rob([1, 2, 3, 1]) == 4) diff --git a/Week_04/id_3/dp/LeetCode_309_3_v1.py b/Week_04/id_3/dp/LeetCode_309_3_v1.py new file mode 100644 index 00000000..367e2186 --- /dev/null +++ b/Week_04/id_3/dp/LeetCode_309_3_v1.py @@ -0,0 +1,59 @@ +""" +给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。​ + +设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票): + +你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 +卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。 +示例: + +输入: [1,2,3,0,2] +输出: 3 +解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出] + +======================= +DP还是不熟,需要可以练习,先从暴力解法开始。 +status 0不操作 1买 2卖 +在recursion三个参数 下标 上一次的状态 数据 +三种状态三种不同的下钻方式 +技巧在于买入不卖的等待状态相当于每次的累加 每一步的状态都可以计算 便于缓存 +price[5]-price[2] = (prices[3]-price[2])+(prices[4]-price[3])... +======================= +加入缓存 参数其实就是状态 当前下标配合当前状态构成了一个缓存 +注意 二维数组初始化不可以这么写 [[0,0,0]]*n 这样所有数组的子元素都引用的同一个二级数组 [0,0,0] + +完美,一条过 打败93% +""" + + +class Solution: + def maxProfit(self, prices) -> int: + if not prices: + return 0 + return self.recursion(0, 0, prices, [[None, None, None] for _ in range(len(prices))]) + + def recursion(self, idx, status, prices, cache): + if idx >= len(prices): + return 0 + if cache[idx][status] is not None: + return cache[idx][status] + if status == 0: + r = max( + self.recursion(idx+1, 0, prices, cache), + self.recursion(idx+1, 1, prices, cache) + ) + elif status == 1: + r = (prices[idx] - prices[idx-1]) + max( + self.recursion(idx+1, 1, prices, cache), + self.recursion(idx+1, 2, prices, cache), + ) + elif status == 2: + r = self.recursion(idx+1, 0, prices, cache) + cache[idx][status] = r + return r + + +s = Solution() +print(s.maxProfit([1, 2, 3, 0, 2, 4, 5, 7, 8]) == 9) +print(s.maxProfit([1, 2, 3, 0, 2]) == 3) +print(s.maxProfit([1, 2, 3, -2, 5, 0, 2]) == 8) diff --git a/Week_04/id_3/dp/LeetCode_309_3_v2.py b/Week_04/id_3/dp/LeetCode_309_3_v2.py new file mode 100644 index 00000000..6bead42f --- /dev/null +++ b/Week_04/id_3/dp/LeetCode_309_3_v2.py @@ -0,0 +1,63 @@ +""" +给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。​ + +设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票): + +你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 +卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。 +示例: + +输入: [1,2,3,0,2] +输出: 3 +解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出] + +======================= +尝试dp递推 +按套路是写出来了,但是真的好难按正常思路去理解。 +尝试理解一下 + +所谓的自底向上还是很难理解,还是顺序写dp比较容易理解 +当前如果是空仓 则最大值是 之前空仓或者卖出的最大值 +如果是买入状态 则最大值是 之前空仓或者买入状态+差值的最大值 +如果是卖出操作 则最大值是 之前是买入状态的最大值 +====================== +优化缓存数组,减少内存使用。目前这种n只依赖n-1的dp,没必要记录全量。 +内存占用打败 98.84% +====================== +还得多练练 +""" + + +class Solution: + def maxProfit(self, prices) -> int: + if not prices: + return 0 + return self.dp2(prices) + + def dp1(self, prices): + cache = (0, 0, 0) + for idx in range(len(prices) - 1, 0, -1): + d = prices[idx] - prices[idx - 1] + cache = ( + max(cache[0], cache[1]), + max(cache[1], cache[2]) + d, + cache[0], + ) + return max(cache[0], cache[1]) + + def dp2(self, prices): + cache = (0, 0, 0) + for idx in range(1, len(prices)): + d = prices[idx] - prices[idx - 1] + cache = ( + max(cache[0], cache[2]), + max(cache[0], cache[1] + d), + cache[1] + d + ) + return max(cache) + + +s = Solution() +print(s.maxProfit([1, 2, 3, 0, 2, 4, 5, 7, 8]), s.maxProfit([1, 2, 3, 0, 2, 4, 5, 7, 8]) == 9) +print(s.maxProfit([1, 2, 3, 0, 2]), s.maxProfit([1, 2, 3, 0, 2]) == 3) +print(s.maxProfit([1, 2, 3, -2, 5, 0, 2]), s.maxProfit([1, 2, 3, -2, 5, 0, 2]) == 8) diff --git a/Week_04/id_3/dp/LeetCode_322_3_v1.py b/Week_04/id_3/dp/LeetCode_322_3_v1.py new file mode 100644 index 00000000..8168ba30 --- /dev/null +++ b/Week_04/id_3/dp/LeetCode_322_3_v1.py @@ -0,0 +1,31 @@ +class Solution: + def coinChange(self, coins, amount: int) -> int: + if not coins: + return -1 + + return self.dfs(coins, amount, [None] * (amount+1)) + + def dfs(self, coins, amount, cache): + if amount == 0: + return 0 + + if amount < 0: + return -1 + + if cache[amount] is None: + result = -1 + for c in coins: + r = self.dfs(coins, amount - c, cache) + if r == -1: + continue + r += 1 + result = r if result == -1 else min(result, r) + + cache[amount] = result + + return cache[amount] + + +s = Solution() +print(s.coinChange([1, 2, 5], 11) == 3) +print(s.coinChange([186, 419, 83, 408], 6249)) diff --git a/Week_04/id_3/dp/LeetCode_337_3_v1.py b/Week_04/id_3/dp/LeetCode_337_3_v1.py new file mode 100644 index 00000000..879c740c --- /dev/null +++ b/Week_04/id_3/dp/LeetCode_337_3_v1.py @@ -0,0 +1,58 @@ +""" +在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。 + +计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。 + +示例 1: + +输入: [3,2,3,null,3,null,1] + + 3 + / \ + 2 3 + \ \ + 3 1 + +输出: 7 +解释: 小偷一晚能够盗取的最高金额 = 3 + 3 + 1 = 7. +示例 2: + +输入: [3,4,5,1,3,null,1] + +  3 + / \ + 4 5 + / \ \ + 1 3 1 + +输出: 9 +解释: 小偷一晚能够盗取的最高金额 = 4 + 5 = 9. + +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +依然先用传统的回溯+缓存 +""" + + +class Solution: + def rob(self, root) -> int: + if not root: + return 0 + return self.rec(root, False, {}) + + def rec(self, node, prev, cache): + if not node: + return 0 + _id = id(node) + if _id not in cache: + r1 = self.rec(node.left, False, cache) + self.rec(node.right, False, cache) + r2 = node.val + self.rec(node.left, True, cache) + self.rec(node.right, True, cache) + cache[_id] = (r1, r2) + + r1, r2 = cache[_id] + return r1 if prev else max(r1, r2) diff --git a/Week_04/id_3/dp/LeetCode_337_3_v2.py b/Week_04/id_3/dp/LeetCode_337_3_v2.py new file mode 100644 index 00000000..cf776f25 --- /dev/null +++ b/Week_04/id_3/dp/LeetCode_337_3_v2.py @@ -0,0 +1,27 @@ +""" +DP的思路目前是广度优先策略用dict缓存父级的递归结果 +不过卡住了,自从向叶的dp似乎最终很难汇集一个结果,得试试自叶向根了。 +==================== +看了各路答案,思路本题很难用递推处理 失败 +""" + + +class Solution: + def rob(self, root) -> int: + if not root: + return 0 + + cache = {id(root): (0, 0)} + queue = [root] + + result = 0 + while queue: + _queue = [] + _cache = {} + for node in queue: + p1, p2 = cache[id(node)] + r = (max(p1, p2), p1 + node.val) + if not node.left and not node.right: + pass + + return result diff --git a/Week_04/id_3/dp/LeetCode_337_3_v3.py b/Week_04/id_3/dp/LeetCode_337_3_v3.py new file mode 100644 index 00000000..022b270f --- /dev/null +++ b/Week_04/id_3/dp/LeetCode_337_3_v3.py @@ -0,0 +1,22 @@ +""" +有点儿类似用递归模拟递推 +没必要使用回溯+缓存 直接递归下钻即可拿到子节点的类似递推的结果 +算是深度优先+递推 非常简单高效 +击败接近100% +""" + + +class Solution: + def rob(self, root) -> int: + if not root: + return 0 + return max(self.dfs(root)) + + def dfs(self, node): + if not node: + return 0, 0 + + l1, l2 = self.dfs(node.left) + r1, r2 = self.dfs(node.right) + + return max(l1 + r1, l2 + r1, l1 + r2, l2 + r2), node.val + l1 + r1 diff --git a/Week_04/id_3/dp/LeetCode_62_3_v1.py b/Week_04/id_3/dp/LeetCode_62_3_v1.py new file mode 100644 index 00000000..8ea8ca76 --- /dev/null +++ b/Week_04/id_3/dp/LeetCode_62_3_v1.py @@ -0,0 +1,50 @@ +""" +一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。 + +机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。 + +问总共有多少条不同的路径? + +例如,上图是一个7 x 3 的网格。有多少可能的路径? + +说明:m 和 n 的值均不超过 100。 + +示例 1: + +输入: m = 3, n = 2 +输出: 3 +解释: +从左上角开始,总共有 3 条路径可以到达右下角。 +1. 向右 -> 向右 -> 向下 +2. 向右 -> 向下 -> 向右 +3. 向下 -> 向右 -> 向右 +示例 2: + +输入: m = 7, n = 3 +输出: 28 +=========================== +老套路先试试回溯+缓存 +优化 碰触到右或者下的边可直接返回1 +缓存为m*n数组,mn启点 00终点,这样变量能少传两个。 +""" + + +class Solution: + def uniquePaths(self, m: int, n: int) -> int: + if not m or not n: + return 0 + return self.rec(m-1, n-1, [[None for _ in range(n)] for _ in range(m)]) + + def rec(self, m, n, cache): + if not m or not n: + return 1 + + if cache[m][n] is None: + cache[m][n] = self.rec(m-1, n, cache) + self.rec(m, n-1, cache) + + return cache[m][n] + + +s = Solution() +print(s.uniquePaths(3, 2) == 3) +print(s.uniquePaths(7, 3) == 28) diff --git a/Week_04/id_3/dp/LeetCode_62_3_v2.py b/Week_04/id_3/dp/LeetCode_62_3_v2.py new file mode 100644 index 00000000..8f2e83f5 --- /dev/null +++ b/Week_04/id_3/dp/LeetCode_62_3_v2.py @@ -0,0 +1,26 @@ +""" +老套路 DP递推 自底向上 +00默认是终点递推比较容易 +""" + + +class Solution: + def uniquePaths(self, m: int, n: int) -> int: + if not m or not n: + return 0 + + cache = [1] * n + for _m in range(1, m): + _cache = [1] * n + for _n in range(1, n): + _cache[_n] = _cache[_n-1] + cache[_n] + + cache = _cache + + return cache[n - 1] + + +s = Solution() +print(s.uniquePaths(3, 2) == 3) +print(s.uniquePaths(7, 3) == 28) +print(s.uniquePaths(3, 7) == 28) diff --git a/Week_04/id_3/dp/LeetCode_63_3_v1.py b/Week_04/id_3/dp/LeetCode_63_3_v1.py new file mode 100644 index 00000000..bf433bf4 --- /dev/null +++ b/Week_04/id_3/dp/LeetCode_63_3_v1.py @@ -0,0 +1,49 @@ +""" +一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。 + +机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。 + +现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径? + +=================================== +老套路 先递归 +直接用初始化数组当缓存 +用None取代本来是结果0的点位 避免重复计算 -1取代障碍物点位 +""" + + +class Solution: + def uniquePathsWithObstacles(self, obstacleGrid) -> int: + if not obstacleGrid or not obstacleGrid[0]: + return 0 + + for m in range(len(obstacleGrid)): + for n in range(len(obstacleGrid[0])): + obstacleGrid[m][n] = None if obstacleGrid[m][n] == 0 else -1 + + return self.rec(0, 0, len(obstacleGrid)-1, len(obstacleGrid[0])-1, obstacleGrid) + + def rec(self, m, n, m_max, n_max, grid): + if m > m_max or n > n_max: + return 0 + + if grid[m][n] == -1: + return 0 + + if m == m_max and n == n_max: + return 1 + + if grid[m][n] is None: + grid[m][n] = self.rec(m+1, n, m_max, n_max, grid) + self.rec(m, n+1, m_max, n_max, grid) + + return grid[m][n] + + +s = Solution() +print(s.uniquePathsWithObstacles([ + [0, 0, 0], + [0, 1, 0], + [0, 0, 0] +])) +print(s.uniquePathsWithObstacles([[1, 0]])) +print(s.uniquePathsWithObstacles([[0, 1]])) diff --git a/Week_04/id_3/dp/LeetCode_63_3_v2.py b/Week_04/id_3/dp/LeetCode_63_3_v2.py new file mode 100644 index 00000000..e3758a7f --- /dev/null +++ b/Week_04/id_3/dp/LeetCode_63_3_v2.py @@ -0,0 +1,36 @@ +""" +尝试DP +""" + + +class Solution: + def uniquePathsWithObstacles(self, grid) -> int: + if not grid or not grid[0]: + return 0 + + for m in range(len(grid)): + for n in range(len(grid[0])): + if grid[m][n] == 1: + grid[m][n] = 0 + continue + + if m == 0 and n == 0: + grid[m][n] = 1 + continue + + if n > 0: + grid[m][n] += grid[m][n-1] + if m > 0: + grid[m][n] += grid[m-1][n] + + return grid[m][n] + + +s = Solution() +print(s.uniquePathsWithObstacles([ + [0, 0, 0], + [0, 1, 0], + [0, 0, 0] +])) +print(s.uniquePathsWithObstacles([[1, 0]])) +print(s.uniquePathsWithObstacles([[0, 1]])) diff --git a/Week_04/id_3/dp/LeetCode_70_3_v1.py b/Week_04/id_3/dp/LeetCode_70_3_v1.py new file mode 100644 index 00000000..efb3ea09 --- /dev/null +++ b/Week_04/id_3/dp/LeetCode_70_3_v1.py @@ -0,0 +1,35 @@ +""" +先用第一印象的数学公式解决 +====== +想到的不行 本质是个n^n 的解决方案 +====== +试试递归+缓存的玩法 +""" +import math + + +class Solution: + def climbStairs(self, n: int) -> int: + if not n: + return 0 + return self.stair(n, [0] * (n+1)) + + def stair(self, n, cache): + if n == 0: + return 0 + if n == 1: + return 1 + if n == 2: + return 2 + + if cache[n]: + return cache[n] + + r = self.stair(n-1, cache) + self.stair(n-2, cache) + cache[n] = r + return r + + +s = Solution() +# print(s.climbStairs(3)) +print(s.climbStairs(4)) diff --git a/Week_04/id_3/dp/LeetCode_70_3_v2.py b/Week_04/id_3/dp/LeetCode_70_3_v2.py new file mode 100644 index 00000000..8adc4f8f --- /dev/null +++ b/Week_04/id_3/dp/LeetCode_70_3_v2.py @@ -0,0 +1,22 @@ +""" +递推比较直观 n = cache[n-1]+cache[n-2] +""" + + +class Solution: + def climbStairs(self, n: int) -> int: + if not n: + return 0 + + cache = [1, 1] + index = 2 + while index <= n: + cache.append(cache[index - 1] + cache[index - 2]) + index += 1 + + return cache[n] + + +s = Solution() +print(s.climbStairs(4)) +print(s.climbStairs(10)) diff --git a/Week_04/id_3/greed/LeetCode_455_3_v1.py b/Week_04/id_3/greed/LeetCode_455_3_v1.py new file mode 100644 index 00000000..6adce50f --- /dev/null +++ b/Week_04/id_3/greed/LeetCode_455_3_v1.py @@ -0,0 +1,30 @@ +""" +直接贪心好了,最大的饼干找胃口最大的孩子 +""" + + +class Solution: + def findContentChildren(self, g, s) -> int: + if not g or not s: + return 0 + + s.sort() + g.sort() + + gi = len(g) + r = 0 + for si in range(len(s) - 1, - 1, -1): + sv = s[si] + for gi in range(gi - 1, -1, -1): + gv = g[gi] + if gv <= sv: + r += 1 + break + + return r + + +s = Solution() +print(s.findContentChildren([1, 2, 3], [1, 1])) +print(s.findContentChildren([1, 2], [1, 2, 3])) +print(s.findContentChildren([10, 9, 8, 7], [5, 6, 7, 8])) diff --git a/Week_04/id_3/trie/LeetCode_208_3.py b/Week_04/id_3/trie/LeetCode_208_3.py new file mode 100644 index 00000000..3cb44147 --- /dev/null +++ b/Week_04/id_3/trie/LeetCode_208_3.py @@ -0,0 +1,57 @@ +class Trie: + + def __init__(self): + self.root = TrieNode() + + def insert(self, word: str) -> None: + node = self.root + for c in word: + if c not in node.edges: + node.edges[c] = TrieNode() + node.letter = c + node = node.edges[c] + node.is_word = True + + def search(self, word: str) -> bool: + if not word: + return False + node = self.root + for c in word: + if c in node.edges: + node = node.edges[c] + else: + return False + + return node.is_word + + def startsWith(self, prefix: str) -> bool: + if not prefix: + return False + node = self.root + for c in prefix: + if c in node.edges: + node = node.edges[c] + else: + return False + + return True + + +class TrieNode: + + def __init__(self): + self.edges = {} + self.letter = None + self.is_word = False + + +trie = Trie() + +trie.insert("apple") +print(trie.search("apple")) +print(trie.search("app")) +print(trie.startsWith("app")) +trie.insert("app") +print(trie.search("app")) + + diff --git a/Week_04/id_3/trie/LeetCode_211_3.py b/Week_04/id_3/trie/LeetCode_211_3.py new file mode 100644 index 00000000..3bd9e154 --- /dev/null +++ b/Week_04/id_3/trie/LeetCode_211_3.py @@ -0,0 +1,53 @@ +class WordDictionary: + + def __init__(self): + self.root = TrieNode() + + def addWord(self, word: str) -> None: + node = self.root + for c in word: + if c not in node.edges: + node.edges[c] = TrieNode() + node.letter = c + node = node.edges[c] + node.is_word = True + + def search(self, word: str) -> bool: + if not word: + return False + return self._dfs(self.root, word) + + def _dfs(self, node, word): + for i in range(len(word)): + c = word[i] + + if c == '.': + for sn in node.edges.values(): + if self._dfs(sn, word[i+1:]): + return True + return False + + if c in node.edges: + node = node.edges[c] + else: + return False + + return node.is_word + + +class TrieNode: + + def __init__(self): + self.edges = {} + self.letter = None + self.is_word = False + + +trie = WordDictionary() +trie.addWord("bad") +trie.addWord("dad") +trie.addWord("mad") +print(trie.search('pad')) +print(trie.search('bad')) +print(trie.search('.ad')) +print(trie.search('b..')) diff --git a/Week_04/id_3/trie/LeetCode_720_3_v1.py b/Week_04/id_3/trie/LeetCode_720_3_v1.py new file mode 100644 index 00000000..583a780f --- /dev/null +++ b/Week_04/id_3/trie/LeetCode_720_3_v1.py @@ -0,0 +1,56 @@ +import collections + + +class TrieTree: + + def __init__(self): + self.root = TrieNode() + + def add(self, word): + node = self.root + for w in word: + node = node.edges[w] + node.letter = w + node.is_word = True + + +class TrieNode: + + def __init__(self): + self.edges = collections.defaultdict(TrieNode) + self.letter = None + self.is_word = False + + +class Solution: + def longestWord(self, words): + if not words: + return '' + + tree = TrieTree() + for word in words: + if word == '': + continue + tree.add(word) + + self.result = [] + self.dfs(tree.root, []) + return ''.join(self.result) + + def dfs(self, node, curr): + curr.append(node.letter) + if (len(curr) - 1) > len(self.result): + self.result[:] = curr[1:] + + for key in sorted(node.edges.keys()): + sn = node.edges[key] + if sn.is_word: + self.dfs(sn, curr) + + curr.pop() + + +s = Solution() +# print(s.longestWord(["w", "wo", "wor", "worl", "world"])) +# print(s.longestWord(["a", "banana", "app", "appl", "ap", "apply", "apple"])) +print(s.longestWord( ["e", "el", "ele", "elep", "eleph", "elepha", "elephan", "elephant"])) diff --git a/Week_04/id_3/trie/LeetCode_720_3_v2.py b/Week_04/id_3/trie/LeetCode_720_3_v2.py new file mode 100644 index 00000000..315321c0 --- /dev/null +++ b/Week_04/id_3/trie/LeetCode_720_3_v2.py @@ -0,0 +1,61 @@ +""" +尝试用数组实现Trie树 但是性能似乎没啥改善 +""" +letter_a = ord('a') + + +class TrieTree: + + def __init__(self): + self.root = TrieNode() + + def add(self, word): + node = self.root + for w in word: + index = ord(w) % letter_a + if not node.edges[index]: + node.edges[index] = TrieNode() + node = node.edges[index] + node.letter = w + node.is_word = True + + +class TrieNode: + + def __init__(self): + self.edges = [None] * 26 + self.letter = None + self.is_word = False + + +class Solution: + def longestWord(self, words): + if not words: + return '' + + tree = TrieTree() + for word in words: + if word == '': + continue + tree.add(word) + + self.result = [] + self.dfs(tree.root, []) + return ''.join(self.result) + + def dfs(self, node, curr): + curr.append(node.letter) + if (len(curr) - 1) > len(self.result): + self.result[:] = curr[1:] + + for sn in node.edges: + if not sn or not sn.is_word: + continue + self.dfs(sn, curr) + curr.pop() + + +s = Solution() +print(s.longestWord(["w", "wo", "wor", "worl", "world"])) +print(s.longestWord(["a", "banana", "app", "appl", "ap", "apply", "apple"])) +print(s.longestWord( ["e", "el", "ele", "elep", "eleph", "elepha", "elephan", "elephant"])) diff --git a/Week_04/id_3/trie/LeetCode_720_3_v3.py b/Week_04/id_3/trie/LeetCode_720_3_v3.py new file mode 100644 index 00000000..0b203f27 --- /dev/null +++ b/Week_04/id_3/trie/LeetCode_720_3_v3.py @@ -0,0 +1,65 @@ +""" +在v1基础上尝试做更多的剪枝操作 +==== +加入count 尝试提前过滤掉不需要访问的节点 +时间复杂度O(n*k) k是单词平均长度 +""" +import collections + + +class TrieTree: + + def __init__(self): + self.root = TrieNode() + + def add(self, word): + node = self.root + for w in word: + node = node.edges[w] + node.letter = w + node.count += 1 + node.is_word = True + + +class TrieNode: + + def __init__(self): + self.edges = collections.defaultdict(TrieNode) + self.count = 0 + self.letter = None + self.is_word = False + + +class Solution: + def longestWord(self, words): + if not words: + return '' + + tree = TrieTree() + for word in words: + if word == '': + continue + tree.add(word) + + self.result = [] + self.dfs(tree.root, []) + return ''.join(self.result) + + def dfs(self, node, curr): + curr.append(node.letter) + diff_length = len(curr) - 1 - len(self.result) + if diff_length > 0: + self.result[:] = curr[1:] + + for key in sorted(node.edges.keys()): + sn = node.edges[key] + if sn.is_word and sn.count >= diff_length: + self.dfs(sn, curr) + + curr.pop() + + +s = Solution() +print(s.longestWord(["w", "wo", "wor", "worl", "world"])) +print(s.longestWord(["a", "banana", "app", "appl", "ap", "apply", "apple"])) +print(s.longestWord( ["e", "el", "ele", "elep", "eleph", "elepha", "elephan", "elephant"])) diff --git a/Week_04/id_3/trie/LeetCode_720_3_v4.py b/Week_04/id_3/trie/LeetCode_720_3_v4.py new file mode 100644 index 00000000..c8dd4111 --- /dev/null +++ b/Week_04/id_3/trie/LeetCode_720_3_v4.py @@ -0,0 +1,384 @@ +""" +我对题目之前有个误解,一定要从1个字母开始才行 +Trie树性能似乎比不过人家,试试O(nlogn) +倒序遍历words有3个目的 +1 最终需要有单词是一个字母的才算数,倒序更容易写 +2 更容易剪枝,长度不够的直接pass +3 由于相同的答案要按字典排序 所以在前的要覆盖在后的答案 + +=====我错了 这么整不行 +不用trie 这么多用例过不了 好麻烦 +真的是太折磨人了 各种出乎意料的用例 +======================= +真特么不容易 总算通过了 确实效率提高了 +======================= +v5有个更高效的实现 +""" + + +class Solution: + def longestWord(self, words): + if not words: + return '' + words.sort() + result = '' + rm = {} + last = None + for i in range(len(words)-1, -1, -1): + word = words[i] + + # 被迫去重 + if word == last: + continue + else: + last = word + + if word not in rm: + if len(word) < len(result): + continue + rm[word] = word + + r = rm.pop(word) + if len(r) < len(result): + continue + + if len(word) == 1: + result = r + else: + prev = word[:-1] + # 有一种情况是后来较短的新加入元素反倒覆盖了早先加入的长元素 + if prev in rm and len(rm[prev]) > len(r): + continue + rm[prev] = r + + return result + + +s = Solution() +# print(s.longestWord(["vsw", "vs", "zwu", "vsx", "nc", "o", "vswus", "orv", "imf", "i", "v", "zw", "vs"])) +# print(s.longestWord(["w", "wo", "wor", "worl", "world"])) +# print(s.longestWord(["a", "banana", "app", "appl", "ap", "apply", "apple"])) +# print(s.longestWord(["e", "el", "ele", "elep", "eleph", "elepha", "elephan", "elephant"])) +# print(s.longestWord(["ogz", "eyj", "e", "ey", "hmn", "v", "hm", "ogznkb", "ogzn", "hmnm", "eyjuo", "vuq", "ogznk", "og", "eyjuoi", "d"])) +# print(s.longestWord(["m", "mo", "moc", "moch", "mocha", "l", "la", "lat", "latt", "latte", "c", "ca", "cat"])) +# print(s.longestWord(["rac", "rs", "ra", "on", "r", "otif", "o", "onpdu", "rsf", "rs", "ot", "oti", "racy", "onpd"])) +# print(s.longestWord( +# ["ts", "e", "x", "pbhj", "opto", "xhigy", "erikz", "pbh", "opt", "erikzb", "eri", "erik", "xlye", "xhig", "optoj", +# "optoje", "xly", "pb", "xhi", "x", "o"])) +print(s.longestWord( + ["unnmgrejgrdhyhtlnotakcfrumgchf", "unnmgrejgrdhyhtlnotakcfrumgcko", "unnmgrejgrdhyhtlnotakcfrumgcnt", + "unnmgtdwmfdrggjhwiveakaans", "unnmgrejgkxvrsrcutgmozxwfxtyh", "unnmgrejgrdhyhtlnotakcfrumgckb", + "unnmgrejgrtseekgfsqrpzarrugyoo", "unnmgrejgrdhyhtlnotafgintna", "unnmgrejgrdhyhtlnotakcfrumgcc", + "unnmgrejgrdhyhtlnotakcfrumgcae", "unnmgrejgrdhyhtlnotakcf", "unnmgrejgrdhyhtlnotakcfrumgczf", + "unnmgrejgrdhyhtlnotakcfrumgcuu", "unnmgrejgrdhyhtlnotakcfrumgcgb", "unnmgrejgrdhyhtlnotakstpse", + "unnmgrejgrdhyhtlnotalrrfbhxfwr", "unnmgrejgrdhyhtlnotakcfrumgcle", "unnmgrejgrdhyhtlnotakcfrumgcia", + "unnmgrejgrdhyhtlno", "unnmgrejjnoewygegmereqavjufj", "unnmgrejgrdhyhtlnotakcfrumgcnj", + "unnmgrejgrdhyhtlnotakcfrumgcli", "unnmgrejgrdhyhtlnotakcfrumgcqg", "unnmgrejgrdhyhtlnotakcfrumgcdc", + "unnmgrejgrdhyhtlnotakcfrumgcqz", "unnmgrejgrdhyhtlnotakcfrumgcnx", "unnolyiqthfxeeuiqwyyyxa", + "unnmgrejgrdhyhtlnoteeqstntxyzb", "unnmgrejgrdhyhtlnotakcfrumgcom", "unnmgr", "unnmgrejgrdhyhtlnotakcfrumgcmb", + "unnmgrejgrdhyhtlnotakcfrumgcka", "unnmgrejgrdhyhtlnotakcfrumgcqs", "fwqhslqjtdkkuqfmydynsaaiiepp", + "unnmgrejgrdibavjwpkovmmdga", "unnmgrejgrdhyhtlnotakcfrumgczz", "unnmgrejgrdhyhtlpraihr", "unnmgrenxlnedexgyvpeyb", + "unnmgrejgrdhyhtlnotakcfrumgctm", "unnmgrejgrdhyhtlnotakcfrumgcvs", "unnmgrejgrdhyhtlnotakcfrumgcou", + "unnmbatzovqozurvkwzpumnfpjp", "unnmgrejgrdhyhtlnotakcfrumgcbj", "unnmgrejgrdhyhtlnotakcfrumgcpz", + "unnmgrejgrdhyhtlnotakcfrumgcqu", "unnmgrejgrdhyhtlnotakcfrumgcux", "unnmgrejgrdhyhtlnotakcfrumgchq", + "unnmgrejgrdhyhtlnotakcfrumgcxo", "unnmgrejgrdhyhtlnotakcfrumgcrp", "unnmgrejgrdhyhtlnotakcfrumgcpf", + "unnmgrejgrdhyhtlnotakcfrumgcdb", "unnmgrejgrdhyhtlnotakcfrumgcob", "unnmgrejgrdhyhtlnotakcfrumgchn", + "unnmgrejgrdhyhtlnotakcfrumgcmq", "unnmgrejgrdhyhtlnotakcfrumgcki", "unnmgrejgrdhyhtlnotakcfrumgcmr", + "unnmgrejdlxyrouwopnyciahsbdm", "unnmgrejgrdhyhtlnotakcfrumgclo", "unnmgrejgrdhyhtlnotakcfrumgccn", + "unnmgrejgrdhyhtlnov", "unnmgrejgrdhyhtlnotakcfrumgcnq", "unnmgrejgrdhyhtlnotakcfrumgcjj", + "unnmgrejgrdhyhtlnotakcfrumgcaa", "unnmgrejgrdhyhtlnotakcfrumgctz", "unnmgrejgrdhyhtlnotakcfrumgchy", + "unnmgrejgrdhyhtlnotakcfrumgcpz", "unnmgrejgrdhyhwdmxzjvdqs", "unnmgrejgrdhyhtljwrbasro", + "unnmgrejgrdhyhtlnotakcfrumgcfu", "unnmgrejgrdhyhtlnotakcfrumgcbh", "unnmgrejgrdhyhtlnotakcfrumgcax", + "unnmgrejgrdhyhtlnotakcfrumgcvg", "unnmgrejgrdhyhtlnotakcfruspsis", "ubhrixkqideeukermfzavtceeezkni", + "unnmgrejgrdhyhtlnotakcfrumgcmu", "unnmgrejgrdhzcpmspthzldkfp", "unnmgrejgrdhyhtlnotakcfrumgcfd", + "unnmauivdwnusmupaol", "unnmgrejgrdhyhtlnotakcfrumgckt", "unnmgrejgrdhyhtlnotakcfrumfgg", + "unnmgrejgrdhyhtlnotakcfrumgcqf", "unnmgrejgrdhyhtlnotakcfrumgczv", "unnmgrejgrdhyhtlnotakcfrumgcme", + "unnmgrejgrdhyhtlnotakcfrumgcxr", "unnmgrejgrdhyhtlnotakcfrumgcvo", "unnmgreqkoxaakegbzmjeginff", + "unnmgrejgrdhyhtlnotakcfrumgcy", "unnmgrejgrdhyhtlnotakcfrumgcyq", "unnmgrejgrdhyhtlnoqndipxyfl", + "unnmgrejgrdhyhtlnotakcfrumgcu", "unnmgrejgrmucinqkufc", "unnmgrejgrdhyhtlnotakcfrumgcrn", + "unnmgrejgrdhyhtlnotakcfrumgcoc", "unnmgrejgrdhyhtlnotakcfrumgcqk", "unnmgrejgrdhyhtlnotakcfsek", + "unnmgrejgrdhyhtlnotakcfrumgcyn", "unnmgrejgrdhyhtlnotakcg", "unnmgrejgrdhyhtlnotakcfrumgcdm", + "unnmgrejgrdhyhtlnotakcfrumgcuy", "unnmgrejgrdhyhtlnotakcfrumgcmi", "unnmgrejgrdhyhtlnotakcfrumgczk", + "unnmgrejgrdhyhtlnotakcfrumgcyb", "unnmgrejgrdhyhtlnotzfb", "unnmgrejgrdhyhtlnotakcfrumgcoo", + "unnmgrejgrdhyhtlnotakcfrumgcwd", "unnmgrejgrdhyhtlnopszcllz", "unnmgrejgrdhyhtlnotakc", + "unnmgrejgrdhyhtlnotakcfrumgcug", "unnmgrejgrdhyhtlnotakcfrumgcgf", "unnmgrejgrdhyhtlnotakcfrumgcok", + "unnmgrejgrdhyhtlnotakcfrumgc", "unnmgrejgrdhyhtlnotakcfrumgcto", "unnmgrejgrdhyhtlnotakcfrumgcwk", + "uxoiokvrivmlliz", "bdzurkrnwmzw", "unnmgrejgrdhyhtlnotakcfrumgciq", "unnmgrejgrdhyhtlnotakcfrumgcrf", + "unnmgrejgrdhyhtlnotakcfrumgcjk", "unnmgrejgrdhyhtlnotakcfrumgcqh", "unnmgrejgrdhyhwerwizdkmk", + "unnmgrejgrdhyhjlrqenvntu", "unnmgrejgrdhyhtlnotakcfrumgcwb", "unnmgrejgrdhyhtlnotakcfrumgcge", + "unnmgrejgrdhyhtlnotakcfrrcgyjk", "unnmgrejgrdhyhtlnotakcfrumgcum", "unnmgrejgrdhyhtlnotakcfrumgcvj", + "unnmgrefmfrwmseeixnapcos", "unnmgrejgrdhyhtlnotakcfrumgcci", "unnmgrejgrdhyhtlnotakcfrumgcgd", + "unnmgrejgrdhyhtlnotakcfrumgchv", "unnmgrejgrdhyhtlnotakcfrumgcjc", "unnmgrejgrdhyhtlnotakcfrumgcog", + "unnmgrejgrdhyhtlnotakcfrumgce", "unnmgrejgrdhyhtlnotakcfrugdyko", "unnmgrejgrdhyhtlnotakcfrumgcsg", + "unnmgrejgrdhyhtlnotakcfrumgcbx", "unnmgrejgrdhyhtlnotakcfrumgcup", "unnmgrejgrdhyhtlnotakcfrumgcth", + "unnmgrejgrdhyhtlnotakcfrumgcab", "unnmgqymi", "unnmgrejgrdhgpzjbcbuagqw", "unnmgrejgrdhyhtlnotakcfrumgcdq", + "unnmgrejgrdhyhtlnotakcfrumgcxp", "unnmgrejgrdhyhtlnotakcfrumgcve", "unnmgrejgrdhyhyzmdasjavr", + "unnmgrejgrdhyhtlnotakcfrumgczg", "unnmgrejgrdhyhtlnotakcfrumgchr", "unnmgrejgrdhyhtlnotakcfrumgcse", + "unnmgrejgrdhyhtlnotakcfrumgcdl", "unnmgrejgrdhyhtlnotakcfrumgccq", "unnmgrejgrdhyhtlnotakcfrumgcdu", + "unnmgrejgrdhyhtlnotakcfrumgczh", "unnmgrejgrdhyhtlnotakcfrumgcds", "unnmgrejgrdhyhtlnotakcfrumgczj", + "unnmgrejgrdhyhtlnotakcfrum", "yulkzvmdhmlymcabaiwabej", "unnmgrejgrdhyhtlnotakcfrumgcig", + "unnmgrejgrdhyhtlnotakcfrumgcvq", "unnmgrejgrdhyhtlnotakcfruml", "unnmgrejgrdhyhtlnotakcfrumgcgg", "unnmg", + "unnmgrejgrdhyhtlnotakcfrumgcmg", "unnyhsyirirrhqygaacirgwujxfvod", "unnmgrejgrdhyhtlnotakcfrumgclu", + "unnmgrejgrdhyhtlnotakcfrumgcsz", "unnmgrejgrdhyhtlnotakcfrumgcof", "unnmgrejgrdhyhtlnotakcfrumgccb", + "unnmgrejgrdhyhtlnotakcfrumgckn", "unnmgrejgrdhyhtlnotakcfrumgcsl", "unnmgrejgrdhyhtlnoklagrmfj", + "unnmgrejgrdhyhtlnnniso", "unnmgrejgrdhyhtlnotakcfrumgcvz", "unnmgrejgr", "unnmgrejgrdhyhtlnotakcfrumgcxu", + "unnmgrejgrdhyhtlnotakcfrumgcin", "unnmgrejgrdhcfvzbreouq", "unnmgrejgrdhyhtlnotakcfrumgcld", + "unnmgrejgrdhyhtlnotakcfrumgcue", "unnmgrejgrdhyhtlfgauwx", "unnmgrejgrdhyhtlnotakcfrumgcqw", + "unnmgrejgrdhyhtlnotakcfrumgcpu", "unnmgrejgrdhyhtlnotakcfrumgcvi", "unnmgrejgrdhyhtlnotakcfrumgcoq", + "unnmgrejgrdhyhtlnotakcfrumgcpo", "unnmgrejgrdhyhtlnotakcfrumgczs", "unnmgrejgaiickcjjbkhhjrysys", + "unnmgrejgrdhyhtlnotakcfrumgcd", "u", "unnmgrejgrdhyhtlnotakcfrumgcjp", "unnmgrejgrdhyhtlnotakcfrumgcgk", + "unnmgrejgrdhyhtlnotakcfrumgcjz", "unnmgrejgrdhyhtlnotakcfrucsvbp", "unnmgrejgrdhyhtlnotakcfrumgcny", + "unnmgrejgrdhyhtlnotnabdnnabj", "unnmgrejgrdhyhtlnotakcfrumgcqo", "unnmgrejgrdhyhtlnotakcfrumgchs", + "unnmgrejgrdhyhtlnotakcfrumgcfn", "unnmgrejgrdhyhtlnotakcfrumgcst", "unnmgrejgrdhyhtlnotakcfrumgcdd", + "unnmgrejgrdhyhtlnotakcfrumgcsv", "unnmgrejgrpcjtlsjnxwrpm", "unnmgrejgrdhyhtlnotakcfrumgcel", + "unnmgrejgrdhyhtlnotakcfrumgcus", "unnmgrejgrdhyhtlnotakcfrumgcu", "unnmgrejgrdhyhtlnjatnmhpnzjom", + "unnmgrejgrdhyhtlnotakcfrumgcea", "unnmgrejgrdhyhntfazynbyxzvs", "unnmgrejgrdhyhtlnotakcfruok", + "unnmgrejgrdhyhtlnotakcfrumgcym", "unnmgrejgrdhyhtlnotakcfrumgcgx", "unnmgrejgrdhyhtlnotakcfrumgcop", + "unnmgrejgrdhyhtlnotakcfrumgcos", "unnmgrejgrdhyhtlnotakcfrumgcxj", "unnmgrejgrdhybisadlnowsttsnzag", + "unnmgrejgrdhyhtlnotakcfrumgcpk", "unnmgrejocgg", "unnmgrejgrdhyh", "unnmgrejgrdhyhtlnotakcfrumgcdp", + "unnmgrvxapikutsajevxythefrqu", "unnmgrejgrdhyhtlnotakcfrumgcte", "unnmgrejgrdhyhtlnotakcfrumgcaj", + "unnmgrejgrdhyhtlnotakcfrumgcfa", "unnmgrejgrdhyhtlnotakcfrumgckx", "unnmgrejgrdhyhtlnotakcfrumgczo", + "unnmgrejgrdhyhtlnotakcfrumgcam", "unnmgrejgrdhyhtlnotakcfrumgcee", "unnmgrejgrdhyhtlnotakcfrumgcyw", + "unnmgrejgrdhyhtlnotakcfrumgckw", "unnmgrejgrdhyhtlnotakcfrumgcjd", "unnmgrejgrdhyhtlnotakcfrumgcay", + "unnmgrejgrdhyhtlnotakcfrumgckg", "unnmgrejgrdhyhtlnotakcfrumgcad", "unnmgrejgrdhyhtlnotakwllss", + "unnmeqjoniaczaegfdzou", "unnmgrejgrdhyhtlnotakcfrumgcba", "unnmgrejgrdhyhtlnotakcfrumgcrq", + "unnmgrejgrdhyhtlnotakcfrumgo", "unnmgrejgrdhyhtlnotakcfrumgcqe", "unnmgrejgrd", "unnmgrejgrdhyhtlnotakcfrumgcvx", + "unnmgrejgrdhyhtlnotakcfrumgcqr", "unnmgrejgrdhyhtlnotakcfrumgcxy", "unnmgrejgrdhyhtlnotakcfrumgcks", + "unnmgrejgrdhyhtlnotakcfrumgcuq", "unnmgrejgrdhyhtlnotakcfbad", "unnmgrejgrdhyhtlnotakcfrumgcpa", + "unnmgrejgrdhyhtlnotakcfrumgczr", "unnmgrejgrdhyhtlncxovnenmoe", "unnmgrejgrdhyhtlnotakcfrumgcsw", + "unnmgrejgrdhyhtlnotakcfrumgctu", "unnmgrejgrdhyhtlnotakcfrumgckk", "unnmgrejgrdhyhtlnotakcfrumgczn", + "unnmgrejgraiyrcljbabpsnbxdwdf", "unnmgrejgrdhyhtlsm", "unnmgrejgrdhyhtlnoydbxtdkuf", "ugtozcniwqyt", + "unnmgrejgrdhyhtlnotakcfrumgcrs", "unnmgrejgrdhyhtlnotakcfrumgcnf", "unnmgrejgrdhyhtlnotakcfrumfxss", + "unnmgrejgrdhyhtlnotakcfrumgco", "unhsffydvo", "unnmgrr", "unnmgrejgrdhyhtlnotakcfrumgcrl", + "unnmgfbforatzmkoextfzweoru", "unnmgrejgrdhyhtlnotakcfrumgcyg", "unnmgrejgrdhyhtlnotakcfrumgcaq", + "unnmgrejgrdhyhtlnotakcfrumgcwo", "unnmgrejgrdhyhtlnotakcfrumgctl", "unnmgrejgrdhyhtlnotakcfrumgcsm", + "unnmgrejgrdhyhtlnotakcfrumgclw", "unnmgrejgrdhyhtlnotakcfrumgcif", "unnmgrejgrdhyhtlnotakcfrumgcqy", + "unnmgrejgrdhyhtlnotakcfrumgcnd", "unnmgrejgrdhyhtlnotakcfrumgcov", "unnmgrejgrdhyppoppnjlrnfyhbf", + "unnmgrejgrdhyhtlnotakcfrumgcjr", "unnmgrejgrdhyhtlnotakcfrumgcct", "unnmgrejgrdhyhtlnotaaixakv", + "unnmgrejgrdhyhtlnotakcfrumgczc", "unnmgrejgrdhyhtlnotakcfrumgckh", "unnmgrejgrdhyhtlnotakcfrumgcgq", + "unnmgrejgrdhyhtlnotakcfrumgctw", "unnmgrejgrdhyhtlnotakcfrumgcyv", "unnmgrejgrdhyhtlnotakcfrumgcja", + "unnmgrejgrdhyhtlnotakcfrumgcuo", "unnmgrejgrdhyhtlnotakcfrumgcvu", "unnmgrejgrdhyhtlnotakcfrumgcuk", + "unnmgrejgrdhyhtlnotakcfrumgcje", "unnmgrejgrdhyhtlnotakcfrumgcls", "unnmgrejgrdhyhtlnotakcfrumgcn", + "unnmgrejgrdhyhtlnotakcfrumgceo", "unnmgrejgrdhyhtlnotakcfrumgcmc", "unnmgrejgrdhyhtlnotakcfrumgcsj", + "unnmgrejgrdhyhtlnotakcfrumgcfm", "unnmgrejgrdhyhtlnotakcfrumgckr", "unnmgrejgrdhyhtlnotavt", + "unnmgrejgrdhyhtlnotakcfrumgcrb", "unnmgrejgrdhyhtlnotakcfrumgcyt", "unnmgrejgrdhyhtlnotakcfrumgced", "unnmgrejgr", + "unnmgrejgrdhyhtlnotakcfrumgazp", "unnmgrejgrdhyhtlnotakcfrumgcgh", "unnmgrejgrdhyhtlnotakcfrumgcvn", + "unnmgrejgrdhyhtlnotakcfrumgclz", "unnmgrejgrdhv", "unnmgrejgrdhyhtlnotakcap", "unnmgrejgrdhyhtlnotakcfrumgcdn", + "unnmgrejgrdhyhtlnotakcfrumgcuf", "unnmgrejgrdhyhtlnotakcfrumgcqn", "unnmgrejgrdhyhtlnotakcfrumgcvt", + "unnmgrejgrdhyhtupdlrapwjdgcgdu", "unnmgrejgrdhyhtlnotakcfrumgcwr", "unnmgrejgrdhyhtlnotakcfrumgcx", + "unnmgrejgrdhyhtlnotakcfrumgcne", "unnmgrejgrdhyhtlnotakcfrumgccp", "unnmgrejgrdhyhtlnotakcfrumgchk", + "unnmgrejgrdhyhtlnotakcfrumgcgj", "unnmgrejgrdhyhtlnotakcfrumgccu", "unnmgrejgrdhyhtnwk", + "unnmgrejgrdhyhtlnotakcfrumgcyy", "unnmgrejgrdm", "unnmgrejgrdhyhtlnotakcfruwrgq", + "unnmgrejgrdhyhtlnotakcfrumgccm", "unnmgrejgrdhyhtlnotakcfrumgcql", "unnmgrejgrdhyhtlpjxrbyuyy", + "unnmgrejgrdhyhtlnotakcfrumgczi", "unnmgrejgrdhyhtlnotakcfrumgciy", "unnmgrejgrdhyhtlnotakcfrumgctd", + "unnmgrejgrdhyhtlnotakcfrumg", "unnmgrejgrdhyhtlnotakcfrumgcev", "unnmgzwr", "unnmgrejgrdhyhtlnotakcfrumgcps", + "unnmgrejgrdhyhtlnotakcfrumgckj", "unnmgrejgrdhyhtlnotakcfrijs", "unnmgrejgrdhyhtlnotakcfrumgcon", + "unnmgrejgrdhyhtlnotarwnjdzsp", "unnmgrejgrdhyhtlnotakcfrumgcla", "unnmgrejgrdhj", "unnmgrejgrdhyhtlnvqttyjkul", + "unnmgrejgrdhyhtlnotakcfrumgclx", "unnmgrejgrdhyhtlnotakcfrumgcdx", "unnmgrejgrdhyhtlnotakcfrumgcyz", + "unnmgrejgrdhyhtlnotakcfrumgcag", "unnmgrejgrdhyhtlnotakcfrumgcpb", "unnmgrejgrdhyhtlnotakcfrumgcfw", + "unnmgrejgrdhyhtlnotakcfrumgceu", "unnfwczbdsxebmzqcngxn", "unnmgrejgrdhyhtlnotakcfrumgcju", + "unnmgrejgrdhyhtlnotakcfrumgcgo", "unqnhd", "unnmgrejgrdhyhtlnotakcfrumgciu", "unnmgrejgrdhyhtlnobqjxh", + "unnmgrejgrdhyhtlnotakcfrumgcem", "unnmgrejgrdhyhtlnotakcfrumgcud", "unnmgrejgrdhyhtlnotakcfrumgchh", + "unnmgrejgrdhyhtlnotakcfrumgcio", "unnmgrejgxofdqcwtidusfpbvjadrd", "unnmgrejgrdhyhtlnotwzqqnpbyy", + "unnmgrejgrdhyhtlnotakcfrumgcpt", "unnmgrejgrdhyhtlnopbwqjqtwjo", "unnmgrejgrdhyhtlnotakcfrumgcmo", + "unnmgrejgrdhyhtlnotakcfrumgcxd", "unnmgwiy", "unnmgrejgrdhyhtlnotakcfrumgcyl", "unnmgrejgrdhyhtlnotakcfrumgcoj", + "unnmgrejgrdhyhtlnotakcfrumgcxm", "unnmgrejgrdhy", "unnmgrejgrdhyhtlnotakcfrumgchw", + "unnmgrejgrdhyhtlnotakcfrumgcun", "unnmgrejgrdhyhtlnotakcfrumgczd", "unnmgrejgrdhyhtlnotakcfrumgcdp", + "unnmgrejgrdhyhtlnotakcfrumgcbs", "unnmgrejgrdhyhtlnotakcfrumgcce", "unnmgrejgrdhyhtlnotakcfrumgcku", + "unnmgrayfnjflpxzcgsneuezjwznr", "unnmgrejbwfvnjievqrnvh", "unnmgrejgrdhyhtlnotakcfrumgctv", + "unnmgrejgrdhyhtlnotakcfrumgcpg", "unnmgrejgrdhyhtlnoclylfchqd", "unnmgrejgrdhyhtlnotakcfrumgcfv", "uvmbstlaqcqk", + "unnmgrejgrdhyhtlnotakcfrumgceq", "unnmgrejgrdhyhgmimkbgohnx", "unnmgrejgrdhyhtlnotakcm", "unnmgrejgrdhpaojwpitfy", + "unnmgrejgrdhyhtlnotakcfrumgcwz", "unnmgrejgrdhyhtbhxfyacquzye", "unnmgrejgrdhyhtlnotakcfrumgcav", + "unnmgrejgrdhyhtlnotakcfrumgczl", "unnmgrejgrdhyhtlnotakcfrumgcua", "unnmgrejgrdhyhtlnotakcfrumgcbz", + "unnmgrejgpk", "unnmgrejgrdhyhtlnotakcfrumgcnr", "unnmgrejgrdhyhtlnotakcfrumgcjt", + "unnmgrejgrdhyhtlnotakcfrumgcff", "unnmgrejgrdhyhtlnotwpzl", "unnmgrejgrdhyhtlnotakcfrumgcd", + "unnmgrejgrdhyhtlnotakcfrumgcxl", "unnmgrejgrdhyhtlnotakcfrumgcrj", "unnmgrejgrdhyhtlnotakcfrumgcgi", + "unnmgrejgrdhyhtlnotakcfrumgcsf", "unnmgrejgrdhyhtlnotakcfrumgcrr", "unnmgrejgrdhyhtlnotakcfrumgcfx", + "unnmgrejgrdhyhtlnotakcfrumgcwf", "unnmgrejgrdhyhtlnotalbsklsmt", "unnmgrejgrdhyhtlnotakcfrumgcwv", + "unnmgrejgrdhyhtlnotakcfywyfs", "unnmgrejgrdhyhtlnotakcfrumszn", "unnmgrejgrdhyhtlnotakcfrumgcsc", + "unnmgrejgrdhyhtlnotakcfrumgkm", "unnmgrejgrdhyhtlnotakcfrumgcgy", "unnmgrejgrdhyhtlnotakcfrumgcac", + "unnmgrejgrdhyhtlnotakcfrumgcil", "unnmgrejgrdhyhtlnotakcfrumgczb", "unnmgrejgrdhyhtlnotakcfrumgcrm", + "unnmgrejgrdhyhtlnotakcfrumgcnk", "ukqeym", "unnmgrejgrdhyhtlnotakcfrumgceh", "unnmgrejgrdhyhtlnotakcfrumgcak", + "unnmgrejgrdhyhtlnotakcfrhhdbw", "unnmgrejgrdhyhtlnotakcfrumgcvl", "unnmgrejgrdhyhtlnotakcfrumgr", + "unnmgrejgrdhyhtlnotakcfrumgcqa", "unnmgrejgrdhyhtlnotakcfrumgcns", "unnmgrejgrdhyhtlnotakcfrumgcbq", + "unnmgrejlyvqfzhalhvcmljzswvub", "unnmgrejgrdhyhtlnotrmtcwcphyy", "unnmgrejgrdhyhtlnotakcfrumgcpe", + "unnmgrejgrdhyhtlnotakcfrumgcyj", "unnmgrejgrdhyhtlnotakcfrumgcjs", "unnmgrejgrdhyhtlnotakcfrumgcwc", + "unnmgrejgrdhyhtlnotakcfrumgcno", "unnmgrejgrdhyhtlnos", "unnmgrejgrnpdx", "unnmgrejgrdhyhtlnotakcfrumgccg", + "unnmgrejgrdhyhtlnotakcfrumgcrc", "unnmgrejgrdhyhtlnotakczqdndk", "unnmgrejgrdhyhtlnotakcfrumgcuh", + "unnmgrejgrdhyhtlnotakcfrumgccs", "unnmgrejgrdhyhtlnotakcfrumgcmj", "unnmgrejgrdhyhtlnotakcfrumgclj", + "unnmgrejgsnnirkv", "unnmgrej", "ujcaoawifxy", "unnmgrejgrdhyhtlnjfyecozuou", "unnmgrejgrdhyhtlnotakcfrumgcpl", + "unnmgrejgrdhyhtlnotakcfrumrjx", "unnmgrejgrdhyhtlnotakcfrumgcws", "unnmgrejgrdhyhtlnotakcfrumgcek", + "unnmgrejgrdhyhtlnotakcfrumgcbd", "unnmzpromreensmkblv", "unnmgrejgrdhyhtlnotakcfrumgciv", + "unnmgrejgrdhyhtlnotakcfrumgcsx", "unnmgrudgvucgjlpdiijueghj", "unnmgrejgrdhyhtlnotakcfrumgcv", + "unnmgrejgrdhyhtlnotakcfrumgcpq", "unnmgrejgrdhyhtlnotakcfrumgcfp", "unnmgrejgrdhyhtlnotakcfrumgcqd", + "unnmgrejgrdhyhtlnotakcfrumgcul", "unnmgrejgrdhyhtlnotaroxeulx", "unnmgrejgrydscsgdou", "unnmgrejgrdhnegg", + "unnmgrejgrdhyhtlnotakcfrumgcfh", "unnmgrejgrdhyhtlnotakcfrumgcib", "unnmgrejgrdhyhtlnotakcfrumgcbe", + "unnmgrejgrdhyhtlnotakcfrumgct", "unnmgrejgrdhyhtlnotakcfrumgckp", "unnmgrejgrdhyhtlnotakcfrumgcph", + "unnmgrejgrdhyhtlnotakcfrumgck", "unnppqvsozeypffgs", "unnmgrejgrdhyhtqksdpfqk", "unnmgrejgrdhyhtlnotakcfrumgcde", + "unnmgrejgrdhyhtlnotakcfrumgcxz", "unnmgrejgrdhyhtlnotakcfrumgcyu", "unnmgrejgrdhyhtlnotakcfrumgclh", + "unnmgrejgrdhyhtlnotakcfrumgcis", "unnmgrejgrdhyhtlnotakcfrumgcnm", "unnmgrejgrdhyhtlnotakcfrumgctf", + "unnmgrejgrdhyhtlnotakcfrumgcbv", "unnmgrejgrdhyhtlnotakcfrxphm", "unnmgrejgrdhyhtlnotakcfrumgcys", + "unnmgrejgrdhyhtlnotakcfrumgcxb", "unnmgrejgrdhyhtlnotakcfrumgcsv", "unnmgrejgrdhyhtlnotakcfrumgchz", + "unnmgrejgrdhyhtlnotakcfrumgciz", "unnmgrejgrdhyhtlnotakcfrumgckv", "unnmgrejgrdhyhtlnotakcfrumgcpw", + "unnmgrejgrdhyhtlnotakcfrumgcxi", "unnmgrejgrdhyhtlnotakcfrumgcxs", "unnmgrejgrdhyhtlnotakcfrumgcho", + "unnmgrejgrdhyhtlnotakcfrumgcck", "unnmgrejgrdhyhfpktehqte", "unnmgrejgrdhyhtlnotakcfrumgckc", + "unnmgrejgrdhyhtlnotakcfrumgcqi", "unnmgrejgrdhyhtlnotakcfrumgcpi", "unnmgrejgrdhyhtlnotakcfrumgcyd", + "unnmgrejgrdhyhtlnotakcfrumgcpj", "unnmgrejgrdhyhtlnotakcfrumgcr", "unnmgrejgrdhyhtlnotakcfrumgcve", + "unnmgrejgrdhyhtlnotakcfrumgcbb", "unnmgrejgrdhyhw", "unnmgrejgrdhyhtlnotakcfrumgcnv", + "unnmgrejgrdhyhtlnotakcfrumgcut", "unnmgrejgrdhyhtlnotakcfrumgckz", "unnmgrejgrdhyhtlnotakcfrumgcod", + "unnmgrejgrdhyhtlnotakcfrumgcvh", "unnmgrjycqjafaykapibeny", "unnmgebvrlxccz", "unnmgrejgrdhyhtlnotakcfrumgcxx", + "unnmgrejgrdhyhtlnotakcfrumgcqb", "unnmgrejgrdhyhtlnotakcfrumgcas", "unnmgrejgrdhyhtlnotakcfrumgcva", + "unnmgrejgrdhyhtlnotakcfrumgccw", "unnmgrejgrdhyhtlnotakcfrumgcao", "unnmgrejgrdhyhtlnotakcfrumgcf", + "unnmgrejgrdhyhtlnotakcfrumgclm", "unnmgrejgrdhyhtlnotakcfrumgctp", "unnmgrejgrdhyhtlnotakcfrumgcpx", + "unnmgrejgrdhyhtleed", "unnmgrejgmtoyjezwedqblnb", "unnmgrejgrdvnhpigjnwkwgoytzetx", "unnmgrejgrdhyhzfdjqi", + "unnmgrejgrdhyhtlnotakcfrumgcta", "unnmgrejgrdhyhtlnotakcfrumgcxa", "unnmgriednpasskcoql", + "unnmgrejgrdhyhtlnotakcfrumgchg", "unnmgrejgrdhyhtlnotakcfrumgclg", "unnmgrejgrdhyhtlnotakcfrumgchl", + "unnmgrejgrdhyhtlnotakcfru", "unnmgrejgrdhyhtlnotakcfrumgcgl", "unnmgrejgranmdoswgepkuht", + "unnmgrejgrdhyhtlnotakcfrumgcjo", "unnmgrejgrdhyhtlnotakcfrumgcez", "unnmgrejgrdhyhtlnotakcfrumiab", + "unnmgrejgrdhyhtlnotakcfrumgcoz", "unnmgrejyjkryslhwwuujfatznm", "unnmgrejgrdh", "unnmgrejgrdhyhtlnotakcfrumgcqc", + "unnmgrejgrdhyhtlnotakcfrumgchj", "unnmgrejgrdhyhtlnotakcfrumgccx", "unnmgrejgrdhyhtlnotakcfrumgcyc", + "unnmgrejgrdhyhtlnotakcfrumgclv", "unnmgrtfbu", "unnmgrejg", "unnmgrejgrdhyhtlnotakcfrumgcn", + "unnmgrejgrdhyhtlnotakcfrumgcrh", "unnmgrejgrdhyhtlnotakcfrumgcsp", "unnmgrejgrdhyhtlnotakjmx", + "unnmgrejgrdhyhtlnotakcfrumgccf", "unnmgrejgrdhyhtlnotakcfrumgcyx", "unnmgrejgrdhyhtlnotakcfrumgcvf", + "unnmgrejgrdhyhtlnotakcfrumgckf", "unnmgrejgrdhyhtlnotakcfrumgcrx", "unnmgrejdxkvuvkmpxozzwwcpiyo", + "unnmgrejgrdhyhtlnotakcfrumgcor", "unnmgrejgrdhyhtkvswyemrnzc", "unnmgrejgrdhyhtlnotakcfrumgcuj", + "unnmgrejgrdhyhtlnojg", "unnmgrejgrdhyhtlnotakcfrumgcms", "unnmgre", "unnmgrejgrdhyhtlnotakcfrumgcaf", + "unnmgrejgrdhyhtlnotakcfrumgckl", "unnmgrejgrdhyhtlnotakcfrumgcbm", "unnmgrejgrdhyhtlnotakcfrumgcbn", + "unnmgrejgrdhyhtlnotakcfrumgcsx", "unnhijigjqsdslpbkindh", "unnmgrejgrdhyhtlnotakcfrumgccd", + "unnmgrejgrdhyhtlnotakcfrumgcwi", "unnmgrejgrdhyhtlnotakcfrumgcex", "unnmgrejgrdhyhtlnotakcfruwu", + "unnmgrejgrdhyhtlnotakcfrumgceg", "unnmgrejgrdhyhtlnotakcfrumgchx", "unnmgrejgrdhyhtlnotakcfrumgcye", + "unnmgrejgrdhyhtlnotakcfrumgcgm", "unnmgrejgrdhyhtlnotakcfrgdtva", "unnmgrejgrdhyhtlnotakcfrumgcq", + "unnmgrejgrdhyhtlnotakcfrumgcih", "unnmgrejgrdhyhtpqmsawnaldkbpal", "unnmgrejgrdhyhtlnotakcfrumgcoy", + "unnmgrejgrdhyhtlnotakcfrumgcar", "un", "unnmgrejgrdhyhtlnotakcfrumgcxw", "unnmgrejgrdhyhtlnotakcvpurjlyf", + "unnmgrejgrdhyhtlnotakcfrumgcsh", "unnmgrejgrdhyhtlnotakcfrumgcfb", "unnmgrejgrdhyhtlnotakcfrumgcfg", + "unnmgrejgrdhyhtlnotakcfrumgcxc", "unnmgrejgrdhyhtlnotakcfrumgcvd", "unnmgrejgrdhyhtlnotakcfrumgckm", + "unnmgrejgrdhyhtlnotah", "unnmgrejgrdhyhtlnotakcfrumgcln", "unnmgrejgrdhyhtlnotakcfrumgcow", + "unnmgrejguvxajmfzlabypdqa", "unnmgrejgrdhyhtlnotakcfrumgcfz", "unnmgrejgrdhyhtlnotakcfrumgcfs", + "unnmgrejgrdhyhtlnot", "unnmgrejgrdhyhtlnotakcfrumgcdy", "unncavnigadfjammkonpydmy", "unnmgrejgrdhyhqphfswzijde", + "unnmgrejgrdhyhtlnotakkpphfvfo", "unnm", "unnmgrejgrdhyhtlnotakcfrumgcxq", "unnmgrejgrdhyhtlnotakcfrumgcha", + "unnmgrejgrdhyhtlnotakcfrumgcsa", "unnmgrejgrdhyhtlnotakcfrumgcrd", "unnmgrejgrdhyhtlnotakcfrumgclb", + "unnmgrejgrdhyhtlnotakcfrumgcmw", "unnmgrejgrdhyhtlnotakcfrumgci", "unnmgrejgrdhyhtlnotakcfrumgczq", + "unnmgrejgrdhyhtlnotakcfrumgcrz", "unnmgrejgrdhyhtlnotakcfrumgces", "unnmgrejgrdhyhtlnotakcfrumgcmt", + "unnmgrejgrdhyhtlnotakcfrumgczz", "unnmgrejgrdhyhtlnotakcfrumgchm", "unnmgrejgrdhyhtlnotakcfrumgcdw", + "unnmgrejgrdhyhtlnotakcfrumgcgc", "unnmgrejgrdhyhtlnotakcsexkock", "unnmgrejgrdhyhtlnotakcfrumgu", + "unnmgrejgrdhyhtlnotakcfrumgcze", "unnmgrejgrdhyhtlnotakcfrumgctx", "unnmgrejgrdhyhtlnotakcfrumgcgp", + "unnmgrejgrdhyhtlnotakcfrumgcxn", "unnmgrejgrdhyhtlnfvjomwptova", "unnmgrejgrdhyhtlnotakcfrumgcwe", + "unnmgrejgrdhyhtlnotakcfrumgcgu", "unnmgrejgrdhyhtlnotakcfrumgcit", "unnmgrejgrdhyhtlnotakcfrumgcdh", + "unnmgrejgrdhyhtlnotakcfrumgcjm", "unnmgrejgrdhyhtlnotakcfrumgcso", "unnmgrejgrdhyhtlnotakcfrumgcui", + "unnmgrejgrdhyhtlnotakcfrumgclp", "unnmgrejgrdhyhtlnotakcfrumgcnn", "unnmgrejgrdhyhtlnotakcfrumgcau", + "unnmgrejgrdhyhtlnotakcfrumgcdj", "unnmgrejgrdhyhtlnotakcfrumgcbt", "unnmgrejgrdhyhtlnotakcfrumgcsk", + "unnmgrejgrdhyhtlnotakcfrumgcda", "unnmgrejgrdhyhtlnotakcfrumgcwu", "unnmgrejgrdhyhtlnotakcfrumgcqj", + "unnmgrejyfypdastivqvpmmmuwcqz", "unnmgrejgrdhyhtlnotakcfrumgcfl", "unnmgrejgrdhyhtlnotakcfrumgcnc", "unjbnr", + "unnmgrejgrdhyhtlnotakcfrumgcft", "unnmgrejgrdhyhtlnotakcfrumgcrw", "unnmgrejgrdhyhtlnotakcfrumgcnl", + "unnmgrejgrdhyhtlnotakcfrumgcsn", "unnmgrejgrdhyhtlhegi", "unnmgrejgrdhyhtlnotakcfrumgcxv", + "unnmgrejgrdhyhtlnotakcfrumgcew", "unnmgrejgrdhyhtln", "unnmgrejgrdhyhtlnotakcfrumgcjb", "unnmgnvvdurlowdmeotrb", + "unnmgrejgrdhyhtlnotakcfrumgcww", "unnmgrejgrdhyhtlnotakcfrumgcni", "unnmgrejgrdhyqeqwqtc", + "unnmgrejgrdhyhtlnotakcfrufokd", "unnmgrejgrdhyhtltbqlfb", "unnmgrejgrdhyhtlnotakcfrumgcbl", + "unnmgrejgrdhyhtlnotakcfrumgcjq", "unnmgrejgrdhyhtlnotakcfrumgcxe", "unnmgrejgrdhyhtlnotakcfrumgcdg", "unn", + "unnmgrejgrdhyhtlnotakcfrumgcbw", "unnmgrejgrdhyhtlnotakcfrumgcjv", "unnmgrejgrdhyhtlnotakcfrumgcgr", + "unnmgrejgrdhyhtlnotakcfruawulv", "unnmgrejgrdhyhtlnotakcfrwne", "unnmgrejgrdhyhtlnotakcfrumgcap", + "unnmgrejgrdhyhtlnotakcfrumgczw", "unnmgrejqjuiqmpknlnoeufr", "unnmgrejgrdhyhtal", "unnmgrejgrdhyhtlnotakcfr", + "unnmgrejgrdhyhtlnotakcfrumgcet", "unnmnvxgduagdze", "unnmgrejgrdhyhtlnotakcfrumgcer", "unnv", + "unnmgrejgrdhyhtlnotakcfrumgccl", "unnmgrejgrdhyhtlnotakcfrumgca", "ooq", "unnmgrejgrdhyhtlnotakcfrumgclc", + "unnmgrejgrdhyhtlnotakcfrumgcwt", "unnmgrfpfy", "unnmgrejgrdhyhtlnotak", "unnmgrejgrdhyhtlnotakcfrumgchd", + "unnmgrejgrdhyhtlnotakcfrumgcgs", "unnmgrejgrdhyhtlnotakcfrumgcbk", "unnmgrejgrdhyhtlnvemzl", + "unnmgrejgrdhyhtlnotakvmsozm", "unnmgrejgrdhyhtlnotakcfrumgczx", "unnmgrejgrdhyhtlnotakcfrumgcxf", + "unnmgrejgrdhyhtlnotakcfrumgccr", "unnmgrejgrdhyhtlnotakcfrumgcie", "unnmgrejgrdhkjiqj", + "unnmgrejgrdhyhtlnotakcfrumgcs", "unnmgrejgrdhyhtlnotakcfrumgcdf", "unnmgrejgrdhyhtlnotakcfrumgcmy", + "unnmgrejgrdhyhtlnotakcfrumgcjn", "unnmgrejgrdhyhtlnotakcfrumgcwy", "unnmgrejgrdhyhtlnotakcfrumgcbu", + "unnmgrejgrdhyhtlnotakcfrumgcru", "unnmgrejgrdhyhtlnotakcfrumgcb", "unnmgrejgrdhyhtlnotakcfrumgcsu", + "unnmgrejgrdhyhtlnotakcfrumgclr", "unnmgrejgrdhyhtlnotcurjdwusi", "unnmgrejgrdhyhtlnotakcfrumgcah", + "unnmgrejgrdhyhtlnotakcfrumgcpm", "ugjdkpvylidshorcdmy", "unnmgrejgrdhyhtlnotakcfrumgcz", + "unnmgrejgrdhyhtlnotakcfrumgcvk", "unnmgrejgrdhyhtlnotakcfrumgcjx", "unnmgrejgrdhyhtlnotakcfrumgcey", + "unnmgrejgrdhyhtlnotakcfrumgcqq", "unnmgrejgrdhyhtllaoqjqtonthq", "unnmgrejgrdhyhtlnotakcfrumgcti", + "unnmgrejgrdhyhtlnotakcfrumgcyk", "unnmgrejgrdhyhtlnotakcfrumgcal", "unnmgrejgrdhyhtlnotakcfrumgcre", + "unnmgrejgrdhyhtlnotakcfrumgcra", "unnmgrejgrdhyhtlnotakcfrumgcqm", "unnmgrejgrdhyhtlnotakcfrumgcbo", + "unnmgrejgrdhyhtlnotakcfrumgcdz", "unqqjfeuixcefq", "unnmgrejgrdhyhtlnotakcfrumgcko", + "unnmgrejgrdhyhtlnotakcfrumgcmp", "unnmgrejgrdhyhtlnotakcfrumgczy", "unnmgrejgrdhyhtlnotakcfrumgj", + "unnmgrejgrdhyhtlnotakcfrumgch", "unnmgrejgrdhyhtlnotakcfrumgctb", "unnmgrejgrdhyhtlnotakcfrumgciw", + "unnmgrejgrdhyhtlnotakcfrumgcvb", "unnmgrejgrdhyhtlnota", "unnmgregbysgbuajvoyerlkqhyhfty", + "unnmgrejgrdhyhtlnotakcfrumgcgz", "unnmgrejgrdhyhtlnotakcfrumgccv", "unnmgrejgrdhyhtlnotakcfrumgcxg", + "unnmgrejgrdhyhtlnotakcfrumgcri", "unnmgrejgrdhyhtlnotakcfrumgctt", "unnmgrejgrdhyhtlnotakcfrumgcen", + "unnmgrejgrdhyhtlnotakcfrumgcna", "unnmgrejgrdhyhtlnottusaco", "unnmgrejgrdhyhtlnotakcfrumgchi", + "unnmgrejgrdhyhtlnotakcfrumgclt", "unnmgrejgrdhyhtlnotakcfrumgcfk", "unnmgrejgrdhyhtlnotakcfrumgchu", + "unnmgrejgrdhyhtlnotakcfrumgcmz", "unnmgrejgrdhyhtlnotakcfrumgcpc", "unnmgrejgrdhyhtlnotakcfrumgcbr", + "unnmgrejgrdhyhtlnotakcfrumgcnb", "unnmgrejgrdhyhtlnotakcfrumgcyp", "unnmgrejgrdhyhtlnotakcfrumgcdk", + "unnmgrejgrdhyhtlnotakcfrumgczt", "unnmgrejgrdhyhtlnotakcfrumgtl", "unnmgrejgrdhyhtljssmaergclgwds", + "unnmgrejgrdhyhtzogzlakba", "unnmgrejgrdhyhtlnotakcfrumgcsb", "unnmgrejgrdhytlmxmdiyt", + "unnmgrejgrdhyhtlnotakcfrumgczp", "unnmgrejgrdhyhtlnotakcfrumgcza", "unnmgrehygumnsieeegycfkqshdu", + "unnmgrejgrdhyhtlnotakcfrumgcry", "unnmgrejgrdhyhtlnotakcfrumgcwq", "unnmgrejgrdhyhrqahifvtbvghja", + "unnmgrejgrdhyhtlnotakcfrumgctr", "unnmgrejgrdhyhtlnotakcpekpz", "unnmgrejgrdhyhtlnotakcfrumgcvm", + "unnmgrejgrdhyhtlnotakcfrumgcuc", "unnmgrejgrdhyhtlnotakcfrumgcvp", "unnmgrejgrdhyhtlnotakcfrumgcim", + "unnmgrejgrdhyhtlnotakcfrumgcnp", "unnmgrejgrdhyhtlnotakcfrumgclf", "unnmgrejgrdhyhtlnotakcfrumgcip", + "unnmgrejgrdhyhtlnotakcfrumgcch", "unnmgrejgrdhyhtlnotakcfrumgceb", "uy", "unnmgrejgrdhyhtlnotakcfrumgcoa", + "unnmgrejgrdhyhtlnotakcfrumgcmm", "unnmgrejgrdhyhtlnotakcfrumgcgn", "unnmgrejgrdhyhtlnotakcfrumgclq", + "unnmgrejgrdhyhtlnotakcfrumgcrg", "unnmgrejgrdhyhtlnotpxrjxhez", "unnmgrejgrdhyhtlnotakcfrumgcgt", + "unnmgrejgrdhyhtlnotakcfrumgcox", "unnmgrejgrdhyht", "unnmgrejgrdhyhtlnotakcfrumgcjg", "unnmgroxnk", + "unnmgrejgrdhyhtlnotakcfrumgyt", "unnmgrejgrdhyhtlnotakcfrumgcic", "unnmgrejgrdhyhtlnotakcfrumgctq", "unx", + "unnmgmzdwratt", "unnmgrejgrdhyhtlnotakcfrumgclk", "unnmgrejgrdhyhtlnotakcfrumgcaz", "unnmthlfg", + "unnmgrejgrdhyhtlnotakcfrumgcfo", "unnmgrejgrdhyhtlnotakcfrumgcpr", "unnmgrejgrdhyhtlnotakcfrumgcgw", + "unnmgrejgrdhyhtlnotakcfrumgcnz", "unnmgrejgrdhyhtlnotakcfrumgcdo", "unnmgrejgrdhyhtlnotakcfrumgcjf", + "unnmgrejgrdhyhtlnotakcfrumgcdi", "unnmgrejgrrtueahrax", "unnmgrejgrdhyhtlnotakcfrumgcbg", "tnohyrrwoler", + "unnmglzpcpxbuvrottj", "unnmgrejgrdhyhtlnotakcfrumgcvy", "unnmgrejgrdhyhtlnotakcfrumgcjy", "unnmgrejgrdhyhtorsq", + "unnmgrejgrdhyhtlnotakcfrumgctj", "unnmgrejgrdhyhtlnotakcfrumgcdw", "unnmgrejgrdhyhtlnotakcfrumgche", + "unnmgrejgrdhyhtlnotakcfrumgchc", "unnbaznjphnbfb", "unnmgrejgrdhyhtlnotakcfrumgcqp", + "unnmgrejgrdhyhtlnotakcfrumgcgv", "unnmgrejgrdhyhtbevyyvfgifad", "unnmgrejgrdhyhtlnotakcfrumgcky", + "unnmgrejgrdhyhtlnotakcfrumgcdr", "unnmgrejgrdhyhtlnotakcfrumgcub", "unnmgrejgrdhyhtlnotakcfrumgcm", + "unnmgrejgrdhyhtlnotakcfrumgcwm", "unnmgrejgrdhyhtlnotakcfrumgcro", "unnmgrejgrdhyhtlnotakcfrumgcjh", + "unnadhzmwyvjdq", "unnmgreevzcgzkxxzdgnlrugobphch", "unnmgrejgrdhyhtlnotakcfrumgcby", + "unnmgrejgrdhyhtlnotakcfrumgcvv", "unnmgrejgrdhyhtlnotakcfrumgcpp", "unnmgrejgrdhyhtlnotakcfrumgchp", + "unnmgrejgrdhyhtlnotakcfrumgcat", "unnmgrejgrdhyhtlnotakcfrumgcp", "unnmgrejgrdhyhtlnotakje", + "unnmgrejgrdhyhtlnotakcfrumgcii", "unnmgrejgrdhyhtlnotaufzaypqi", "unnmgrejgrdhyhtlnotakcfhf", + "unnmgrejgrdhyhtlnotakcfrumgcir", "unnmgrejgrdhyhtlnotakcfrumgcoi", "unnmgrejgrdhyhtlnotakcfrumgcaw", + "unnmgrejgrdhyhtlnotakcfrumgcwa", "unnmgrejgrdhyhtlnotakcfrumgcbi", "unnmgrejgrdhyhtlnotakcfrumgcfr", "ujmwoct", + "unnmgrejgrdhyhy", "unnmgrejgrdhyhtlnotakcfrumgcvr", "unnmgrejgrdhyhtlnotakcfrumgcfe", "unnmgrejgrdhyhtlnota", + "unnmgrejgrdhyhtlnotakcfrumgcpv", "unnmgrejgrdhyhtlnotakcfrumgczm", "unnmgrejgrdhyhtlnotakcfrumgcbi", + "unnwesyhllkrljgrsvfmb", "unnmgrejgrdhyhtlnotfopgljgyrk", "unnmgrejgrdhyhtlnotakcfrumgcpn", + "unnmgrejgrdhyhtlnotakcfrumgcur", "unnmgrejgrdhyhtlnotakcfrumgcoe", "unnmgrejgrdhyhtlnotakcfrumgcpd", + "unnmgrejgrdhyhtlnotakcfrumgcmh", "unnmgrejgrdhyhtlnotakcfrumgcai", "unnmgrejgrdhyhtlnotakcfrumgctn", + "unnmgrejgrdhyszjqda", "unnmgngmxgixgxsxlh", "unnmgrejgrdhyhtlnotakcfrumgcly", "unnmgrejgrdhyhtlnotakcfrumgcjw", + "unnmgrejgrdhyhtrtsuxpdswzrvl", "unnqahpbmswmk", "unnmgrejgrdhyhtlnotakcfrumgcsi", + "unnmgrejgrdhyhtlnotakcfrumgcyi", "unnmgrejgrdhyhtlnotakcfrumgcml", "unnmgrejgrdhyhtlnotakcfrumgcyf", + "unnmgrejgrdhyhtlnotakcfrumgcnh", "unnmgrejduxxzishhdmpa", "unnmgrejgrdhyhtlnotakcfrumgcbf", + "unnmgrejgrdhyhtlnotakcfrumgcyr", "unnmgrejgrdhyhtlnotakcfrumgcma", "unnmgrejgrdhyhtlnotakcfrumgcei", + "unnmgrejgrdhyhtlnotakcfrumgcjl", "unnmgrejgrdhyhtlnotakcfrumgcwj", "unnmgrejgrdhyhtlnotakcfrumgcix", + "unnmgrejgrdhyhtlnotakcfrumgcng", "unnmgrejgrdhydhkj", "unnmgrejgrdhyhtlnotakcfrumgckd", + "unnmgrejgrdhyhtlnotakcfrumgcyo", "unnmgrejgrdhyhtlnotakcfrumgctk", "unnmgrejgrdhyhtlnotakcfrumgcot", + "unnmgrejgrdhyhtlnotakcfrumgcxh", "unnmgrejgrdhyhtlnotakcfrumgcke", "unnmgrejgrdhyhtlnotakcfrumgcqt", + "unnmgrejgrdhyhtlnotakcfrumgcwn", "unnmgrejgrdhyhtlnotakcfrumgcfj", "unnmgrejgrdhyhtlnotakcfrumgcuw", + "unnmgrejgrdhyhtlnotakcfrumru", "unnmgrejgrdhyhtlnotakcfrumgcuy", "unnmgrejgrdhyhtlnotakcfrumgcmn", + "unbdbapznjavq", "unnmgrejgrdhyhtlnotakcfrumgcnu", "unnmgrejgrdhyhtlnotakcfrumgczu", "unnfeau", + "unnmgrejgrdhyhtlnotakcfrumgcik", "unnmgrejgrdhyhtlnotakcfrumgcty", "unnmgrejgrdhyhtlnotakcfrumgcll", + "unnmgrejgrdhyhtlnotakcfrumgcwh", "unnmgrejgkzkwiwncea", "unnmgrejgrdhyhtlnotakcfrumgcwl", + "unnmgrejgrdhyhtlnotakcfrumgckw", "unnmgrejgrdhyhtlnotakcfrumgcss", "unnmgrejgbymfoq", + "unnmgrejgrdhyhtlnotakcfrumgcju", "unnmgrejgrdhyhtlnotakcfrumgcts", "unnmgrejgrdhyhtlnotakcfrumgcqh", + "unnmgrejgrdhyhtlnotakcfrumgcht", "unnmgrejgrdhyhtlnotakcfrumgcqx", "unnmgrejgrpvifhhxvxdo", + "unnmgrejgrdhyhtlnotnloxwhtp", "unnmgrejgrdhyhtlnotakcfrumgcfc", "unnmgrejgrdhyhbjtp", + "unnmgrejgrdhyhtlnotakcfrumgcca", "unnmgrejgrdhyhtlnotakcfrumgcvw", "unnmgrejgrdhyhtlnotakcfrumgcmd", + "unnmgrejgrdhypsloh", "unnmgrejgrdhyhtlnotakcfrhag", "unnmgrejgrdhyhtlnotakmyhunlwru", "unnmgrejgrdhgcjazaxy", + "unnmgrejgrdhyhtlnotakcfrumgcid", "unnmgrejgrdhyhtlnotakcfrumgcw", "unnuan", "unnmgrejgrdhyhtlnotakcfrumgcfi", + "unnmgrejgrdhyhtlnotakcfrumgccy", "unnmgrejgrdhyhtlnotakcfrumgcej", "unnmgrejgrdhyhtlnotakcfrumgckq", + "unnmgrejgrdhyhtlnotakcfrumgcol", "unnmgrejgrdhyhtlnotakcfrumgcqv", "unnmgrejgrdhyhtlnotakcfrumgcg", + "unnmgrejgrdhyhtlnotakcfrumgcl", "unnmgrejgrdhyhtlnotakcfrumgcco", "unnmgrejgrdhyhtl", + "unnmgrejgrdhyhtlnotakcfrumgcbc", "unnmgrejgrdhyhtlnotakcfrumgcef", "unnmgrejgrdhyhtlnotakcfrumgcnw", + "unnmgrejgrdhyhtlnotakcfrumgcmk", "unnmgrejgrdhyhtlnotakcfrumgccj", "unnmgrejgrdhyhtlongzfhhaapd", + "unnmgrejgrdhyhtlnotakcfrumgcki", "unnmgrejgrdhyhtlnotakcfrumgccc", "unnmgrejgrdhyrvc", + "unnmgrejgrdhyhtlnotakcfrumgcsr", "unnmgrejgrdhyhtlnotasftxw", "unnmgrejgrdhyhtlnotakcfrumgcrv", + "unnmgrejgrdhyhtlnotakcfrumgcmx", "unnmgrejgrdhyhtlnotakcfrumgcga", "bwcsrcgsctlyudalyckkud", + "unnmgrejgrdhyhtlnotakcfrumgcij", "unnmgrejgrdhyhtlnor", "unnmgrejgrdhyhtlnotakcfrumgcmv", + "unnmgrejgrdhyamkqdaoooxmoszrb", "unnmgrejgrdhyhtlnotakcfrumgcuv", "unnmgrejgrdhyhtlnotanswtp", + "unnmgrejgrdhyhtlnotakcfrumgcrt", "unnmgrejgrdhyhtlnotakcfrumgcsq", "unnmgrejgrdhyhtlnotakcfrumgcvc", + "unnmlitobgnug", "lxppiyzvjtvchghycpprppmwunh", "unnmgrejgrdhyhtlnotakcfrumgcj", "unnmgrejgrdhyhtlnotakcfrumgcxk", + "unxmlewoxqitppybjkpqyyvxuqn", "unnmgrejgrdhyhtlnotakcfrumgcfq", "unnmgrejgrdhyhtlnotakcfrumgcoh", + "unnmgrejgrdhyhmgb", "unnmgrejgrdhyhtlnotakcnkpeij", "unnmgrejgrdhyhtlnotakcfrumgcdv", + "unnmgrejgrdhyhtlnotakcfrumgccz", "unnmgrejgrdhyhtlnotakcfrumgctc", "unnmgrejgrdhyhtlnotakcfrumgcrk", + "unnmgrejgrdhyhtlnotakcfrumgcsy", "unnmgrejgrdhyhtlnotakcfrumgcwx", "unnmgrejgrdhyhtlnotakcfrumgcfy", + "unnmgrejgrhl", "unnmgrejgrdhyhtlnotakcfrumgcec", "unnmgrejgrdhyhtlnotakcfrumgcsd", + "unnmgrejgrdhyhtlnotakcfrumgcya", "unnmgrejgrdhyhtlnotagrwb", "unnmgrejgrdhyhtlnotakcfrumgcwp", + "unnmgrejgrdhyhtlnotakcfrumgcji", "unnmgrejgrdhyhtlnvtgmosuo", "unnmgrejgrdhyhtlnotakcfrumgcbf", + "unnmgrejgrdhyhtlnotakcfrumgcmf", "unnmgrejgrdhyhtlnotakcfrumgcwg", "unnmgrejgrdhyhtlnotakcfrumgcan", + "unnmgrejgrdhyhtlnotakcfrumgcdt", "unnmgrejgrdhyhtlnotakcfrumgcuz", "unnmgrejgrdhyhtlnotakcfrumgcep", + "unnmgrejgrdhyhtlnotakcfrumgctg", "unnmgylmgdwoutwckudw", "unnmgrejgrdhyhtlnotakcfrumgcvt", "hcxraxlhemowtugjk", + "unnmgrejgrdhyhtlnotakcfrumgchb", "unnmgrejgrdhyhtlnotaktleiptkz", "unnmgrejgrdhyhtlnotakcfrumgcr", + "unnmgrejgrdhyhtlnotakcfrumgcbp", "unnmgrejgrdhyhtlnotakcfrumgcxt", "unnmgrejgrdhyhtlnotakcfrumgcpy", + "unnmgrejgrdhyhtlnotakcfrumgcyh"])) diff --git a/Week_04/id_3/trie/LeetCode_720_3_v5.py b/Week_04/id_3/trie/LeetCode_720_3_v5.py new file mode 100644 index 00000000..fa2f896f --- /dev/null +++ b/Week_04/id_3/trie/LeetCode_720_3_v5.py @@ -0,0 +1,39 @@ +""" +在v4的基础上进一步优化 +按字母正序 字母长度倒序 +这样可以更加稳准狠的剪枝 +====== +真是又简单又高效…… +O(nlogn) +====== +打败了100%,值得纪念 +""" + + +class Solution: + def longestWord(self, words): + if not words: + return '' + words_set = set(words) + words.sort() + words.sort(key=len, reverse=True) + for word in words: + w = word + while w in words_set: + w = w[:-1] + + if len(w) == 0: + return word + + +s = Solution() +print(s.longestWord(["vsw", "vs", "zwu", "vsx", "nc", "o", "vswus", "orv", "imf", "i", "v", "zw", "vs"])) +print(s.longestWord(["w", "wo", "wor", "worl", "world"])) +print(s.longestWord(["a", "banana", "app", "appl", "ap", "apply", "apple"])) +print(s.longestWord(["e", "el", "ele", "elep", "eleph", "elepha", "elephan", "elephant"])) +print(s.longestWord(["ogz", "eyj", "e", "ey", "hmn", "v", "hm", "ogznkb", "ogzn", "hmnm", "eyjuo", "vuq", "ogznk", "og", "eyjuoi", "d"])) +print(s.longestWord(["m", "mo", "moc", "moch", "mocha", "l", "la", "lat", "latt", "latte", "c", "ca", "cat"])) +print(s.longestWord(["rac", "rs", "ra", "on", "r", "otif", "o", "onpdu", "rsf", "rs", "ot", "oti", "racy", "onpd"])) +print(s.longestWord( + ["ts", "e", "x", "pbhj", "opto", "xhigy", "erikz", "pbh", "opt", "erikzb", "eri", "erik", "xlye", "xhig", "optoj", + "optoje", "xly", "pb", "xhi", "x", "o"])) diff --git a/Week_04/id_3/trie/TrieTree.py b/Week_04/id_3/trie/TrieTree.py new file mode 100644 index 00000000..f421d20e --- /dev/null +++ b/Week_04/id_3/trie/TrieTree.py @@ -0,0 +1,26 @@ +import collections + + +class TrieTree: + + def __init__(self): + self.root = TrieNode() + + def add(self, word): + node = self.root + for w in word: + node = node.edges[w] + node.letter = w + node.is_word = True + + +class TrieNode: + + def __init__(self): + self.edges = collections.defaultdict(TrieNode) + self.letter = None + self.is_word = False + + +tree = TrieTree() +tree.add('hello') diff --git a/Week_04/id_30/LeetCode_169_030.cpp b/Week_04/id_30/LeetCode_169_030.cpp new file mode 100644 index 00000000..dffba74d --- /dev/null +++ b/Week_04/id_30/LeetCode_169_030.cpp @@ -0,0 +1,28 @@ +class Solution { +public: + int elementsCountInRange(vector& nums, int beg, int end, int num) + { + int count = 0; + for (int i = beg; i <= end; ++i) + { + if (nums[i] == num) ++count; + } + return count; + } + + int majorityElementInRange(vector& nums, int beg, int end) + { + if (beg == end) return nums[beg]; + int mid = beg + (end - beg) / 2; + int leftMajority = majorityElementInRange(nums, beg, mid); + int rightMajority = majorityElementInRange(nums, mid + 1, end); + if (leftMajority == rightMajority) return leftMajority; + int leftNum = elementsCountInRange(nums, beg, end, leftMajority); + int rightNum = elementsCountInRange(nums, beg, end, rightMajority); + return leftNum > rightNum ? leftMajority : rightMajority; + } + + int majorityElement(vector& nums) { + return majorityElementInRange(nums, 0, nums.size() - 1); + } +}; \ No newline at end of file diff --git a/Week_04/id_30/LeetCode_198_030.cpp b/Week_04/id_30/LeetCode_198_030.cpp new file mode 100644 index 00000000..c5b13608 --- /dev/null +++ b/Week_04/id_30/LeetCode_198_030.cpp @@ -0,0 +1,14 @@ +class Solution { +public: + int rob(vector& nums) { + int n = nums.size(); + int dp_i = 0, dp_pre_i = 0; + for (int i = 0; i < n; ++i) + { + int cur_dp_i = dp_i; + dp_i = max(dp_i, dp_pre_i + nums[i]); + dp_pre_i = cur_dp_i; + } + return dp_i; + } +}; \ No newline at end of file diff --git a/Week_04/id_30/LeetCode_309_030.cpp b/Week_04/id_30/LeetCode_309_030.cpp new file mode 100644 index 00000000..606ef5fc --- /dev/null +++ b/Week_04/id_30/LeetCode_309_030.cpp @@ -0,0 +1,15 @@ +class Solution { +public: + int maxProfit(vector& prices) { + int n = prices.size(); + int mpi_0 = 0, mpi_1 = INT_MIN, mp_pre_i_0 = 0; + for (int i = 0; i < n; ++i) + { + int cur_i_0 = mpi_0; + mpi_0 = max(mpi_0, mpi_1 + prices[i]); + mpi_1 = max(mpi_1, mp_pre_i_0 - prices[i]); + mp_pre_i_0 = cur_i_0; + } + return mpi_0; + } +}; \ No newline at end of file diff --git a/Week_04/id_30/LeetCode_455_030.cpp b/Week_04/id_30/LeetCode_455_030.cpp new file mode 100644 index 00000000..187a061d --- /dev/null +++ b/Week_04/id_30/LeetCode_455_030.cpp @@ -0,0 +1,13 @@ +class Solution { +public: + int findContentChildren(vector& g, vector& s) { + sort(g.begin(), g.end()); + sort(s.begin(), s.end()); + int i = 0; + for (int j = 0; i < g.size() && j < s.size(); ++j) + { + if (s[j] >= g[i]) ++i; + } + return i; + } +}; \ No newline at end of file diff --git a/Week_04/id_30/LeetCode_53_030.cpp b/Week_04/id_30/LeetCode_53_030.cpp new file mode 100644 index 00000000..a3daf6f0 --- /dev/null +++ b/Week_04/id_30/LeetCode_53_030.cpp @@ -0,0 +1,14 @@ +class Solution { +public: + int maxSubArray(vector& nums) { + if (nums.size() == 0) return 0; + int maxSum = nums[0]; + int sum = nums[0]; + for (int i = 1; i < nums.size(); ++i) + { + sum = max(nums[i], sum + nums[i]); + maxSum = max(sum, maxSum); + } + return maxSum; + } +}; \ No newline at end of file diff --git a/Week_04/id_30/LeetCode_720_030.cpp b/Week_04/id_30/LeetCode_720_030.cpp new file mode 100644 index 00000000..2b2e0fce --- /dev/null +++ b/Week_04/id_30/LeetCode_720_030.cpp @@ -0,0 +1,83 @@ +class Solution { +public: + class Trie + { + public: + Trie(vector& words) : m_words(words) + { + m_root = new TrieNode(0); + for (int i = 0; i < words.size(); ++i) + { + insert(words[i], i + 1); + } + } + + int getChildIndex(char c) { return c - 'a'; } + + void insert(string word, int i) + { + TrieNode* p = m_root; + for (char c : word) + { + int index = getChildIndex(c); + if (p->children[index] == nullptr) + { + p->children[index] = new TrieNode(c); + } + p = p->children[index]; + } + p->end = i; + } + + string bfs() + { + string resultWord; + queue nodeQueue; + nodeQueue.push(m_root); + while (!nodeQueue.empty()) + { + bool hasLongerWord = false; + for(int nodeCount = nodeQueue.size(); nodeCount > 0; --nodeCount) + { + TrieNode* node = nodeQueue.front(); + nodeQueue.pop(); + if (node == m_root || node->end > 0) + { + if (!hasLongerWord && node->end > 0) + { + resultWord = m_words[node->end - 1]; + hasLongerWord = true; + } + for (TrieNode* child : node->children) + { + if(child) nodeQueue.push(child); + } + } + } + } + return resultWord; + } + + private: + static const int ChildrenSize = 26; + class TrieNode + { + public: + TrieNode(char cc) : c(cc), end(0) + { + for (int i = 0; i < ChildrenSize; ++i) children[i] = nullptr; + } + char c; + unsigned int end; + TrieNode* children[ChildrenSize]; + }; + + TrieNode* m_root; + vector& m_words; + }; + + string longestWord(vector& words) { + Trie trie(words); + return trie.bfs(); + } +}; \ No newline at end of file diff --git a/Week_04/id_30/LeetCode_784_030.cpp b/Week_04/id_30/LeetCode_784_030.cpp new file mode 100644 index 00000000..fee3a813 --- /dev/null +++ b/Week_04/id_30/LeetCode_784_030.cpp @@ -0,0 +1,27 @@ +class Solution { +public: + vector permuationResults; + + vector letterCasePermutation(string S) { + permutateString(S, 0); + return permuationResults; + } + + void permutateString(string& S, int i) + { + if (i >= S.size()) + { + permuationResults.push_back(S); + return; + } + permutateString(S, i + 1); + if (isalpha(S[i])) + { + char prevChar = S[i]; + if (isupper(S[i])) S[i] = tolower(S[i]); + else S[i] = toupper(S[i]); + permutateString(S, i + 1); + S[i] = prevChar; + } + } +}; \ No newline at end of file diff --git a/Week_04/id_30/LeetCode_78_030.cpp b/Week_04/id_30/LeetCode_78_030.cpp new file mode 100644 index 00000000..51ee1ab7 --- /dev/null +++ b/Week_04/id_30/LeetCode_78_030.cpp @@ -0,0 +1,23 @@ +class Solution { +public: + vector> subsetsResult; + + vector> subsets(vector& nums) { + vector result; + permutateSubsets(nums, 0, result); + return subsetsResult; + } + + void permutateSubsets(vector& nums, int i, vector& result) + { + if (i >= nums.size()) + { + subsetsResult.push_back(result); + return; + } + permutateSubsets(nums, i + 1, result); + result.push_back(nums[i]); + permutateSubsets(nums, i + 1, result); + result.pop_back(); + } +}; \ No newline at end of file diff --git a/Week_04/id_33/Leetcode_46_33.java b/Week_04/id_33/Leetcode_46_33.java new file mode 100644 index 00000000..4da5fbd3 --- /dev/null +++ b/Week_04/id_33/Leetcode_46_33.java @@ -0,0 +1,27 @@ +/* + * @lc app=leetcode id=46 lang=java + * + * [46] Permutations + */ +class Solution { + public List> permute(int[] nums) { + List> result = new ArrayList<>(); + backTrace(nums, result, new ArrayList<>()); + return result; + } + + public void backTrace(int[] nums, List> result, List tempList){ + if(tempList.size() == nums.length){ + result.add(new ArrayList(tempList)); + return; + } + + for(int i = 0; i< nums.length; i++){ + if(tempList.contains(nums[i])) continue; + tempList.add(nums[i]); + backTrace(nums, result, tempList); + tempList.remove(tempList.size()-1); + } + } +} + diff --git a/Week_04/id_33/Leetcode_53_33.java b/Week_04/id_33/Leetcode_53_33.java new file mode 100644 index 00000000..68295e42 --- /dev/null +++ b/Week_04/id_33/Leetcode_53_33.java @@ -0,0 +1,17 @@ +/* + * @lc app=leetcode id=53 lang=java + * + * [53] Maximum Subarray + */ +class Solution { + public int maxSubArray(int[] nums) { + if(nums.length==0) return 0; + int maxSum = nums[0], sum = nums[0]; + for (int i = 1; i < nums.length; i++){ + sum = Math.max(nums[i], sum + nums[i]); + maxSum = Math.max(sum, maxSum); + } + return maxSum; + } +} + diff --git a/Week_04/id_33/Leetcode_62_33.java b/Week_04/id_33/Leetcode_62_33.java new file mode 100644 index 00000000..49a54d19 --- /dev/null +++ b/Week_04/id_33/Leetcode_62_33.java @@ -0,0 +1,19 @@ +/* + * @lc app=leetcode id=62 lang=java + * + * [62] Unique Paths + */ +class Solution { + public int uniquePaths(int m, int n) { + int[][] dp = new int[n][m]; + for (int i = 0; i < n; i++) dp[i][0] = 1; + for (int i = 0; i < m; i++) dp[0][i] = 1; + for (int i = 1; i < n; i++){ + for (int j = 1; j < m; j++){ + dp[i][j] = dp[i-1][j] + dp[i][j-1]; + } + } + return dp[n-1][m-1]; + } +} + diff --git a/Week_04/id_33/Leetcode_70_33.java b/Week_04/id_33/Leetcode_70_33.java new file mode 100644 index 00000000..64f1210b --- /dev/null +++ b/Week_04/id_33/Leetcode_70_33.java @@ -0,0 +1,18 @@ +/* + * @lc app=leetcode id=70 lang=java + * + * [70] Climbing Stairs + */ +class Solution { + public int climbStairs(int n) { + if (n == 1) return 1; + int[] dp = new int[n + 1]; + dp[1] = 1; + dp[2] = 2; + for (int i = 3; i <= n; i++) { + dp[i] = dp[i - 1] + dp[i - 2]; + } + return dp[n]; + } +} + diff --git a/Week_04/id_33/Leetcode_714_33.java b/Week_04/id_33/Leetcode_714_33.java new file mode 100644 index 00000000..fdf26e8b --- /dev/null +++ b/Week_04/id_33/Leetcode_714_33.java @@ -0,0 +1,21 @@ +/* + * @lc app=leetcode id=714 lang=java + * + * [714] Best Time to Buy and Sell Stock with Transaction Fee + */ +class Solution { + public int maxProfit(int[] prices, int fee) { + if(prices.length <= 1) return 0; + int profit = 0, min = prices[0]; + for(int i = 0;i < prices.length;i++){ + if(prices[i] < min){ + min = prices[i]; + }else if(prices[i] > min + fee){ + profit += prices[i] - min - fee; + min = prices[i] - fee; + } + } + return profit; + } +} + diff --git a/Week_04/id_35/Leetcode_169_35.java b/Week_04/id_35/Leetcode_169_35.java new file mode 100644 index 00000000..e443734c --- /dev/null +++ b/Week_04/id_35/Leetcode_169_35.java @@ -0,0 +1,107 @@ +package com.leecode.week04; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; + +/** + * 求众数 给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。 + * + * 你可以假设数组是非空的,并且给定的数组总是存在众数。 + * + * @author xuemin.zhu + */ +public class Leetcode_169_35 { + + public static void main(String[] args) { + + Leetcode_169_35 lc = new Leetcode_169_35(); + //System.out.println(lc.majorityElement(new int[]{3, 2, 3})); + System.out.println(lc.majorityElement(new int[]{2, 2, 1, 1, 1, 2, 2})); + System.out.println(lc.majorityElement(new int[]{1})); + System.out.println(lc.majorityElement(new int[]{2,2})); + System.out.println(lc.majorityElement(new int[]{6,5,5})); + + } + + /** + * Boyer-Moore: + * 思路说明:把所有数据都看成是众数和非众数两类,然后就像玩消消乐那样一个碰一个去抵消掉 这里是不一样的抵消掉 + * 因为众数是数量比较多的,把全部非众数灭掉之后还有剩,剩下的就是我们要找的众数了 + */ + public int majorityElement(int[] nums) { + + //题目中保证要有众数,两个元素的情况只能是两个一样的了 + if (nums.length == 1 || nums.length == 2) { + return nums[0]; + } + + int majorIndex = 0;//首先选择0作为众数 + int majorCount = 0;//当前众数的计数个数 + for (int i = 0; i < nums.length; i++) { + if (nums[i] == nums[majorIndex]) { + majorCount++; + } else { + majorCount--; + } + + if (majorCount == 0) { + //当前众数是0之后需要重新选举新的众数,i 会在经过majorCount时majorCount会变成1 + majorIndex = i + 1; + + } + } + + return nums[majorIndex]; + } + + + /** + * 思路1:最直接的搞法就是先计算出每个数字出现的次数,再看看是不是超过n/2 这里想试试jdk8中新式写法^^ + */ + + public int majorityElement_v1(int[] nums) { + + Map map = Arrays.stream(nums) + .mapToObj(num -> new Tuple(String.valueOf(num), num)) + .collect(Collectors.groupingBy(Tuple::getKey, Collectors.counting())); + + List> entrys = map.entrySet().stream() + .filter(s -> s.getValue() > nums.length / 2).collect(Collectors.toList()); + + if (entrys.isEmpty() || entrys.size() != 1) { + return -1; + } + + return Integer.valueOf(entrys.get(0).getKey()); + } + + static class Tuple { + + private String key; + private Integer val; + + public Tuple(String key, Integer val) { + this.key = key; + this.val = val; + } + + public Integer getVal() { + return val; + } + + public void setVal(Integer val) { + this.val = val; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + } +} diff --git a/Week_04/id_35/Leetcode_198_35.java b/Week_04/id_35/Leetcode_198_35.java new file mode 100644 index 00000000..4bf7a11d --- /dev/null +++ b/Week_04/id_35/Leetcode_198_35.java @@ -0,0 +1,58 @@ +package com.leecode.week04; + +/** + * 打家劫舍 + * 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 + * + * 给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。 + * + */ +public class Leetcode_198_35 { + + public static void main(String[] args) { + Leetcode_198_35 lc=new Leetcode_198_35(); + + System.out.println(lc.rob(new int[]{1,2,3,1})); + + System.out.println(lc.rob(new int[]{2,9,7,3,1})); + + + } + + /** + * 相邻的房间不能偷,转换成我在当前的一套房间的行为 + * 1.前一个房间我没有偷,那么当前的房间我可以偷 + * 2.前一个房间我是偷了的,当前的房间就不能偷了 + * 所以偷到当前的房间的最高金额就是在两种方案中选择最高的 + * + * dp[i]=max(dp[i-1]+0),dp[i-2]+num[i] + * + * @param nums + * @return + */ + public int rob(int[] nums) { + int[] dp=new int[nums.length]; + + if(nums==null||nums.length==0){ + return 0; + } + + if(nums.length==1){ + return nums[0]; + } + + if(nums.length==2){ + return Math.max(nums[0],nums[1]); + } + + + dp[0]=nums[0]; + dp[1]=Math.max(dp[0],nums[1]);//第一次偷了就是dp[0],第一次不偷0+第二次偷num[1],两种情况找个比较大的 + + for(int i=2;i=3的时候都有这种关系 dp[n]=dp[n-1]+d[n-2],表示的是剩下一步走到N的情况和剩下走两步走到N的情况,所以要走到N步就是前面两者的和 + */ + public int climbStairs(int n) { + int oneStep = 1; + int twoStep = 2; + + switch (n) { + case 1: + return oneStep; + case 2: + return twoStep; + default: + int[] dp = new int[n]; + dp[0] = oneStep; + dp[1] = twoStep; + for (int i = 2; i < n; i++) { + dp[i] = dp[i - 1] + dp[i - 2]; + } + return dp[n - 1]; + } + + + } +} diff --git a/Week_04/id_36/LeetCode_169_36.py b/Week_04/id_36/LeetCode_169_36.py new file mode 100644 index 00000000..2ef99fdb --- /dev/null +++ b/Week_04/id_36/LeetCode_169_36.py @@ -0,0 +1,129 @@ +# +# @lc app=leetcode.cn id=169 lang=python3 +# +# [169] 求众数 +# +# https://leetcode-cn.com/problems/majority-element/description/ +# +# algorithms +# Easy (59.73%) +# Likes: 259 +# Dislikes: 0 +# Total Accepted: 49.1K +# Total Submissions: 82.1K +# Testcase Example: '[3,2,3]' +# +# 给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。 +# +# 你可以假设数组是非空的,并且给定的数组总是存在众数。 +# +# 示例 1: +# +# 输入: [3,2,3] +# 输出: 3 +# +# 示例 2: +# +# 输入: [2,2,1,1,1,2,2] +# 输出: 2 +# +# + +# # 暴力法 +# class Solution: +# def majorityElement(self, nums: List[int]) -> int: +# majority_num = len(nums)//2 + +# for num in nums: +# count = 0 +# for n in nums: +# if n == num: +# count += 1 + +# if count > majority_num: +# return num + +# return -1 + +# # 哈希表-1 +# class Solution: +# def majorityElement(self, nums: List[int]) -> int: +# if not nums or len(nums) < 1: +# return 0 + +# counts = {} + +# for num in nums: +# if not counts.get(num): +# counts[num] = 1 +# else: +# counts[num] += 1 + +# max_value = 0 +# majority = 0 + +# for key, value in counts.items(): +# if value > max_value: +# max_value = value +# majority = key + +# return majority + +# # 哈希表-2 +# class Solution: +# def majorityElement(self, nums: List[int]) -> int: +# import collections +# counts = collections.Counter(nums) +# return max(counts.keys(), key = counts.get) + +# # 排序 +# class Solution: +# def majorityElement(self, nums: List[int]) -> int: +# nums_len = len(nums) +# if not nums or nums_len < 1: +# return 0 + +# nums.sort() +# return nums[nums_len // 2] + +# # 分治 +# class Solution: +# def majorityElement(self, nums: List[int]) -> int: +# def majority_element_rec(low, high): +# if low == high: +# return nums[low] + +# middle = low + (high - low) // 2 +# left = majority_element_rec(low, middle) +# right = majority_element_rec(middle + 1, high) + +# if left == right: +# return left + +# # left_count = sum(1 for i in range(low, high + 1) if nums[i] == left) +# # right_count = sum(1 for i in range(low, high + 1) if nums[i] == right) +# left_count = 0 +# right_count = 0 +# for i in range(low, high + 1): +# if nums[i] == left: +# left_count += 1 +# elif nums[i] == right: +# right_count += 1 + +# return left if left_count > right_count else right + +# return majority_element_rec(0, len(nums) - 1) + +# Boyer-Moore 投票算法 +class Solution: + def majorityElement(self, nums: List[int]) -> int: + count = 0 + candidate = None + + for num in nums: + if count == 0: + candidate = num + count += (1 if num == candidate else -1) + + return candidate + diff --git a/Week_04/id_36/LeetCode_455_36.py b/Week_04/id_36/LeetCode_455_36.py new file mode 100644 index 00000000..4b7b0edf --- /dev/null +++ b/Week_04/id_36/LeetCode_455_36.py @@ -0,0 +1,89 @@ +# +# @lc app=leetcode.cn id=455 lang=python3 +# +# [455] 分发饼干 +# +# https://leetcode-cn.com/problems/assign-cookies/description/ +# +# algorithms +# Easy (49.91%) +# Likes: 91 +# Dislikes: 0 +# Total Accepted: 10.7K +# Total Submissions: 21.4K +# Testcase Example: '[1,2,3]\n[1,1]' +# +# 假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i ,都有一个胃口值 gi +# ,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j ,都有一个尺寸 sj 。如果 sj >= gi ,我们可以将这个饼干 j 分配给孩子 i +# ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。 +# +# 注意: +# +# 你可以假设胃口值为正。 +# 一个小朋友最多只能拥有一块饼干。 +# +# 示例 1: +# +# +# 输入: [1,2,3], [1,1] +# +# 输出: 1 +# +# 解释: +# 你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。 +# 虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。 +# 所以你应该输出1。 +# +# +# 示例 2: +# +# +# 输入: [1,2], [1,2,3] +# +# 输出: 2 +# +# 解释: +# 你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。 +# 你拥有的饼干数量和尺寸都足以让所有孩子满足。 +# 所以你应该输出2. +# +# +# +# class Solution: +# def findContentChildren(self, g: List[int], s: List[int]) -> int: +# g.sort() +# s.sort() + +# gi = 0 +# si = 0 +# res = 0 + +# while gi < len(g) and si < len(s): +# if s[si] >= g[gi]: +# si += 1 +# gi += 1 +# res += 1 +# else: +# si += 1 + +# return res + +class Solution: + def findContentChildren(self, g: List[int], s: List[int]) -> int: + import heapq + + heapq.heapify(g) + heapq.heapify(s) + + res = 0 + + while g and s: + if s[0] >= g[0]: + heapq.heappop(g) + heapq.heappop(s) + res += 1 + else: + heapq.heappop(s) + + return res + diff --git a/Week_04/id_36/LeetCode_46_36.py b/Week_04/id_36/LeetCode_46_36.py new file mode 100644 index 00000000..7c864673 --- /dev/null +++ b/Week_04/id_36/LeetCode_46_36.py @@ -0,0 +1,48 @@ +# +# @lc app=leetcode.cn id=46 lang=python3 +# +# [46] 全排列 +# +# https://leetcode-cn.com/problems/permutations/description/ +# +# algorithms +# Medium (69.78%) +# Likes: 294 +# Dislikes: 0 +# Total Accepted: 29.2K +# Total Submissions: 41.9K +# Testcase Example: '[1,2,3]' +# +# 给定一个没有重复数字的序列,返回其所有可能的全排列。 +# +# 示例: +# +# 输入: [1,2,3] +# 输出: +# [ +# ⁠ [1,2,3], +# ⁠ [1,3,2], +# ⁠ [2,1,3], +# ⁠ [2,3,1], +# ⁠ [3,1,2], +# ⁠ [3,2,1] +# ] +# +# +class Solution: + def permute(self, nums: List[int]) -> List[List[int]]: + def backtrack(first = 0): + if first == n: + output.append(nums[:]) + + for i in range(first, n): + nums[first], nums[i] = nums[i], nums[first] + backtrack(first + 1) + nums[first], nums[i] = nums[i], nums[first] + + n = len(nums) + output = [] + backtrack() + + return output + diff --git a/Week_04/id_36/LeetCode_53_36.py b/Week_04/id_36/LeetCode_53_36.py new file mode 100644 index 00000000..6bc83058 --- /dev/null +++ b/Week_04/id_36/LeetCode_53_36.py @@ -0,0 +1,88 @@ +# +# @lc app=leetcode.cn id=53 lang=python3 +# +# [53] 最大子序和 +# +# https://leetcode-cn.com/problems/maximum-subarray/description/ +# +# algorithms +# Easy (45.55%) +# Likes: 1009 +# Dislikes: 0 +# Total Accepted: 65.3K +# Total Submissions: 142.9K +# Testcase Example: '[-2,1,-3,4,-1,2,1,-5,4]' +# +# 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 +# +# 示例: +# +# 输入: [-2,1,-3,4,-1,2,1,-5,4], +# 输出: 6 +# 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。 +# +# +# 进阶: +# +# 如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。 +# +# # 暴力法 +# class Solution: +# def maxSubArray(self, nums: List[int]) -> int: +# n = len(nums) +# if n <= 0: +# return 0 + +# tmp = nums[0] +# max_value = tmp + +# for i in range(1, n): +# tmp = tmp + nums[i] if tmp > 0 else nums[i] +# max_value = max(max_value, tmp) + +# return max_value + +# class Solution: +# def maxSubArray(self, nums: List[int]) -> int: +# n = len(nums) +# if n <= 0: +# return 0 +# elif n == 1: +# return nums[0] + +# max_value = nums[0] +# tmp = 0 + +# for num in nums: +# tmp = tmp + num if tmp > 0 else num +# max_value = max(max_value, tmp) + +# return max_value + +# 分治法 +class Solution: + def maxSubArray(self, nums: List[int]) -> int: + n = len(nums) + if n <= 0: + return 0 + elif n == 1: + return nums[0] + + middle = n // 2 + max_left = self.maxSubArray(nums[0 : middle]) + max_right = self.maxSubArray(nums[middle : n]) + + tmp = 0 + max_le = nums[middle - 1] + for i in range(middle - 1, -1, -1): + tmp += nums[i] + max_le = max(max_le, tmp) + + max_ri = nums[middle] + tmp = 0 + for i in range(middle, n): + tmp += nums[i] + max_ri = max(max_ri, tmp) + + return max(max_left, max_right, max_le + max_ri) + diff --git a/Week_04/id_36/LeetCode_70_36.py b/Week_04/id_36/LeetCode_70_36.py new file mode 100644 index 00000000..25c3ec37 --- /dev/null +++ b/Week_04/id_36/LeetCode_70_36.py @@ -0,0 +1,56 @@ +# +# @lc app=leetcode.cn id=70 lang=python3 +# +# [70] 爬楼梯 +# +# https://leetcode-cn.com/problems/climbing-stairs/description/ +# +# algorithms +# Easy (45.72%) +# Likes: 518 +# Dislikes: 0 +# Total Accepted: 55.5K +# Total Submissions: 121.4K +# Testcase Example: '2' +# +# 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 +# +# 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? +# +# 注意:给定 n 是一个正整数。 +# +# 示例 1: +# +# 输入: 2 +# 输出: 2 +# 解释: 有两种方法可以爬到楼顶。 +# 1. 1 阶 + 1 阶 +# 2. 2 阶 +# +# 示例 2: +# +# 输入: 3 +# 输出: 3 +# 解释: 有三种方法可以爬到楼顶。 +# 1. 1 阶 + 1 阶 + 1 阶 +# 2. 1 阶 + 2 阶 +# 3. 2 阶 + 1 阶 +# +# +# +class Solution: + def climbStairs(self, n: int) -> int: + def climb_stairs(i, n, m_dict): + if i > n: + return 0 + elif i == n: + return 1 + + if m_dict.get(i) and m_dict.get(i) > 0: + return m_dict.get(i) + + m_dict[i] = climb_stairs(i + 1, n, m_dict) + climb_stairs(i + 2, n, m_dict) + return m_dict[i] + + return climb_stairs(0, n, {}) + diff --git a/Week_04/id_36/LeetCode_720_36.py b/Week_04/id_36/LeetCode_720_36.py new file mode 100644 index 00000000..401b8cc8 --- /dev/null +++ b/Week_04/id_36/LeetCode_720_36.py @@ -0,0 +1,73 @@ +# +# @lc app=leetcode.cn id=720 lang=python3 +# +# [720] 词典中最长的单词 +# +# https://leetcode-cn.com/problems/longest-word-in-dictionary/description/ +# +# algorithms +# Easy (42.64%) +# Likes: 36 +# Dislikes: 0 +# Total Accepted: 2.6K +# Total Submissions: 6.2K +# Testcase Example: '["w","wo","wor","worl","world"]' +# +# +# 给出一个字符串数组words组成的一本英语词典。从中找出最长的一个单词,该单词是由words词典中其他单词逐步添加一个字母组成。若其中有多个可行的答案,则返回答案中字典序最小的单词。 +# +# 若无答案,则返回空字符串。 +# +# 示例 1: +# +# +# 输入: +# words = ["w","wo","wor","worl", "world"] +# 输出: "world" +# 解释: +# 单词"world"可由"w", "wo", "wor", 和 "worl"添加一个字母组成。 +# +# +# 示例 2: +# +# +# 输入: +# words = ["a", "banana", "app", "appl", "ap", "apply", "apple"] +# 输出: "apple" +# 解释: +# "apply"和"apple"都能由词典中的单词组成。但是"apple"得字典序小于"apply"。 +# +# +# 注意: +# +# +# 所有输入的字符串都只包含小写字母。 +# words数组长度范围为[1,1000]。 +# words[i]的长度范围为[1,30]。 +# +# +# +# class Solution: +# def longestWord(self, words: List[str]) -> str: +# ans = "" +# word_set = set(words) +# for word in words: +# word_len = len(word) +# ans_len = len(ans) +# if word_len > ans_len or word_len == ans_len and word < ans: +# if all(word[:k] in word_set for k in range(1, word_len)): +# ans = word + +# return ans + +class Solution: + def longestWord(self, words: List[str]) -> str: + ans = "" + word_set = set(words) + words.sort(key = lambda c : (-(len(c)), c)) + for word in words: + if all(word[:k] in word_set for k in range(1, len(word))): + return word + + return "" + diff --git a/Week_04/id_36/LeetCode_77_36.py b/Week_04/id_36/LeetCode_77_36.py new file mode 100644 index 00000000..a500827e --- /dev/null +++ b/Week_04/id_36/LeetCode_77_36.py @@ -0,0 +1,46 @@ +# +# @lc app=leetcode.cn id=77 lang=python3 +# +# [77] 组合 +# +# https://leetcode-cn.com/problems/combinations/description/ +# +# algorithms +# Medium (68.76%) +# Likes: 129 +# Dislikes: 0 +# Total Accepted: 13.2K +# Total Submissions: 19.1K +# Testcase Example: '4\n2' +# +# 给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。 +# +# 示例: +# +# 输入: n = 4, k = 2 +# 输出: +# [ +# ⁠ [2,4], +# ⁠ [3,4], +# ⁠ [2,3], +# ⁠ [1,2], +# ⁠ [1,3], +# ⁠ [1,4], +# ] +# +# +class Solution: + def combine(self, n: int, k: int) -> List[List[int]]: + def backtrack(first = 1, curr = []): + if len(curr) == k: + output.append(curr[:]) + + for i in range(first, n + 1): + curr.append(i) + backtrack(i + 1, curr) + curr.pop() + + output = [] + backtrack() + return output + diff --git a/Week_04/id_36/LeetCode_78_36.py b/Week_04/id_36/LeetCode_78_36.py new file mode 100644 index 00000000..9b116983 --- /dev/null +++ b/Week_04/id_36/LeetCode_78_36.py @@ -0,0 +1,51 @@ +# +# @lc app=leetcode.cn id=78 lang=python3 +# +# [78] 子集 +# +# https://leetcode-cn.com/problems/subsets/description/ +# +# algorithms +# Medium (73.91%) +# Likes: 268 +# Dislikes: 0 +# Total Accepted: 23.5K +# Total Submissions: 31.8K +# Testcase Example: '[1,2,3]' +# +# 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。 +# +# 说明:解集不能包含重复的子集。 +# +# 示例: +# +# 输入: nums = [1,2,3] +# 输出: +# [ +# ⁠ [3], +# [1], +# [2], +# [1,2,3], +# [1,3], +# [2,3], +# [1,2], +# [] +# ] +# +# +class Solution: + def subsets(self, nums: List[int]) -> List[List[int]]: + n = len(nums) + if n == 0: + return [] + + res = [] + + def backtrack(i, tmp): + res.append(tmp) + for j in range(i, n): + backtrack(j + 1, tmp + [nums[j]]) + + backtrack(0, []) + return res + diff --git a/Week_04/id_37/LeetCode_455_037.md b/Week_04/id_37/LeetCode_455_037.md new file mode 100644 index 00000000..9493d0de --- /dev/null +++ b/Week_04/id_37/LeetCode_455_037.md @@ -0,0 +1,38 @@ +import java.util.Arrays; + +/// 455. Assign Cookies +/// https://leetcode.com/problems/assign-cookies/description/ +/// 先尝试满足最贪心的小朋友 +/// 时间复杂度: O(nlogn) +/// 空间复杂度: O(1) +public class Solution { + + public int findContentChildren(int[] g, int[] s) { + + Arrays.sort(g); + Arrays.sort(s); + + int gi = g.length - 1, si = s.length - 1; + int res = 0; + while(gi >= 0 && si >= 0){ + if(s[si] >= g[gi]){ + res ++; + si --; + } + gi --; + } + + return res; + } + + public static void main(String[] args) { + + int g1[] = {1, 2, 3}; + int s1[] = {1, 1}; + System.out.println((new Solution()).findContentChildren(g1, s1)); + + int g2[] = {1, 2}; + int s2[] = {1, 2, 3}; + System.out.println((new Solution()).findContentChildren(g2, s2)); + } +} \ No newline at end of file diff --git a/Week_04/id_37/LeetCode_51_037.md b/Week_04/id_37/LeetCode_51_037.md new file mode 100644 index 00000000..0f2679e8 --- /dev/null +++ b/Week_04/id_37/LeetCode_51_037.md @@ -0,0 +1,82 @@ +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.ArrayList; + +/// 51. N-Queens +/// https://leetcode.com/problems/n-queens/description/ +/// 时间复杂度: O(n^n) +/// 空间复杂度: O(n) +public class Solution { + + private boolean[] col; + private boolean[] dia1; + private boolean[] dia2; + private ArrayList> res; + + public List> solveNQueens(int n) { + + res = new ArrayList>(); + col = new boolean[n]; + dia1 = new boolean[2 * n - 1]; + dia2 = new boolean[2 * n - 1]; + + LinkedList row = new LinkedList(); + putQueen(n, 0, row); + + return res; + } + + // 尝试在一个n皇后问题中, 摆放第index行的皇后位置 + private void putQueen(int n, int index, LinkedList row){ + + if(index == n){ + res.add(generateBoard(n, row)); + return; + } + + for(int i = 0 ; i < n ; i ++) + // 尝试将第index行的皇后摆放在第i列 + if(!col[i] && !dia1[index + i] && !dia2[index - i + n - 1]){ + row.addLast(i); + col[i] = true; + dia1[index + i] = true; + dia2[index - i + n - 1] = true; + putQueen(n, index + 1, row); + col[i] = false; + dia1[index + i] = false; + dia2[index - i + n - 1] = false; + row.removeLast(); + } + + return; + } + + private List generateBoard(int n, LinkedList row){ + + assert row.size() == n; + + ArrayList board = new ArrayList(); + for(int i = 0 ; i < n ; i ++){ + char[] charArray = new char[n]; + Arrays.fill(charArray, '.'); + charArray[row.get(i)] = 'Q'; + board.add(new String(charArray)); + } + return board; + } + + private static void printBoard(List board){ + for(String s: board) + System.out.println(s); + System.out.println(); + } + + public static void main(String[] args) { + + int n = 4; + List> res = (new Solution()).solveNQueens(n); + for(List board: res) + printBoard(board); + } +} \ No newline at end of file diff --git a/Week_04/id_37/NOTE.md b/Week_04/id_37/NOTE.md index 107ea7d6..aab753de 100644 --- a/Week_04/id_37/NOTE.md +++ b/Week_04/id_37/NOTE.md @@ -1 +1,13 @@ # 学习笔记 +## 分配饼干的学习笔记 +给一个孩子的饼干应当尽量小又能满足该孩子,这样大饼干就能拿来给满足度比较大的孩子。因为最小的孩子最容易得到满足,所以先满足最小的孩子。 + +证明:假设在某次选择中,贪心策略选择给当前满足度最小的孩子分配第 m 个饼干,第 m 个饼干为可以满足该孩子的最小饼干。假设存在一种最优策略,给该孩子分配第 n 个饼干,并且 m < n。我们可以发现,经过这一轮分配,贪心策略分配后剩下的饼干一定有一个比最优策略来得大。因此在后续的分配中,贪心策略一定能满足更多的孩子。也就是说不存在比贪心策略更优的策略,即贪心策略就是最优策略。 + +## N-Queens问题笔记 +一行一行地摆放,在确定一行中的那个皇后应该摆在哪一列时,需要用三个标记数组来确定某一列是否合法,这三个标记数组分别为:列标记数组、45 度对角线标记数组和 135 度对角线标记数组。 + +45 度对角线标记数组的长度为 2 * n - 1,(r, c) 的位置所在的数组下标为 r + c。 +135 度对角线标记数组的长度也是 2 * n - 1,(r, c) 的位置所在的数组下标为 n - 1 - (r - c)。 + + diff --git a/Week_04/id_38/LeetCode_169_038.java b/Week_04/id_38/LeetCode_169_038.java new file mode 100644 index 00000000..c556f19b --- /dev/null +++ b/Week_04/id_38/LeetCode_169_038.java @@ -0,0 +1,32 @@ +/* + * @lc app=leetcode.cn id=169 lang=java + * + * [169] 求众数 + */ + +class LeetCode_169_038 { + + public int majorityElement(int[] nums) { + Arrays.sort(nums); + return nums[nums.length/2]; + } + + public int majorityElement2(int[] nums) { + int majorityCount = nums.length / 2; + + Map countMap = new HashMap(); + for (int num : nums) { + if (countMap.get(num) != null) { + countMap.put(num, countMap.get(num) + 1); + } else { + countMap.put(num, 1); + } + + if (countMap.get(num) > majorityCount) { + return num; + } + } + + return -1; + } +} diff --git a/Week_04/id_38/LeetCode_455_038.java b/Week_04/id_38/LeetCode_455_038.java new file mode 100644 index 00000000..57684879 --- /dev/null +++ b/Week_04/id_38/LeetCode_455_038.java @@ -0,0 +1,37 @@ +/* + * @lc app=leetcode.cn id=455 lang=java + * + * [455] 分发饼干 + */ +class LeetCode_455_038 { + public int findContentChildren(int[] g, int[] s) { + Arrays.sort(g); + Arrays.sort(s); + int count = 0; + int i = 0, j = 0; + while (i < g.length && j < s.length) { + if (g[i] <= s[j]) { + i++; + j++; + count++; + } else { + j++; + } + } + return count; + } + + public int findContentChildren2(int[] g, int[] s) { + Arrays.sort(g); + Arrays.sort(s); + int i = 0, j = 0; + int l1 = g.length, l2 = s.length; + while (i < l1 && j < l2) { + if (g[i] <= s[j]) { + i++; + } + j++; + } + return i; + } +} diff --git a/Week_04/id_38/LeetCode_51_038.java b/Week_04/id_38/LeetCode_51_038.java new file mode 100644 index 00000000..256aa8cc --- /dev/null +++ b/Week_04/id_38/LeetCode_51_038.java @@ -0,0 +1,76 @@ +/* + * @lc app=leetcode.cn id=51 lang=java + * + * [51] N皇后 + */ + +class LeetCode_51_038 { + + int rows[]; + // "hill" diagonals + int hills[]; + // "dale" diagonals + int dales[]; + int n; + // output + List> output = new ArrayList(); + // queens positions + int queens[]; + + public boolean isNotUnderAttack(int row, int col) { + int res = rows[col] + hills[row - col + 2 * n] + dales[row + col]; + return (res == 0) ? true : false; + } + + public void placeQueen(int row, int col) { + queens[row] = col; + rows[col] = 1; + hills[row - col + 2 * n] = 1; // "hill" diagonals + dales[row + col] = 1; //"dale" diagonals + } + + public void removeQueen(int row, int col) { + queens[row] = 0; + rows[col] = 0; + hills[row - col + 2 * n] = 0; + dales[row + col] = 0; + } + + public void addSolution() { + List solution = new ArrayList(); + for (int i = 0; i < n; ++i) { + int col = queens[i]; + StringBuilder sb = new StringBuilder(); + for(int j = 0; j < col; ++j) sb.append("."); + sb.append("Q"); + for(int j = 0; j < n - col - 1; ++j) sb.append("."); + solution.add(sb.toString()); + } + output.add(solution); + } + + public void backtrack(int row) { + for (int col = 0; col < n; col++) { + if (isNotUnderAttack(row, col)) { + placeQueen(row, col); + // if n queens are already placed + if (row + 1 == n) addSolution(); + // if not proceed to place the rest + else backtrack(row + 1); + // backtrack + removeQueen(row, col); + } + } + } + + public List> solveNQueens(int n) { + this.n = n; + rows = new int[n]; + hills = new int[4 * n - 1]; + dales = new int[2 * n - 1]; + queens = new int[n]; + + backtrack(0); + return output; + } +} diff --git a/Week_04/id_38/LeetCode_70_038.java b/Week_04/id_38/LeetCode_70_038.java new file mode 100644 index 00000000..4a6997c9 --- /dev/null +++ b/Week_04/id_38/LeetCode_70_038.java @@ -0,0 +1,35 @@ +/* + * @lc app=leetcode.cn id=70 lang=java + * + * [70] 爬楼梯 + */ + +class LeetCode_70_038 { + + public int climbStairs(int n) { + if (n == 1){ + return 1; + } + int[] dp = new int[n + 1]; + dp[1] = 1; + dp[2] = 2; + for (int i = 3; i <= n; i++){ + dp[i] = dp[i -1] + dp[i - 2]; + } + return dp[n]; + } + + public int climbStairs2(int n) { + return climb_Stairs(0, n); + } + + public int climb_Stairs(int i, int n) { + if (i > n) { + return 0; + } + if (i == n) { + return 1; + } + return climb_Stairs(i + 1, n) + climb_Stairs(i + 2, n); + } +} diff --git a/Week_04/id_38/LeetCode_720_038.java b/Week_04/id_38/LeetCode_720_038.java new file mode 100644 index 00000000..6bb3af5e --- /dev/null +++ b/Week_04/id_38/LeetCode_720_038.java @@ -0,0 +1,91 @@ +/* + * @lc app=leetcode.cn id=720 lang=java + * + * [720] 词典中最长的单词 + */ + +class LeetCode_720_038 { + + public String longestWord(String[] words) { + Set s = new HashSet<>(); + for(String word : words) + s.add(word); + int ml = 0; + String mw = ""; + for(String w : words){ + if(w.length() < ml) continue; + if(w.length() == ml && w.compareTo(mw) >= 0) continue; + int n = w.length(); + boolean flag = true; + for(int i = 1; i < n; i++){ + if(!s.contains(w.substring(0, i))){ + flag = false; + break; + } + } + if(flag){ + ml = w.length(); + mw = w; + } + } + + return mw; + } + + + //#endregion + private static final int R = 26; + private TrieNode root; + + private static class TrieNode { + private final TrieNode[] children; + private String word; + + private TrieNode() { + children = new TrieNode[R]; + word = null; + } + } + + private void insertWord(String word) { + int len = word.length(); + TrieNode curr = root; + char c; + int idx; + for (int i = 0; i < len; ++i) { + c = word.charAt(i); + idx = c - 'a'; + + if (curr.children[idx] == null) { + curr.children[idx] = new TrieNode(); + } + + curr = curr.children[idx]; + } + + curr.word = word; + } + + private String findLongestWord(TrieNode root) { + String rst = root.word == null ? "" : root.word; + for (TrieNode child : root.children) { + if (child == null || child.word == null) continue; + String s = findLongestWord(child); + if (s.length() > rst.length()) rst = s; + } + return rst; + } + + public String longestWord2(String[] words) { + // initialize a new trie + root = new TrieNode(); + + // construct the trie based on input dictionary words + for (String word : words) { + insertWord(word); + } + + // find the longest dictionary word in this trie according to given rules + return findLongestWord(root); + } +} diff --git a/Week_04/id_38/LeetCode_784_038.java b/Week_04/id_38/LeetCode_784_038.java new file mode 100644 index 00000000..0c81d770 --- /dev/null +++ b/Week_04/id_38/LeetCode_784_038.java @@ -0,0 +1,32 @@ +/* + * @lc app=leetcode.cn id=784 lang=java + * + * [784] 字母大小写全排列 + */ + +class LeetCode_784_038 { + public List letterCasePermutation(String S) { + List ans = new ArrayList<>(); + StringBuilder root = new StringBuilder(S); + dfs(ans, root, 0); + return ans; + } + + private void dfs(List ans, StringBuilder root, int index) { + if (index == root.length()) { + ans.add(root.toString()); + return; + } + char c = root.charAt(index); + if ('a' <= c && c <= 'z') { + root.setCharAt(index, (char) (c - 32)); + dfs(ans, root, index + 1); + root.setCharAt(index, c); + } else if ('A' <= c && c <= 'Z') { + root.setCharAt(index, (char) (c + 32)); + dfs(ans, root, index + 1); + root.setCharAt(index, c); + } + dfs(ans, root, index + 1); + } +} diff --git a/Week_04/id_39/LeetCode_309_39.js b/Week_04/id_39/LeetCode_309_39.js new file mode 100644 index 00000000..1e81efbc --- /dev/null +++ b/Week_04/id_39/LeetCode_309_39.js @@ -0,0 +1,15 @@ +/** + * @param {number[]} prices + * @return {number} + * https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/ + * 只考虑前一天 + */ +var maxProfit = function(prices) { + let sell = [0], buy = [-prices[0]], cool = [0]; + for (let i = 1; i < prices.length; i++) { + sell[i] = Math.max(buy[i-1] + prices[i], sell[i-1]); + buy[i] = Math.max(cool[i-1] - prices[i], buy[i-1]); + cool[i] = Math.max(sell[i-1], buy[i-1], cool[i-1]); + } + return sell[sell.length-1]; +}; \ No newline at end of file diff --git a/Week_04/id_39/LeetCode_70_39.js b/Week_04/id_39/LeetCode_70_39.js new file mode 100644 index 00000000..aae5d9eb --- /dev/null +++ b/Week_04/id_39/LeetCode_70_39.js @@ -0,0 +1,12 @@ +/** + * @param {number} n + * @return {number} + * https://leetcode.com/problems/climbing-stairs/ + */ +var climbStairs = function(n) { + let dp = [0, 1, 2]; + for (let i = 3; i <= n; i++) { + dp[i] = dp[i-1] + dp[i-2]; + } + return dp[n]; +}; \ No newline at end of file diff --git a/Week_04/id_39/LeetCode_84_39.js b/Week_04/id_39/LeetCode_84_39.js new file mode 100644 index 00000000..893e88cf --- /dev/null +++ b/Week_04/id_39/LeetCode_84_39.js @@ -0,0 +1,35 @@ +/** + * @param {number[]} heights + * @return {number} + * https://leetcode.com/problems/largest-rectangle-in-histogram/ + * 回顾第一周视频,以栈的解法解答该题目 + */ +class newStack { + constructor () { + this.arr = [...arguments]; + } + peek () { + return this.arr[this.arr.length - 1]; + } + push (node) { + this.arr.push(node); + } + pop () { + return this.arr.pop(); + } +} + +var largestRectangleArea = function(heights) { + let stack = new newStack(-1), maxArea = 0; + + for (let i = 0; i < heights.length; i++) { + while(heights[i] < heights[stack.peek()] && stack.peek() != -1) { + maxArea = Math.max(maxArea, heights[stack.pop()] * (i - stack.peek() - 1 )); + } + stack.push(i); + } + while (stack.peek() != -1) { + maxArea = Math.max(maxArea, heights[stack.pop()] * (heights.length - stack.peek() - 1 )); + } + return maxArea; +}; \ No newline at end of file diff --git a/Week_04/id_39/NOTE.md b/Week_04/id_39/NOTE.md index 107ea7d6..dadb935a 100644 --- a/Week_04/id_39/NOTE.md +++ b/Week_04/id_39/NOTE.md @@ -1 +1,6 @@ # 学习笔记 + +- 这周把之前的用单调栈求解面积的视频又看了一遍,并做了代码实现,还是有点小迷糊,还是得多做 +- DP的题目 + - 思路都是从结果开始考虑,找子问题,看能不能倒推回去 + - 不过边界限制条件不太好想,得多写多练才可以 \ No newline at end of file diff --git a/Week_04/id_40/LeetCode_208_40.cpp b/Week_04/id_40/LeetCode_208_40.cpp new file mode 100644 index 00000000..ceb4a217 --- /dev/null +++ b/Week_04/id_40/LeetCode_208_40.cpp @@ -0,0 +1,93 @@ +/* + * @lc app=leetcode id=208 lang=cpp + * + * [208] Implement Trie (Prefix Tree) + * + * https://leetcode.com/problems/implement-trie-prefix-tree/description/ + * + * algorithms + * Medium (39.02%) + * Likes: 1640 + * Dislikes: 34 + * Total Accepted: 184.5K + * Total Submissions: 472.8K + * Testcase Example: '["Trie","insert","search","search","startsWith","insert","search"]\n[[],["apple"],["apple"],["app"],["app"],["app"],["app"]]' + * + * Implement a trie with insert, search, and startsWith methods. + * + * Example: + * + * + * Trie trie = new Trie(); + * + * trie.insert("apple"); + * trie.search("apple"); // returns true + * trie.search("app"); // returns false + * trie.startsWith("app"); // returns true + * trie.insert("app"); + * trie.search("app"); // returns true + * + * + * Note: + * + * + * You may assume that all inputs are consist of lowercase letters a-z. + * All inputs are guaranteed to be non-empty strings. + * + * + */ +const int MAXN = 26; +class Trie { +public: + /** Initialize your data structure here. */ + bool is_str; // 标识当前结点是否为一个完整的字符串 + Trie *next[MAXN]; // 下一个结点的指针数组 + Trie() { + is_str = NULL; + memset(next,0,sizeof(next)); + } + + /** Inserts a word into the trie. */ + void insert(string word) { + Trie *cur = this; // cur初始化为根结点指针 + for(char w : word){ // 遍历word中的每一个字符 + if(cur->next[w-'a']==NULL){ // 下一个结点不存在,新增一个结点 + Trie *new_node = new Trie(); + cur->next[w-'a'] = new_node; + } + cur = cur->next[w-'a']; + } + cur->is_str = true; // 当前结点已经是一个完整的字符串了 + + + } + + /** Returns if the word is in the trie. */ + bool search(string word) { + Trie *cur = this; + for(char w : word){ + if(cur!=NULL) + cur = cur->next[w-'a']; // 更新cur指针的指向,使其指向下一个结点 + } + return (cur!=NULL&&cur->is_str); // cur指针不为空且cur指针指向的结点为一个完整的字符串,则成功找到字符串 + } + + /** Returns if there is any word in the trie that starts with the given prefix. */ + bool startsWith(string prefix) { + Trie *cur = this; + for(char w : prefix){ + if(cur!=NULL) + cur = cur->next[w-'a']; + } + return (cur!=NULL); // 相比search(),这里只需判断cur指针是否为空就行了 + } +}; + +/** + * Your Trie object will be instantiated and called as such: + * Trie* obj = new Trie(); + * obj->insert(word); + * bool param_2 = obj->search(word); + * bool param_3 = obj->startsWith(prefix); + */ + diff --git a/Week_04/id_40/LeetCode_337_40.cpp b/Week_04/id_40/LeetCode_337_40.cpp new file mode 100644 index 00000000..1f6ed8f4 --- /dev/null +++ b/Week_04/id_40/LeetCode_337_40.cpp @@ -0,0 +1,82 @@ +/* + * @lc app=leetcode id=337 lang=cpp + * + * [337] House Robber III + * + * https://leetcode.com/problems/house-robber-iii/description/ + * + * algorithms + * Medium (48.27%) + * Likes: 1561 + * Dislikes: 32 + * Total Accepted: 105.9K + * Total Submissions: 219.4K + * Testcase Example: '[3,2,3,null,3,null,1]' + * + * The thief has found himself a new place for his thievery again. There is + * only one entrance to this area, called the "root." Besides the root, each + * house has one and only one parent house. After a tour, the smart thief + * realized that "all houses in this place forms a binary tree". It will + * automatically contact the police if two directly-linked houses were broken + * into on the same night. + * + * Determine the maximum amount of money the thief can rob tonight without + * alerting the police. + * + * Example 1: + * + * + * Input: [3,2,3,null,3,null,1] + * + * ⁠ 3 + * ⁠ / \ + * ⁠ 2 3 + * ⁠ \ \ + * ⁠ 3 1 + * + * Output: 7 + * Explanation: Maximum amount of money the thief can rob = 3 + 3 + 1 = 7. + * + * Example 2: + * + * + * Input: [3,4,5,1,3,null,1] + * + * 3 + * ⁠ / \ + * ⁠ 4 5 + * ⁠ / \ \ + * ⁠1 3 1 + * + * Output: 9 + * Explanation: Maximum amount of money the thief can rob = 4 + 5 = 9. + * + */ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +class Solution { +public: + int tryRob(TreeNode* root, int& l, int& r) { + if (!root) + return 0; + + int ll = 0, lr = 0, rl = 0, rr = 0; + l = tryRob(root->left, ll, lr); + r = tryRob(root->right, rl, rr); + + return max(root->val + ll + lr + rl + rr, l + r); + } + + int rob(TreeNode* root) { + int l, r; + return tryRob(root, l, r); + } +}; + diff --git a/Week_04/id_40/LeetCode_53_40.cpp b/Week_04/id_40/LeetCode_53_40.cpp new file mode 100644 index 00000000..1e106777 --- /dev/null +++ b/Week_04/id_40/LeetCode_53_40.cpp @@ -0,0 +1,68 @@ +/* + * @lc app=leetcode id=53 lang=cpp + * + * [53] Maximum Subarray + * + * https://leetcode.com/problems/maximum-subarray/description/ + * + * algorithms + * Easy (43.84%) + * Likes: 4476 + * Dislikes: 156 + * Total Accepted: 555.6K + * Total Submissions: 1.3M + * Testcase Example: '[-2,1,-3,4,-1,2,1,-5,4]' + * + * Given an integer array nums, find the contiguous subarray (containing at + * least one number) which has the largest sum and return its sum. + * + * Example: + * + * + * Input: [-2,1,-3,4,-1,2,1,-5,4], + * Output: 6 + * Explanation: [4,-1,2,1] has the largest sum = 6. + * + * + * Follow up: + * + * If you have figured out the O(n) solution, try coding another solution using + * the divide and conquer approach, which is more subtle. + * + */ +class Solution { +public: +/* + //暴力解法 + int maxSubArray(vector& nums) { + if(nums.size()==0) return NULL; + int max=nums[0];//存最大值 + int sum=0;//求和 + for(int i=0;imax) max=sum; + } + } + return max; + } +*/ + + //动态规划 + int maxSubArray(vector& nums) { + if(nums.size() == 0) return NULL; + int res = INT_MIN; + int sum = -1; + for(int i = 0; i < nums.size(); ++i) + { + sum = max(nums[i], sum + nums[i]); + res = max(sum, res); + } + return res; + } + +}; + diff --git a/Week_04/id_40/LeetCode_714_40.cpp b/Week_04/id_40/LeetCode_714_40.cpp new file mode 100644 index 00000000..48378ca4 --- /dev/null +++ b/Week_04/id_40/LeetCode_714_40.cpp @@ -0,0 +1,53 @@ +/* + * @lc app=leetcode id=714 lang=cpp + * + * [714] Best Time to Buy and Sell Stock with Transaction Fee + * + * https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/description/ + * + * algorithms + * Medium (50.65%) + * Likes: 934 + * Dislikes: 31 + * Total Accepted: 41K + * Total Submissions: 80.9K + * Testcase Example: '[1,3,2,8,4,9]\n2' + * + * Your are given an array of integers prices, for which the i-th element is + * the price of a given stock on day i; and a non-negative integer fee + * representing a transaction fee. + * You may complete as many transactions as you like, but you need to pay the + * transaction fee for each transaction. You may not buy more than 1 share of + * a stock at a time (ie. you must sell the stock share before you buy again.) + * Return the maximum profit you can make. + * + * Example 1: + * + * Input: prices = [1, 3, 2, 8, 4, 9], fee = 2 + * Output: 8 + * Explanation: The maximum profit can be achieved by: + * Buying at prices[0] = 1Selling at prices[3] = 8Buying at prices[4] = + * 4Selling at prices[5] = 9The total profit is ((8 - 1) - 2) + ((9 - 4) - 2) = + * 8. + * + * + * + * Note: + * 0 < prices.length . + * 0 < prices[i] < 50000. + * 0 . + * + */ +class Solution { +public: + int maxProfit(vector& prices, int fee) { + int s0 = 0, s1 = INT_MIN; + for(int p:prices) { + int tmp = s0; + s0 = max(s0, s1+p); + s1 = max(s1, tmp-p-fee); + } + return s0; + } +}; + diff --git a/Week_04/id_40/LeetCode_77_40.cpp b/Week_04/id_40/LeetCode_77_40.cpp new file mode 100644 index 00000000..0f309672 --- /dev/null +++ b/Week_04/id_40/LeetCode_77_40.cpp @@ -0,0 +1,56 @@ +/* + * @lc app=leetcode id=77 lang=cpp + * + * [77] Combinations + * + * https://leetcode.com/problems/combinations/description/ + * + * algorithms + * Medium (48.20%) + * Likes: 804 + * Dislikes: 47 + * Total Accepted: 208.5K + * Total Submissions: 432.6K + * Testcase Example: '4\n2' + * + * Given two integers n and k, return all possible combinations of k numbers + * out of 1 ... n. + * + * Example: + * + * + * Input: n = 4, k = 2 + * Output: + * [ + * ⁠ [2,4], + * ⁠ [3,4], + * ⁠ [2,3], + * ⁠ [1,2], + * ⁠ [1,3], + * ⁠ [1,4], + * ] + * + * + */ +class Solution { +public: + vector> combine(int n, int k) { + vector> result; + int i = 0; + vector p(k, 0); + while (i >= 0) { + p[i]++; + if (p[i] > n) + --i; + else if (i == k - 1) + result.push_back(p); + else { + ++i; + p[i] = p[i - 1]; + } + } + return result; + + } +}; + diff --git a/Week_04/id_41/LeetCode_121_41.cpp b/Week_04/id_41/LeetCode_121_41.cpp new file mode 100644 index 00000000..515c3c52 --- /dev/null +++ b/Week_04/id_41/LeetCode_121_41.cpp @@ -0,0 +1,21 @@ +/* + * @lc app=leetcode id=121 lang=cpp + * + * [121] Best Time to Buy and Sell Stock + * T(n) = O(N) + * T(n) = O(1) + */ +class Solution { +public: + int maxProfit(vector& prices) { + int maxPro = 0; + int minPrice = INT_MAX; + + for (auto p : prices) + { + minPrice = min(minPrice, p); + maxPro = max(p - minPrice, maxPro); + } + return maxPro; + } +}; diff --git a/Week_04/id_41/LeetCode_122_41.cpp b/Week_04/id_41/LeetCode_122_41.cpp new file mode 100644 index 00000000..e2d94076 --- /dev/null +++ b/Week_04/id_41/LeetCode_122_41.cpp @@ -0,0 +1,21 @@ +/* + * @lc app=leetcode id=122 lang=cpp + * + * [122] Best Time to Buy and Sell Stock II + * T(n) = O(N) + * S(n) = O(1) + */ +class Solution { +public: + int maxProfit(vector& prices) { + int n = prices.size(); + int res = 0; + + for (int i = 1; i < n; i++) + { + if (prices[i] > prices[i - 1]) + res += prices[i] - prices[i - 1]; + } + return res; + } +}; diff --git a/Week_04/id_41/LeetCode_123_41.cpp b/Week_04/id_41/LeetCode_123_41.cpp new file mode 100644 index 00000000..2d9cf09c --- /dev/null +++ b/Week_04/id_41/LeetCode_123_41.cpp @@ -0,0 +1,37 @@ +/* + * @lc app=leetcode id=123 lang=cpp + * + * [123] Best Time to Buy and Sell Stock III + * dp[day][kthTransaction][state] + * day can be optimized in prices iteration. + * kthTransaction: 0(base) 1(1st transction) or 2(2nd transaction) + * state: sell(0) or buy(1) + * + * dp[kthTransaction][state] + * dp[k][0] = max(dp[k][0], dp[k][1] + price); + * dp[k][1] = max(dp[k][1], dp[k-1][0] - price); + * Time complexity : O(day * transactionCount) + * Space complexity : O(1) + */ +class Solution { +public: + int maxProfit(vector& prices) { + vector> dp(3, vector(2, 0)); + + for (int k = 1; k <= 2; k++) + { + dp[k][0] = 0; + dp[k][1] = INT_MIN; + } + + for (int price : prices) + { + for (int k = 1; k <= 2; k++) + { + dp[k][0] = max(dp[k][0], dp[k][1] + price); + dp[k][1] = max(dp[k][1], dp[k - 1][0] - price); + } + } + return dp[2][0]; + } +}; diff --git a/Week_04/id_41/LeetCode_188_41.cpp b/Week_04/id_41/LeetCode_188_41.cpp new file mode 100644 index 00000000..fb31b38f --- /dev/null +++ b/Week_04/id_41/LeetCode_188_41.cpp @@ -0,0 +1,39 @@ +class Solution +{ +public: + int maxProfit(int k, vector &prices) + { + if (k <= 0 || prices.size() <= 1) + return 0; + + if (k > prices.size() / 2) + return maxProfixWithoutTransactionLimit(prices); + + vector buy(k, INT_MIN); + vector sell(k, 0); + + for (auto price : prices) + { + buy[0] = max(buy[0], -price); + sell[0] = max(sell[0], buy[0] + price); + for (int j = 1; j < k; j++) + { + buy[j] = max(buy[j], sell[j - 1] - price); + sell[j] = max(sell[j], buy[j] + price); + } + } + + return max(sell[k - 1], 0); + } + +private: + int maxProfixWithoutTransactionLimit(vector &prices) + { + int result = 0; + for (int i = 1; i < prices.size(); i++) + { + result += max(prices[i] - prices[i - 1], 0); + } + return result; + } +}; diff --git a/Week_04/id_41/LeetCode_198_41.cpp b/Week_04/id_41/LeetCode_198_41.cpp new file mode 100644 index 00000000..0af3f2eb --- /dev/null +++ b/Week_04/id_41/LeetCode_198_41.cpp @@ -0,0 +1,22 @@ +/* + * @lc app=leetcode id=198 lang=cpp + * + * [198] House Robber + * TC : O(N) + */ +class Solution +{ +public: + int rob(vector &nums) + { + int pre = 0; + int cur = 0; + for (auto n : nums) + { + int temp = max(pre + n, cur); + pre = cur; + cur = temp; + } + return cur; + } +}; diff --git a/Week_04/id_41/LeetCode_208_41.cpp b/Week_04/id_41/LeetCode_208_41.cpp new file mode 100644 index 00000000..5bc7bb07 --- /dev/null +++ b/Week_04/id_41/LeetCode_208_41.cpp @@ -0,0 +1,80 @@ +/* + * @lc app=leetcode id=208 lang=cpp + * + * [208] Implement Trie (Prefix Tree) + */ +class TrieNode { +public: + char data; + vector children; + bool isEndingChar; + TrieNode(char c) : data(c), children(26, nullptr), isEndingChar(false) + { + } + ~TrieNode() + { + for (auto child : children) + { + if (child) + delete child; + } + } +}; + +class Trie { +public: + /** Initialize your data structure here. */ + Trie() { + root = new TrieNode(' '); + } + ~Trie() { + delete root; + } + /** Inserts a word into the trie. */ + void insert(string word) { + TrieNode* p = root; + for (auto c : word) + { + int index = c - 'a'; + if (p->children[index] == nullptr) + { + p->children[index] = new TrieNode(c); + } + p = p->children[index]; + } + p->isEndingChar = true; + } + + /** Returns if the word is in the trie. */ + bool search(string word) { + TrieNode* p = root; + for (auto c : word) + { + int index = c - 'a'; + if (p->children[index] == nullptr) + { + return false; + } + p = p->children[index]; + } + return p->isEndingChar; + } + + /** Returns if there is any word in the trie that starts with the given prefix. */ + bool startsWith(string prefix) { + TrieNode *p = root; + for (auto c : prefix) + { + int index = c - 'a'; + if (p->children[index] == nullptr) + { + return false; + } + p = p->children[index]; + } + return true; + } + +private: + TrieNode* root; +}; diff --git a/Week_04/id_41/LeetCode_212_41.cpp b/Week_04/id_41/LeetCode_212_41.cpp new file mode 100644 index 00000000..2b38d248 --- /dev/null +++ b/Week_04/id_41/LeetCode_212_41.cpp @@ -0,0 +1,103 @@ +class Solution +{ + class Trie + { + public: + Trie *children[26]; // pointers to its substrings starting with 'a' to 'z' + bool leaf; // if the node is a leaf, or if there is a word stopping at here + int idx; // if it is a leaf, the string index of the array words + Trie() + { + this->leaf = false; + this->idx = 0; + fill_n(this->children, 26, nullptr); // initialize children to 26 nullptr. + } + }; + +public: + void insertWords(Trie *root, vector &words, int idx) + { + int pos = 0, len = words[idx].size(); + while (pos < len) + { + if (nullptr == root->children[words[idx][pos] - 'a']) + root->children[words[idx][pos] - 'a'] = new Trie(); + root = root->children[words[idx][pos++] - 'a']; + } + root->leaf = true; + root->idx = idx; + } + + Trie *buildTrie(vector &words) + { + Trie *root = new Trie(); + for (int i = 0; i < words.size(); i++) + { + insertWords(root, words, i); + } + return root; + } + + void checkWords(vector> &board, int i, int j, int row, int col, Trie *root, vector &res, vector &words) + { + char temp; + vector dx = {-1, 1, 0, 0}; + vector dy = {0, 0, -1, 1}; + int x; + int y; + + // terminator + if (board[i][j] == 'X') + return; // visited before; + if (nullptr == root->children[board[i][j] - 'a']) + return; // no string with such prefix + else + { + // process current + temp = board[i][j]; + if (root->children[temp - 'a']->leaf) // if it is a leaf + { + res.push_back(words[root->children[temp - 'a']->idx]); + root->children[temp - 'a']->leaf = false; // set to false to indicate that we found it already + } + board[i][j] = 'X'; //mark the current position as visited, set flag temp = board[i][j] + // check all the possible neighbors + // drill down + x = i + dx[i]; + y = i + dy[i]; + for (int k = 0; k < 4; k++) + { + if (x >= 0 && x < row && y >= 0 && y < col && board[i][j] != 'X') + checkWords(board, x, y, row, col, root->children[temp - 'a'], res, words); + } + // recover + board[i][j] = temp; // recover the current position + } + } + + vector findWords(vector> &board, vector &words) + { + vector res; + int row = board.size(); + if (0 == row) + return res; + int col = board[0].size(); + if (0 == col) + return res; + int wordCount = words.size(); + if (0 == wordCount) + return res; + + Trie *root = buildTrie(words); + + int i, j; + for (i = 0; i < row; i++) + { + for (j = 0; j < col && wordCount > res.size(); j++) + { + checkWords(board, i, j, row, col, root, res, words); + } + } + return res; + } +}; \ No newline at end of file diff --git a/Week_04/id_41/LeetCode_213_41.cpp b/Week_04/id_41/LeetCode_213_41.cpp new file mode 100644 index 00000000..f1f39811 --- /dev/null +++ b/Week_04/id_41/LeetCode_213_41.cpp @@ -0,0 +1,32 @@ +/* + * @lc app=leetcode id=213 lang=cpp + * + * [213] House Robber II + * T(n) = O(N) + * S(n) = O(1) + */ +class Solution { +public: + int rob(vector& nums) { + int n = nums.size(); + if (n < 2) + return n ? nums[0] : 0; + + return max(robber(nums, 0, n - 2), robber(nums, 1, n - 1)); + } + +private: + int robber(vector& nums, int l, int r) + { + int prev = 0; + int curr = 0; + int temp = 0; + for (int i = l; i <= r; i++) + { + temp = max(prev + nums[i], curr); + prev = curr; + curr = temp; + } + return curr; + } +}; diff --git a/Week_04/id_41/LeetCode_309_41.cpp b/Week_04/id_41/LeetCode_309_41.cpp new file mode 100644 index 00000000..92110a15 --- /dev/null +++ b/Week_04/id_41/LeetCode_309_41.cpp @@ -0,0 +1,25 @@ +/* + * @lc app=leetcode id=309 lang=cpp + * + * [309] Best Time to Buy and Sell Stock with Cooldown + * T(n) = O(N) + * S(n) = O(1) + */ +class Solution { +public: + int maxProfit(vector& prices) { + int prev_buy = 0; + int prev_sell = 0; + int buy = INT_MIN; + int sell = 0; + + for (auto price : prices) + { + prev_buy = buy; + buy = max(prev_sell - price, buy); + prev_sell = sell; + sell = max(prev_buy + price, sell); + } + return sell; + } +}; diff --git a/Week_04/id_41/LeetCode_337_41.cpp b/Week_04/id_41/LeetCode_337_41.cpp new file mode 100644 index 00000000..151369ef --- /dev/null +++ b/Week_04/id_41/LeetCode_337_41.cpp @@ -0,0 +1,31 @@ +/* + * @lc app=leetcode id=337 lang=cpp + * + * [337] House Robber III + */ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + * T(n) = O(N) + */ +class Solution { +public: + int rob(TreeNode* root) { + int lm = 0, rm = 0; + return robber(root, lm, rm); + } + + int robber(TreeNode* root, int& lm, int& rm) { + if (root == nullptr) + return 0; + int lm1 = 0, lm2 = 0, rm1 = 0, rm2 = 0; + lm = robber(root->left, lm1, lm2); + rm = robber(root->right,rm1, rm2); + return max(root->val + lm1 + lm2 + rm1 + rm2, lm + rm); + } +}; diff --git a/Week_04/id_41/LeetCode_455_41.cpp b/Week_04/id_41/LeetCode_455_41.cpp new file mode 100644 index 00000000..f5dfed87 --- /dev/null +++ b/Week_04/id_41/LeetCode_455_41.cpp @@ -0,0 +1,25 @@ +/* + * @lc app=leetcode id=455 lang=cpp + * + * [455] Assign Cookies + * Time complexity : O(min(g.size, s.size)) + * Space complexity: O(1) + */ +class Solution { +public: + int findContentChildren(vector& g, vector& s) { + sort(g.begin(), g.end()); + sort(s.begin(), s.end()); + int satisfied = 0; + + for (int j = 0; satisfied < g.size() && j < s.size(); j++) + { + if (g[satisfied] <= s[j]) + { + satisfied++; + } + } + return satisfied; + } +}; + diff --git a/Week_04/id_41/LeetCode_51_41.cpp b/Week_04/id_41/LeetCode_51_41.cpp new file mode 100644 index 00000000..718f863b --- /dev/null +++ b/Week_04/id_41/LeetCode_51_41.cpp @@ -0,0 +1,54 @@ +// T(n) = O(n!) S(n) = O(n) +class Solution { +public: + vector> solveNQueens(int n) { + int row; + vector col(n, 0); + vector diag(2 * n - 1); + vector antiDiag(2 * n - 1); + // 1 עback_inserter + fill_n(back_inserter(curr), n, string(n, '.')); + + numQueen = n; + dfs(0, col, diag, antiDiag); + + return res; + } +private: + vector> res; + vector curr; + int numQueen; + void dfs(int row, + vector& col, + vector& diag, + vector& antiDiag) + { + // terminator + if (row >= numQueen) + { + res.push_back(curr); + return; + } + // process current + for (int i = 0; i < numQueen; i++) + { + if (col[i] == 0 && + // 2row + iɣҪnunQueens - 1ΪԽ + diag[row + i] == 0 && + antiDiag[row - i + numQueen - 1] == 0) + { + col[i] = 1; + diag[row + i] = 1; + antiDiag[row - i + numQueen - 1] = 1; + curr[row][i] = 'Q'; + // drill down + dfs(row + 1, col, diag, antiDiag); + // restore + col[i] = 0; + diag[row + i] = 0; + antiDiag[row - i + numQueen - 1] = 0; + curr[row][i] = '.'; + } + } + } +}; diff --git a/Week_04/id_41/LeetCode_62_41.cpp b/Week_04/id_41/LeetCode_62_41.cpp new file mode 100644 index 00000000..647ca737 --- /dev/null +++ b/Week_04/id_41/LeetCode_62_41.cpp @@ -0,0 +1,21 @@ +/* + * @lc app=leetcode id=62 lang=cpp + * + * [62] Unique Paths + * T(n) = O(m * n) + * S(n) = O(m * n) + */ +class Solution { +public: + int uniquePaths(int m, int n) { + vector> dp(m, vector(n, 1)); + for (int i = 1; i < m; i++) + { + for (int j = 1; j < n; j++) + { + dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; + } + } + return dp[m - 1][n - 1]; + } +}; diff --git a/Week_04/id_41/LeetCode_63_41.cpp b/Week_04/id_41/LeetCode_63_41.cpp new file mode 100644 index 00000000..22a8ab87 --- /dev/null +++ b/Week_04/id_41/LeetCode_63_41.cpp @@ -0,0 +1,28 @@ +/* + * @lc app=leetcode id=63 lang=cpp + * + * [63] Unique Paths II + * T(n) = O(m * n) + * S(n) = O(m * n) + */ +class Solution +{ +public: + int uniquePathsWithObstacles(vector> &obstacleGrid) + { + int m = obstacleGrid.size(); + int n = obstacleGrid[0].size(); + vector> dp(m + 1, vector(n + 1, 0)); + dp[0][1] = 1; + + for (int i = 1; i <= m; i++) + { + for (int j = 1; j <= n; j++) + { + if (!obstacleGrid[i - 1][j - 1]) + dp[i][j] = dp[i][j - 1] + dp[i - 1][j]; + } + } + return dp[m][n]; + } +}; diff --git a/Week_04/id_41/LeetCode_70_41.cpp b/Week_04/id_41/LeetCode_70_41.cpp new file mode 100644 index 00000000..3c4382dc --- /dev/null +++ b/Week_04/id_41/LeetCode_70_41.cpp @@ -0,0 +1,155 @@ +/* + * @lc app=leetcode id=70 lang=cpp + * + * [70] Climbing Stairs + */ + +// dp T(n) = O(n) S(n) = O(n) +class Solution_raw_dp +{ +public: + int climbStairs(int n) + { + vector dp(n); + if (n == 1) + return 1; + if (n < 1) + return 0; + + dp[0] = 1; + dp[1] = 2; + + for (int i = 2; i < n; i++) + { + dp[i] = dp[i - 1] + dp[i - 2]; + } + return dp[n - 1]; + } +}; + +// dp space optimization T(n) = O(n) S(n) = O(1) +class Solution_dp_space_opt +{ +public: + int climbStairs(int n) + { + vector dp(n); + if (n == 1) + return 1; + if (n < 1) + return 0; + + // dp[0] = 1; + int first = 1; + // dp[1] = 2; + int second = 2; + int third = 0; + + for (int i = 2; i < n; i++) + { + // dp[i] = dp[i - 1] + dp[i - 2]; + third = second + first; + first = second; + second = third; + } + return second; + } +}; + +// recursion T(n) = O(2^n) S(n) = O(n) +class Solution_recursion +{ +public: + int climbStairs(int n) + { + if (n <= 2) + return n; + vector memo(n, -1); + return climbStairsHelper(0, n, memo); + } + +private: + int climbStairsHelper(int i, int n, vector &memo) + { + if (i > n) + return 0; + if (i == n) + return 1; + + if (memo[i] != -1) + { + return memo[i]; + } + + memo[i] = climbStairsHelper(i + 1, n, memo) + + climbStairsHelper(i + 2, n, memo); + return memo[i]; + } +}; + +// recursion: matrix multiply T(n) = O(logn) S(n) = O(n) +class Solution +{ +public: + int climbStairs(int n) + { + vector> res(4); + res = powermatrix(n); + return res[0][0]; + } + + vector> powermatrix(int n) + { + vector> Q = {{1, 1}, {1, 0}}; + vector> ret(4); + + if (n == 1) + return Q; + ret = powermatrix(n / 2); + ret = cross(ret, ret); + + if (n & 1) + ret = cross(ret, Q); + + return ret; + } + + vector> cross(vector> A, vector> B) + { + vector> C(2, vector(2, 0)); + for (int i = 0; i < 2; i++) + { + for (int j = 0; j < 2; j++) + { + C[i][j] = A[i][0] * B[0][j] + A[i][1] * B[1][j]; + } + } + + return C; + } +}; + +// recursion: space optimized matrix multiply T(n) = O(logn) S(n) = O(n) +class Solution_opt_matrix_multiply +{ +public: + int climbStairs(int n) + { + return (n <= 2) ? n : helper(n).second; + } + +private: + pair helper(int n) + { + if (n == 0) + { + return {0, 1}; + } + + pair x = helper(n / 2); + pair y = {x.first * (2 * x.second - x.first), + x.first * x.first + x.second * x.second}; + + return n & 1 ? make_pair(y.second, y.first + y.second) : y; + } +}; diff --git a/Week_04/id_41/LeetCode_714_41 b/Week_04/id_41/LeetCode_714_41 new file mode 100644 index 00000000..2508762f --- /dev/null +++ b/Week_04/id_41/LeetCode_714_41 @@ -0,0 +1,22 @@ +/* + * @lc app=leetcode id=714 lang=cpp + * + * [714] Best Time to Buy and Sell Stock with Transaction Fee + * Time complexity : O(N) + * Space Complexity: O(1) + */ +class Solution { +public: + int maxProfit(vector& prices, int fee) { + int n = prices.size(); + int sell = 0; + int buy = -prices[0]; + + for (int i = 1; i < n; i++) + { + sell = max(sell, buy + prices[i] - fee); + buy = max(buy, sell - prices[i]); + } + return sell; + } +}; diff --git a/Week_04/id_41/LeetCode_720_41.cpp b/Week_04/id_41/LeetCode_720_41.cpp new file mode 100644 index 00000000..8e40cc19 --- /dev/null +++ b/Week_04/id_41/LeetCode_720_41.cpp @@ -0,0 +1,121 @@ +/* + * @lc app=leetcode id=720 lang=cpp + * + * [720] Longest Word in Dictionary + * Trie + DFS + * T(n) = O(key_length) + * S(n) = O(26 * key_length *N) + */ + +class TrieNode +{ +public: + char data; + vector children; + bool isEndingChar; + TrieNode(char c) : data(c), children(26, nullptr), isEndingChar(false) + { + } + ~TrieNode() + { + for (TrieNode *child : children) + { + if (child) + delete child; + } + } +}; + +class Trie +{ +public: + void insert(string s) + { + TrieNode *p = root; + for (auto c : s) + { + int index = c - 'a'; + if (p->children[index] == nullptr) + { + TrieNode *newNode = new TrieNode(c); + p->children[index] = newNode; + } + p = p->children[index]; + } + p->isEndingChar = true; + } + + bool find(string pattern) + { + TrieNode *p = root; + for (auto c : pattern) + { + int index = c - 'a'; + if (p->children[index] == nullptr) + { + return false; + } + p = p->children[index]; + } + return p->isEndingChar; + } + + bool startsWith(string pattern) + { + TrieNode *p = root; + for (auto c : pattern) + { + int index = c - 'a'; + if (p->children[index] == nullptr) + return false; + p = p->children[index]; + } + return true; + } + TrieNode *root = new TrieNode(' '); +}; + +class Solution +{ +public: + string longestWord(vector &words) + { + if (words.size() == 0) + return res; + Trie *trieTree = buildTrie(words); + dfs(trieTree->root, ""); + + return res; + } + +private: + Trie *buildTrie(vector &words) + { + Trie *t = new Trie(); + for (string w : words) + { + t->insert(w); + } + return t; + } + + void dfs(TrieNode *root, string curr) + { + if (root == nullptr) + return; + for (int i = 0; i < 26; i++) + { + if (root->children[i] != nullptr && + root->children[i]->isEndingChar == true) + { + curr.append(1, i + 'a'); + if (curr.size() > res.size()) + res = curr; + dfs(root->children[i], curr); + curr.pop_back(); + } + } + } + + string res = ""; +}; diff --git a/Week_04/id_41/LeetCode_77_41.cpp b/Week_04/id_41/LeetCode_77_41.cpp new file mode 100644 index 00000000..f30eddf4 --- /dev/null +++ b/Week_04/id_41/LeetCode_77_41.cpp @@ -0,0 +1,31 @@ +// T(n) = O(n!/k!(n-k)!)) +class Solution +{ +public: + vector> combine(int n, int k) + { + if (n <= 0 or k <= 0 or n < k) + return result; + _combine(n, k, 1); + return result; + } + +private: + vector> result; + vector nums; + void _combine(int n, int k, int start) + { + if (k == nums.size()) + { + result.push_back(nums); + return; + } + + for (int i = start; i <= n - (k - nums.size()) + 1; ++i) + { + nums.push_back(i); + _combine(n, k, i + 1); + nums.pop_back(); + } + } +}; diff --git a/Week_04/id_41/LeetCode_784_41.cpp b/Week_04/id_41/LeetCode_784_41.cpp new file mode 100644 index 00000000..bfc37aa6 --- /dev/null +++ b/Week_04/id_41/LeetCode_784_41.cpp @@ -0,0 +1,38 @@ +/* + * @lc app=leetcode id=784 lang=cpp + * + * [784] Letter Case Permutation + * T(n) = O(N) + * S(n) = O(N) + */ +class Solution { +public: + vector letterCasePermutation(string S) { + if (S.size() == 0) + return res; + helper(S, 0); + return res; + } +private: + vector res; + void helper(string s, int i) + { + // terminator + if (i == s.size()) + { + res.push_back(s); + return; + } + // drill down + helper(s, i + 1); + + if (isalpha(s[i])) + { + // process current : letter case change + s[i] ^= 1 << 5; + helper(s, i + 1); + // restore + s[i] ^= 1 << 5; + } + } +}; diff --git a/Week_04/id_41/LeetCode_78_41.cpp b/Week_04/id_41/LeetCode_78_41.cpp new file mode 100644 index 00000000..5633d0ea --- /dev/null +++ b/Week_04/id_41/LeetCode_78_41.cpp @@ -0,0 +1,54 @@ +/* + * @lc app=leetcode id=78 lang=cpp + * + * [78] Subsets + */ +// T(n) = O(N*2^N), S(n) = O(1) +class Solution_backtracing +{ +public: + vector> subsets(vector &nums) + { + if (nums.size() == 0) + return subs; + dfs(nums, 0); + return subs; + } + +private: + vector> subs; + vector sub; + void dfs(vector &nums, int i) + { + // process current + subs.push_back(sub); + for (int j = i; j < nums.size(); j++) + { + sub.push_back(nums[j]); + // drill down + dfs(nums, j + 1); + // restore + sub.pop_back(); + } + } +}; + +// bitops, T(n) = O(N*2^N), S(n) = O(1) +class Solution +{ +public: + vector> subsets(vector& nums) { + int n = nums.size(); + int p = 1 << n; + vector> subs(p); + + for (int i = 0; i < p; i++) { + for (int j = 0; j < n; j++) { + if ((i >> j) & 1) { + subs[i].push_back(nums[j]); + } + } + } + return subs; + } +}; diff --git a/Week_04/id_42/NOTE.md b/Week_04/id_42/NOTE.md index 107ea7d6..e6ea956e 100644 --- a/Week_04/id_42/NOTE.md +++ b/Week_04/id_42/NOTE.md @@ -1 +1,29 @@ # 学习笔记 + + +## 做的这两道都是Trie树的题目 + +### leet_code 208 题目的意思为 构造Trie树的结构 + +这个题目要记住两点: + + 1.TireNode 这种数据元素 +```java + class TrieNode{ + private TrieNode[] son; + private boolean isWord; + private char val; + TrieNode(){ + son = new TrieNode[SIZE]; + isWord = false; + } + } + +``` + 2. 三种操作 + insert startwith search + + +### leetcode 211 则是在208 的基础上增加了模式匹配 + + 利用了程序中递归 和循环遍历的小技巧 \ No newline at end of file diff --git a/Week_04/id_42/leetcode_208_42.java b/Week_04/id_42/leetcode_208_42.java new file mode 100644 index 00000000..132ceb27 --- /dev/null +++ b/Week_04/id_42/leetcode_208_42.java @@ -0,0 +1,78 @@ +public class leetcode_208_42 { +} + +public class Trie { + private final int SIZE = 26; + private TrieNode root; + + class TrieNode { + private TrieNode[] son; + private boolean isWord; + private char val; + + TrieNode() { + son = new TrieNode[SIZE]; + isWord = false; + } + } + + public Trie() { + root = new TrieNode(); + } + + public void insert(String word) { + if (word.length() == 0) { + return; + } + char[] chars = word.toCharArray(); + TrieNode node = root; + for (int i = 0; i < chars.length; i++) { + int pos = chars[i] - 'a'; + if (node.son[pos] == null) { + node.son[pos] = new TrieNode(); + node.son[pos].val = chars[i]; + } + node = node.son[pos]; + } + + node.isWord = true; + } + + public boolean search(String word) { + if (word == null || word.length() == 0) { + return false; + } + char[] chars = word.toCharArray(); + TrieNode node = root; + for (int i = 0; i < chars.length; i++) { + int pos = chars[i] - 'a'; + if (node.son[pos] == null) { + return false; + } + if (node.son[pos].val != chars[i]) { + return false; + } + node = node.son[pos]; + } + + return node.isWord; + } + + public boolean startsWith(String prefix) { + if (prefix == null || prefix.length() == 0) { + return false; + } + char[] chars = prefix.toCharArray(); + TrieNode node = root; + for (int i = 0; i < chars.length; i++) { + int pos = chars[i] - 'a'; + if (node.son[pos].val != chars[i]) { + return false; + } + node = node.son[pos]; + } + + return true; + } + +} \ No newline at end of file diff --git a/Week_04/id_42/leetcode_211_42.java b/Week_04/id_42/leetcode_211_42.java new file mode 100644 index 00000000..0269ed2a --- /dev/null +++ b/Week_04/id_42/leetcode_211_42.java @@ -0,0 +1,67 @@ +public class leetcode_211_42 { +} +public class WordDictionary { + private final int SIZE = 26; + private TrieNode root; + + class TrieNode { + private TrieNode[] childs; + private boolean isWord; + private char val; + + TrieNode() { + childs = new TrieNode[SIZE]; + isWord = false; + } + } + + public WordDictionary() { + root = new TrieNode(); + } + + + public void addWord(String word) { + if (word == null & word.length() == 0) { + return; + } + char[] chars = word.toCharArray(); + TrieNode node = root; + for (int i = 0; i < chars.length; i++) { + int index = chars[i] - 'a'; + if (node.childs[index] == null) { + TrieNode nodeNew = new TrieNode(); + nodeNew.val = chars[i]; + node.childs[index] = nodeNew; + } + node = node.childs[index]; + } + node.isWord = true; + } + + public boolean search(String word) { + return match(word, root, 0); + } + + public boolean match(String word, TrieNode node, int start) { + if (start == word.length()) { + return node.isWord; + } + char alpha = word.charAt(start); + if (alpha == '.') { + for (int i = 0; i < 26; i++) { + + if ((node.childs[i] != null) && match(word, node.childs[i], start + 1)) { + return true; + } + } + return false; + } else { + if (node.childs[alpha - 'a'] == null) + return false; + return match(word, node.childs[alpha - 'a'], start + 1); + + } + + + } +} diff --git a/Week_04/id_6/LeetCode_208_6.php b/Week_04/id_6/LeetCode_208_6.php new file mode 100644 index 00000000..4ac6dd82 --- /dev/null +++ b/Week_04/id_6/LeetCode_208_6.php @@ -0,0 +1,93 @@ +root = new TrieNode(); + } + + /** + * Inserts a word into the trie. + * @param String $word + * @return NULL + */ + function insert($word) + { + if (!$word) return; + + $node = $this->root; + for ($i = 0; $i < strlen($word); $i ++) { + if (!isset($node->children[$word[$i]])) { + $node->children[$word[$i]] = new TrieNode($word[$i]); + } + + $node = $node->children[$word[$i]]; + } + $node->is_word = true; + } + + /** + * Returns if the word is in the trie. + * @param String $word + * @return Boolean + */ + function search($word) + { + $node = $this->root; + for ($i = 0; $i < strlen($word); $i ++) { + if (!isset($node->children[$word[$i]])) return false; + $node = $node->children[$word[$i]]; + } + + return $node->is_word; + } + + /** + * Returns if there is any word in the trie that starts with the given prefix. + * @param String $prefix + * @return Boolean + */ + function startsWith($prefix) + { + $node = $this->root; + for ($i = 0; $i < strlen($prefix); $i ++) { + if (!isset($node->children[$prefix[$i]])) return false; + $node = $node->children[$prefix[$i]]; + } + + return true; + } +} + +class TrieNode +{ + public $children = []; + public $is_word = false; + public $val = null; + + function __construct($val = null) + { + $this->val = $val; + } +} + +/** + * Your Trie object will be instantiated and called as such: + * $obj = Trie(); + * $obj->insert($word); + * $ret_2 = $obj->search($word); + * $ret_3 = $obj->startsWith($prefix); + */ + +$obj = new Trie(); +$obj->insert('apple'); +$ret_2 = $obj->search('apple'); +$ret_3 = $obj->startsWith('app'); +var_dump($obj, $ret_2, $ret_3); \ No newline at end of file diff --git a/Week_04/id_6/LeetCode_211_6.php b/Week_04/id_6/LeetCode_211_6.php new file mode 100644 index 00000000..16e1996d --- /dev/null +++ b/Week_04/id_6/LeetCode_211_6.php @@ -0,0 +1,102 @@ +root = new TrieNode(); + } + + /** + * Adds a word into the data structure. + * @param String $word + * @return NULL + */ + function addWord($word) + { + if (!$word) return; + + $node = $this->root; + for ($i = 0; $i < strlen($word); $i ++) { + if (!isset($node->children[$word[$i]])) { + $node->children[$word[$i]] = new TrieNode($word[$i]); + } + + $node = $node->children[$word[$i]]; + } + $node->is_word = true; + } + + /** + * Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. + * @param String $word + * @return Boolean + */ + function search($word) + { + if (!$word) return true; + $node = $this->root; + return $this->searchRec($word, $node, 0); + } + + /** + * @param $word + * @param TrieNode $node + * @param $pos + * @return boolean + */ + private function searchRec($word, $node, $pos) + { + if ($pos == strlen($word)) return $node->is_word; + if ($word[$pos] == '.') { + $pos ++; + foreach ($node->children as $child) { + if ($this->searchRec($word, $child, $pos)) { + return true; + } + } + return false; + } else { + if (!isset($node->children[$word[$pos]])) return false; + } + + return $this->searchRec($word, $node->children[$word[$pos]], $pos + 1); + } +} + +class TrieNode +{ + public $children = []; + public $is_word = false; + public $val = null; + + function __construct($val = null) + { + $this->val = $val; + } +} + +/** + * Your WordDictionary object will be instantiated and called as such: + * $obj = WordDictionary(); + * $obj->addWord($word); + * $ret_2 = $obj->search($word); + */ + +$obj = new WordDictionary(); +$obj->addWord('at'); +$obj->addWord('and'); +$obj->addWord('an'); +$obj->addWord('add'); +var_export($obj); +var_dump($obj->search('a')); +var_dump($obj->search('.at')); +$obj->addWord('bat'); +var_export($obj); +var_dump($obj->search('.at')); +var_dump($obj->search('b..')); diff --git a/Week_04/id_6/LeetCode_212_6.php b/Week_04/id_6/LeetCode_212_6.php new file mode 100644 index 00000000..5b5501fd --- /dev/null +++ b/Week_04/id_6/LeetCode_212_6.php @@ -0,0 +1,167 @@ +trie = new Trie(); + } + + /** + * @param String[][] $board + * @param String[] $words + * @return String[] + */ + function findWords($board, $words) + { + if (!$board || !$words) return []; + + // make trie + foreach ($words as $word) { + $this->trie->insert($word); + } + + for ($i = 0; $i < count($board); $i ++) { + for ($j = 0; $j < count($board[0]); $j ++) { + $visited = []; + + if (!$this->trie->startsWith($board[$i][$j])) { + continue; + } + + if ($this->trie->search($board[$i][$j])) { + if (!in_array($board[$i][$j], $this->ret)) { + $this->ret[] = $board[$i][$j]; + } + } + + $visited[$i][$j] = 1; + $start = $board[$i][$j]; + $this->dfs($board, $start, $visited, $i, $j); + } + } + + sort($this->ret); + return $this->ret; + } + + function dfs($board, $start, $visited, $i, $j) + { + $x = [$i - 1, $i, $i + 1, $i]; + $y = [$j, $j - 1, $j, $j + 1]; + $width = count($board); + $height = count($board[0]); + + for ($k = 0; $k < 4; $k ++) { + if ($x[$k] < 0 || $y[$k] < 0 || $x[$k] > $width - 1 || $y[$k] > $height - 1 || (isset($visited[$x[$k]][$y[$k]]) && $visited[$x[$k]][$y[$k]] == 1)) { + continue; + } + + $_start = $start . $board[$x[$k]][$y[$k]]; + if (!$this->trie->startsWith($_start)) { + continue; + } + + if ($this->trie->search($_start)) { + if (!in_array($_start, $this->ret)) { + $this->ret[] = $_start; + } + } + + $visited[$x[$k]][$y[$k]] = 1; + $this->dfs($board, $_start, $visited, $x[$k], $y[$k]); + $visited[$x[$k]][$y[$k]] = 0; + } + } +} + +class Trie +{ + public $root; + + /** + * Initialize your data structure here. + */ + function __construct() + { + $this->root = new TrieNode(); + } + + /** + * Inserts a word into the trie. + * @param String $word + * @return NULL + */ + function insert($word) + { + if (!$word) return; + + $node = $this->root; + for ($i = 0; $i < strlen($word); $i ++) { + if (!isset($node->children[$word[$i]])) { + $node->children[$word[$i]] = new TrieNode($word[$i]); + } + + $node = $node->children[$word[$i]]; + } + $node->is_word = true; + } + + /** + * Returns if the word is in the trie. + * @param String $word + * @return Boolean + */ + function search($word) + { + $node = $this->root; + for ($i = 0; $i < strlen($word); $i ++) { + if (!isset($node->children[$word[$i]])) return false; + $node = $node->children[$word[$i]]; + } + + return $node->is_word; + } + + /** + * Returns if there is any word in the trie that starts with the given prefix. + * @param String $prefix + * @return Boolean + */ + function startsWith($prefix) + { + $node = $this->root; + for ($i = 0; $i < strlen($prefix); $i ++) { + if (!isset($node->children[$prefix[$i]])) return false; + $node = $node->children[$prefix[$i]]; + } + + return true; + } +} + +class TrieNode +{ + public $children = []; + public $is_word = false; + public $val = null; + + function __construct($val = null) + { + $this->val = $val; + } +} + +$board = [["o","a","a","n"],["e","t","a","e"],["i","h","k","r"],["i","f","l","v"]]; +$words = ["oath","pea","eat","rain"]; +$board = [['a', 'a']]; +$words = ['a']; +$board = [["b","a","a","b","a","b"],["a","b","a","a","a","a"],["a","b","a","a","a","b"],["a","b","a","b","b","a"],["a","a","b","b","a","b"],["a","a","b","b","b","a"],["a","a","b","a","a","b"]]; +$words = ["bbaabaabaaaaabaababaaaaababb","aabbaaabaaabaabaaaaaabbaaaba","babaababbbbbbbaabaababaabaaa","bbbaaabaabbaaababababbbbbaaa","babbabbbbaabbabaaaaaabbbaaab","bbbababbbbbbbababbabbbbbabaa","babababbababaabbbbabbbbabbba","abbbbbbaabaaabaaababaabbabba","aabaabababbbbbbababbbababbaa","aabbbbabbaababaaaabababbaaba","ababaababaaabbabbaabbaabbaba","abaabbbaaaaababbbaaaaabbbaab","aabbabaabaabbabababaaabbbaab","baaabaaaabbabaaabaabababaaaa","aaabbabaaaababbabbaabbaabbaa","aaabaaaaabaabbabaabbbbaabaaa","abbaabbaaaabbaababababbaabbb","baabaababbbbaaaabaaabbababbb","aabaababbaababbaaabaabababab","abbaaabbaabaabaabbbbaabbbbbb","aaababaabbaaabbbaaabbabbabab","bbababbbabbbbabbbbabbbbbabaa","abbbaabbbaaababbbababbababba","bbbbbbbabbbababbabaabababaab","aaaababaabbbbabaaaaabaaaaabb","bbaaabbbbabbaaabbaabbabbaaba","aabaabbbbaabaabbabaabababaaa","abbababbbaababaabbababababbb","aabbbabbaaaababbbbabbababbbb","babbbaabababbbbbbbbbaabbabaa"]; +$sol = new Solution(); +var_export($sol->findWords($board, $words)); +//var_export($sol->trie); \ No newline at end of file diff --git a/Week_04/id_6/LeetCode_455_6.php b/Week_04/id_6/LeetCode_455_6.php new file mode 100644 index 00000000..9b34e330 --- /dev/null +++ b/Week_04/id_6/LeetCode_455_6.php @@ -0,0 +1,36 @@ + $v1) { + if ($v1 >= $v) { + $num1 ++; + unset($s[$k]); + break; + } + } + $num += $num1; + if ($num1 == 0 || empty($s)) return $num; + } + return $num; + } +} + +$sol = new Solution(); +$g= [1,2,3]; +$s = [3]; +var_dump($sol->findContentChildren($g, $s)); \ No newline at end of file diff --git a/Week_04/id_6/LeetCode_53_6.php b/Week_04/id_6/LeetCode_53_6.php new file mode 100644 index 00000000..3cea55c1 --- /dev/null +++ b/Week_04/id_6/LeetCode_53_6.php @@ -0,0 +1,30 @@ + 0) { + $sum += $nums[$i]; + } else { + $sum = $nums[$i]; + } + $max = max($max, $sum); + } + + return $max; + } +} + +$sol = new Solution; +$nums = [-2,1,-3,4,-1,2,1,-5,4]; +var_dump($sol->maxSubArray($nums)); \ No newline at end of file diff --git a/Week_04/id_6/LeetCode_709_6.php b/Week_04/id_6/LeetCode_709_6.php new file mode 100644 index 00000000..f428a38d --- /dev/null +++ b/Week_04/id_6/LeetCode_709_6.php @@ -0,0 +1,33 @@ += 0; $j --) { + $profit = $prices[$i] - $prices[$j]; + if ($profit < 0) continue; + if ($j >= 2) { + $dp[$i] = max($profit + $dp[$j - 2], $dp[$i]); + } else { + $dp[$i] = max($profit, $dp[$i]); + } + } + } + + return $dp[count($prices) - 1]; + } +} + +$prices = [1,2]; +$sol = new Solution(); +var_dump($sol->maxProfit($prices)); \ No newline at end of file diff --git a/Week_04/id_6/LeetCode_70_6.php b/Week_04/id_6/LeetCode_70_6.php new file mode 100644 index 00000000..2e069749 --- /dev/null +++ b/Week_04/id_6/LeetCode_70_6.php @@ -0,0 +1,22 @@ + $fee) { + $profit += ($prices[$i] - $min - $fee); + $min = $prices[$i] - $fee; + } + } + + return $profit; + } +} + +$prices = [1, 3, 2, 8, 4, 9]; +$fee = 2; +$sol = new Solution(); +var_dump($sol->maxProfit($prices, $fee)); \ No newline at end of file diff --git a/Week_04/id_6/LeetCode_78_6.php b/Week_04/id_6/LeetCode_78_6.php new file mode 100644 index 00000000..68044e4c --- /dev/null +++ b/Week_04/id_6/LeetCode_78_6.php @@ -0,0 +1,29 @@ +backTracing($nums, [], 0); + return $this->sets; + } + + private function backTracing($nums, $tmp, $i) + { + $this->sets[] = $tmp; + for ($j = $i; $j < count($nums); $j ++) { + $tmp[$j] = $nums[$j]; + $this->backTracing($nums, $tmp, $j + 1); + unset($tmp[$j]); + } + } +} + +$nums = [1,2,3]; +$sol = new Solution(); +var_dump($sol->subsets($nums)); \ No newline at end of file diff --git a/Week_04/id_6/NOTE.md b/Week_04/id_6/NOTE.md index 107ea7d6..b944e7ad 100644 --- a/Week_04/id_6/NOTE.md +++ b/Week_04/id_6/NOTE.md @@ -1 +1,67 @@ # 学习笔记 + +### 208 +- 定义节点类,根节点定义为空,数据结构为 +```php +class TrieNode +{ + public $children = []; + public $is_word = false; + public $val = null; + + function __construct($val = null) + { + $this->val = $val; + } +} +``` +- insert时,构建Trie树,最后一个节点 `is_word`设置为true,代表这里是单词结尾。 +- search时,遍历单词每一个字符,依次从根节点判断下来,当有一个节点不匹配则判断不存在,到最后一个节点,若is_word为true,那么判断为找到。 +- startWith原理同search类似,只是不用最后判断is_word。 + + +### 211 +同样是`字典树`的问题,只是由于涉及到通配符`.`,所以遇到`.`时需要递归求解。 + +### 212 +在`208`题trie树的基础上,使用trie树+DFS实现。 +基于words构建trie树,遍历board二维数组,对每一个遍历到的点,进行深度优先dfs搜索,成功匹配的点标记为已访问入visited数组,保证不重复访问之前遍历到的点。 +在每一个点遍历结束后,要记得清空visited已访问数组。 +基于一个点向上下左右四个方向进行DFS搜索时,每当一个方向DFS结束后,要重置当前点的visited值为0,切记!(在这里卡了我好久才发现问题) + +### 455 +1. 将输入的两个数组g,s有小到大排序。 +2. 依次遍历g内元素,依次取s内元素比较,当s内元素>=g内元素,次数+1并删除s内元素,依次循环下去。 + +### 714 +从头开始,先取第一个元素作为最小值,向后依次遍历比较; +当遇到当前价格<最小值的时候,设置当前价格为最小值; +当遇到当前价格-最小值>手续费的时候,便交易出去; +然后以当前价格-手续费作为新的最小值,继续遍历比较。 + +### 53 +对输入数组从头依次进行遍历,初始化以第一位数为max,每次累加遍历的数字得到和为sum。 +每次循环判断sum是否大于0,大于0则跟max进行比较,置max为两者最大值;小于0则判断前面的队列非最大值队列,置sum为当前num值,再继续进行比较,最后得出max。 + +### 78 +**回溯法。** +依次遍历输入数组,对遍历到的数字进行递归求子集,将每次所得放入结果集合中。 + +### 70 +经典的爬楼梯问题。 + +### 709 +**动态规划。** +从第一个价格开始向后遍历到最后一个价格,依次计算出当前价格卖出能获得的最大收益。 +因为要隔一天才能买入售卖后的新股票,所以总结出dp方程为: +``` +// j为当前价格向前遍历到第0个元素的每一个元素位置 +// $profit = $prices[$i] - $prices[$j] +// j<2时,无法进行新的买入操作,所以最大值是max(当前差额与之前所求当前位置最大值) +// j>=2时,最大值是max(当前卖出的差价+隔一天前所求最大值与当前位置之前所求最大值) +if ($j >= 2) { + $dp[$i] = max($profit + $dp[$j - 2], $dp[$i]); +} else { + $dp[$i] = max($profit, $dp[$i]); +} +``` \ No newline at end of file diff --git a/Week_04/id_7/LeetCode_200_169.cs b/Week_04/id_7/LeetCode_200_169.cs new file mode 100644 index 00000000..05c41c8b --- /dev/null +++ b/Week_04/id_7/LeetCode_200_169.cs @@ -0,0 +1,119 @@ +/* + * @lc app=leetcode.cn id=169 lang=csharp + * + * [169] 求众数 + */ +using System; +using System.Collections.Generic; + +public class Solution2 { + // 解法1 + // 暴力法,直接双层循环遍历所有数字,统计出现次数,大于nums.Length/2就直接返回 + // 优化点:记录之前统计过的数字,再次遇到,则不再统计 + // public int MajorityElement (int[] nums) { + // HashSet hs = new HashSet (); + // for (int i = 0; i < nums.Length; i++) { + // if (hs.Contains (nums[i])) { + // continue; + // } + // int count = 0; + // for (int j = 0; j < nums.Length; j++) { + // if (nums[i] == nums[j]) { count++; } + // } + // if (count > nums.Length / 2) { + // return nums[i]; + // } + // hs.Add (nums[i]); + // } + + // return 0; + // } + + // 解法2,肯定不是自己想出来的,看答案知道的 + // public int MajorityElement (int[] nums) { + // // 摩尔投票法 + // int zongshu = nums[0]; + // int count = 1; + + // for (int i = 1; i < nums.Length; i++) { + // if (zongshu == nums[i]) { + // count++; + // if (count > (nums.Length / 2)) { + // return zongshu; + // } + // } else { + // count--; + // } + + // if (count == 0) { + // zongshu = nums[i]; + // count = 1; + // } + // } + + // return zongshu; + // } + + // 解法3:哈希表,先简单遍历一下,记录所有数出现的次数,然后再遍历哈希表,找出答案 + // public int MajorityElement (int[] nums) { + // Dictionary dicCount = new Dictionary (); + // for (int i = 0; i < nums.Length; i++) { + // if (dicCount.ContainsKey (nums[i])) { + // dicCount[nums[i]]++; + // } else { + // dicCount.Add (nums[i], 1); + // } + // } + + // foreach (var item in dicCount) { + // if (item.Value > nums.Length / 2) { + // return item.Key; + // } + // } + + // return 0; + // } + + // 解法4:排序,方法肯定也不是我想出来的,使用标准函数进行排序,然后直接返回中间数,即为答案 + // public int MajorityElement (int[] nums) { + // Array.Sort (nums); + // return nums[nums.Length / 2]; + // } + + // 解法5 看答案,还有一个随机法,这个哪能想的出来,这么奇葩的方法,这里就不写了 + + // 方法6:分治法,这个才是今天的重点 + public int MajorityElement (int[] nums) { + return DivideConquer (nums, 0, nums.Length - 1); + } + + public int DivideConquer (int[] nums, int left, int right) { + if (left == right) { + return nums[left]; + } + + int mid = (right - left) / 2 + left; + int leftRes = DivideConquer (nums, left, mid); + int rightRes = DivideConquer (nums, mid + 1, right); + + if (leftRes == rightRes) { + return leftRes; + } + + int lftCount = GetCount (nums, leftRes, left, right); + int rgtCount = GetCount (nums, rightRes, left, right); + + return lftCount > rgtCount? leftRes : rightRes; + } + + public int GetCount (int[] nums, int curNum, int left, int right) { + int count = 0; + for (int i = left; i < right + 1; i++) { + if (curNum == nums[i]) + count++; + } + + return count; + } + +} \ No newline at end of file diff --git a/Week_04/id_7/LeetCode_200_455.cs b/Week_04/id_7/LeetCode_200_455.cs new file mode 100644 index 00000000..7c218b90 --- /dev/null +++ b/Week_04/id_7/LeetCode_200_455.cs @@ -0,0 +1,30 @@ +/* + * @lc app=leetcode.cn id=455 lang=csharp + * + * [455] 分发饼干 + */ +using System; + +public class Solution3 { + // 解法1:就是先排序,后暴力查找,计数,最后返回计数结果 + public int FindContentChildren (int[] g, int[] s) { + Array.Sort (g); + Array.Sort (s); + int count = 0; + int sIndex = 0; + for (int i = 0; i < g.Length; i++) { + for (int j = sIndex; j < s.Length; j++) { + if (s[j] >= g[i]) { + sIndex = j + 1; + count++; + if (j == s.Length - 1) { + return count; + } + break; + } + } + } + + return count; + } +} \ No newline at end of file diff --git a/Week_04/id_7/LeetCode_200_70.cs b/Week_04/id_7/LeetCode_200_70.cs new file mode 100644 index 00000000..4f81ee1f --- /dev/null +++ b/Week_04/id_7/LeetCode_200_70.cs @@ -0,0 +1,54 @@ +/* + * @lc app=leetcode.cn id=70 lang=csharp + * + * [70] 爬楼梯 + */ +using System.Collections.Generic; + +public class Solution { + // 方法1: 暴力法+记忆化 + // Dictionary dic = new Dictionary (); + // public int ClimbStairs (int n) { + // if (n == 1) { + // return 1; + // } + + // if (n == 2) { + // return 2; + // } + + // int A; + // if (dic.ContainsKey (n - 1)) { + // A = dic[n - 1]; + // } else { + // A = ClimbStairs (n - 1); + // dic.Add (n - 1, A); + // } + + // int B; + // if (dic.ContainsKey (n - 2)) { + // B = dic[n - 2]; + // } else { + // B = ClimbStairs (n - 2); + // dic.Add (n - 2, B); + // } + + // return A + B; + // } + + // 方法2:动态规划,当然不是我自己想出来的😂 + public int ClimbStairs (int n) { + if (n == 1) { + return 1; + } + + int[] dp = new int[n + 1]; + dp[1] = 1; + dp[2] = 2; + for (int i = 3; i <= n; i++) { + dp[i] = dp[i - 1] + dp[i - 2]; + } + + return dp[n]; + } +} \ No newline at end of file diff --git a/Week_04/id_7/LeetCode_200_720.cs b/Week_04/id_7/LeetCode_200_720.cs new file mode 100644 index 00000000..974afb0a --- /dev/null +++ b/Week_04/id_7/LeetCode_200_720.cs @@ -0,0 +1,120 @@ +/* + * @lc app=leetcode.cn id=720 lang=csharp + * + * [720] 词典中最长的单词 + */ +using System; +using System.Collections.Generic; + +public class Solution1 { + // 方法1 + // 先排序,后将所有单词放入集合中,遍历每一个单词, + // 然后对于每个单词进行每次去除末尾一个字母的循环操作, + // 如果可以执行到单词长度为0,则与strRes进行比较,比strRes长,则替换strRes + // public string LongestWord (string[] words) { + // if (words.Length == 1) { + // return words[0]; + // } + + // Array.Sort (words); + // string strRes = words[0]; + + // HashSet hsWord = new HashSet (); + // foreach (var word in words) { + // hsWord.Add (word); + // } + + // foreach (var word in words) { + // if (word.Length <= 1 || word.Length <= strRes.Length) { + // continue; + // } + // string temp = word; + // while (temp.Length > 0) { + // if (!hsWord.Contains (temp)) { + // break; + // } + // temp = temp.Substring (0, temp.Length - 1); + // if (temp.Length == 0 && strRes.Length < word.Length) { + // strRes = word; + // } + // } + // } + + // return strRes; + // } + + // 方法2 + // 构建字典树(Trie),再使用深度优先遍历(dfs)遍历所有节点,找到最长单词 + // 注意点:需要存储字典树中每个节点对应的单词的位置,即代码中end,这样在深度优先比例时,可以直接从数组中取得对应单词 + // dfs,当前代码使用的是非递归,也可以使用递归 + // 此代码从国际版的官方解法中获得 + class Node { + char c; + public Dictionary children = new Dictionary (); + public int end; + public Node (char c) { + this.c = c; + } + } + + class Trie { + Node root; + public string[] words; + + public Trie () { + root = new Node ('0'); + } + + public void insert (string word, int index) { + Node cur = root; + for (int i = 0; i < word.Length; i++) { + if (cur.children.ContainsKey (word[i])) { + if (cur.children[word[i]] == null) { + cur.children[word[i]] = new Node (word[i]); + } + } else { + cur.children.Add (word[i], new Node (word[i])); + } + + cur = cur.children[word[i]]; + } + + cur.end = index; + } + + public string dfs () { + string ans = ""; + Stack sk = new Stack (); + sk.Push (root); + while (sk.Count > 0) { + Node node = sk.Pop (); + if (node.end < 1 && node != root) { + continue; + } + if (node != root) { + string word = words[node.end - 1]; + if (word.Length > ans.Length || word.Length == ans.Length && word.CompareTo (ans) < 0) { + ans = word; + } + } + + foreach (var v in node.children.Values) { + sk.Push (v); + } + } + + return ans; + } + } + + public string LongestWord (string[] words) { + Trie trie = new Trie (); + int index = 0; + foreach (var word in words) { + trie.insert (word, ++index); + } + trie.words = words; + + return trie.dfs (); + } +} \ No newline at end of file diff --git a/Week_04/id_7/LeetCode_200_784.cs b/Week_04/id_7/LeetCode_200_784.cs new file mode 100644 index 00000000..2ae47a18 --- /dev/null +++ b/Week_04/id_7/LeetCode_200_784.cs @@ -0,0 +1,71 @@ +/* + * @lc app=leetcode.cn id=784 lang=csharp + * + * [784] 字母大小写全排列 + */ +using System.Collections.Generic; + +public class Solution4 { + // 方法1:BFS 不是自己想出来的,从国际版上讨论区学习到的 + // public IList LetterCasePermutation (string S) { + // if (S == null) { + // return new List (); + // } + + // Queue que = new Queue (); + // que.Enqueue (S); + + // for (int i = 0; i < S.Length; i++) { + // if (S[i] >= 48 && S[i] <= 57) continue; + // int size = que.Count; + // for (int j = 0; j < size; j++) { + // string cur = que.Dequeue (); + // // 先把自己加进去 + // que.Enqueue (cur); + + // char[] chs = cur.ToCharArray (); + + // if (chs[i] >= 65 && chs[i] <= 90) { + // // 原本大写的话,这里就转小写 + // chs[i] = char.ToLower (chs[i]); + // que.Enqueue (new string (chs)); + // } else { + // // 否则转大写 + // chs[i] = char.ToUpper (chs[i]); + // que.Enqueue (new string (chs)); + // } + // } + // } + + // return new List (que); + // } + + // 方法2:DFS 同样也不是自己想出来的 + public IList LetterCasePermutation (string S) { + if (S == null) { + return new List (); + } + List lstRes = new List (); + dfs (S.ToCharArray (), lstRes, 0); + + return lstRes; + } + + public void dfs (char[] chs, List lst, int index) { + if (index == chs.Length) { + lst.Add (new string (chs)); + return; + } + + if (chs[index] >= '0' && chs[index] <= '9') { + dfs (chs, lst, index + 1); + return; + } + + chs[index] = char.ToLower (chs[index]); + dfs (chs, lst, index + 1); + + chs[index] = char.ToUpper (chs[index]); + dfs (chs, lst, index + 1); + } +} \ No newline at end of file diff --git a/Week_04/id_8/Leetcode_455_8.java b/Week_04/id_8/Leetcode_455_8.java new file mode 100644 index 00000000..69043976 --- /dev/null +++ b/Week_04/id_8/Leetcode_455_8.java @@ -0,0 +1,15 @@ +class Solution { + public int findContentChildren(int[] g, int[] s) { + int child = 0; + int cookie = 0; + Arrays.sort(g); + Arrays.sort(s); + while (child < g.length && cookie < s.length ){ + if (g[child] <= s[cookie]){ + child++; + } + cookie++; + } + return child; + } +} \ No newline at end of file diff --git a/Week_04/id_8/Leetcode_70_8(2).java b/Week_04/id_8/Leetcode_70_8(2).java new file mode 100644 index 00000000..6cc08995 --- /dev/null +++ b/Week_04/id_8/Leetcode_70_8(2).java @@ -0,0 +1,16 @@ +class Solution { + public int climbStairs(int n) { + if(n<=0) return 0; + if(n==1) return 1; + if(n==2) return 2; + int one_step_before=2; + int two_step_before=1; + int total=0; + for(int i=3;i<=n;i++){ + total=one_step_before+two_step_before; + two_step_before=one_step_before; + one_step_before=total; + } + return total; + } +} \ No newline at end of file diff --git a/Week_04/id_8/Leetcode_70_8.java b/Week_04/id_8/Leetcode_70_8.java new file mode 100644 index 00000000..b8324268 --- /dev/null +++ b/Week_04/id_8/Leetcode_70_8.java @@ -0,0 +1,22 @@ +class Solution { + HashMap map = new HashMap<>(); + + public int climbStairsHelper(int n, HashMap map) { + if (n == 1) { + return 1; + } + if (n == 2) { + return 2; + } + if (map.containsKey(n)) { + return map.get(n); + } else { + map.put(n,climbStairs(n-2)+climbStairs(n-1)); + return climbStairs(n-2)+climbStairs(n-1); + } + } + + public int climbStairs(int n) { + return climbStairsHelper(n, map); + } +} \ No newline at end of file diff --git a/Week_04/id_8/NOTE.md b/Week_04/id_8/NOTE.md index 107ea7d6..2fd8f039 100644 --- a/Week_04/id_8/NOTE.md +++ b/Week_04/id_8/NOTE.md @@ -1 +1,6 @@ # 学习笔记 + +递推公式: +f(n) = f(n-1)+f(n-2) +分解子问题,f(n-1)和f(-2)解决了,f(n)自然解决了。 +比如求 f(3),只要知道f(2)和f(1)的数值,根据递推公式,就能递推出f(3)的值 diff --git a/Week_04/id_9/LeetCode_211_9.java b/Week_04/id_9/LeetCode_211_9.java new file mode 100644 index 00000000..b24a574a --- /dev/null +++ b/Week_04/id_9/LeetCode_211_9.java @@ -0,0 +1,130 @@ +package com.github.lifelab.leetcode.problemset; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.regex.Pattern; + +/** + * 添加与搜索单词 - 数据结构设计 @see https://leetcode-cn.com/problems/add-and-search-word-data-structure-design/ + * + * @author Weichao Li (liweichao0102@gmail.com) + * @since 2019-06-30 + */ +public class Solution211 { + + /** + * hash + cache 实现 + */ + public class WordDictionary1 { + + private Map wd; + + private Map cache; + + /** + * Initialize your data structure here. + */ + public WordDictionary1() { + this.wd = new HashMap<>(); + this.cache = new HashMap<>(); + } + + /** + * Adds a word into the data structure. + */ + public void addWord(String word) { + wd.put(word, word); + } + + /** + * Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. + */ + public boolean search(String word) { + Boolean cacheValue = cache.get(word); + if (Objects.nonNull(cacheValue) && cacheValue) { + return cacheValue; + } else { + cacheValue = wd.keySet().parallelStream().anyMatch(e -> Pattern.matches(word, e)); + cache.put(word, cacheValue); + } + return cacheValue; + } + + } + + /** + * tree 实现 + */ + public class WordDictionary2 { + + class Node { + + private Node[] next; + + private boolean isWord; + + public Node() { + next = new Node[26]; + isWord = false; + } + } + + private Node root; + + /** + * Initialize your data structure here. + */ + public WordDictionary2() { + root = new Node(); + } + + /** + * Adds a word into the data structure. + */ + public void addWord(String word) { + int len = word.length(); + Node curNode = root; + for (int i = 0; i < len; i++) { + char curChar = word.charAt(i); + Node next = curNode.next[curChar - 'a']; + if (next == null) { + curNode.next[curChar - 'a'] = new Node(); + } + curNode = curNode.next[curChar - 'a']; + } + if (!curNode.isWord) { + curNode.isWord = true; + } + } + + /** + * Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. + */ + public boolean search(String word) { + return match(word, root, 0); + } + + private boolean match(String word, Node node, int start) { + if (start == word.length()) { + return node.isWord; + } + char alpha = word.charAt(start); + if (alpha == '.') { + for (int i = 0; i < 26; i++) { + if (node.next[i] != null && match(word, node.next[i], start + 1)) { + return true; + } + } + return false; + } else { + if (node.next[alpha - 'a'] == null) { + return false; + + } + return match(word, node.next[alpha - 'a'], start + 1); + } + } + } + +} \ No newline at end of file diff --git a/Week_04/id_9/LeetCode_78_9.java b/Week_04/id_9/LeetCode_78_9.java new file mode 100644 index 00000000..45e96c72 --- /dev/null +++ b/Week_04/id_9/LeetCode_78_9.java @@ -0,0 +1,39 @@ +package com.github.lifelab.leetcode.problemset; + +import java.util.LinkedList; +import java.util.List; + +/** + * 子集 @see https://leetcode-cn.com/problems/subsets/ + * + * @author Weichao Li (liweichao0102@gmail.com) + * @since 2019-06-30 + */ +public class Solution78 { + + public List> subsets(int[] nums) { + + List> list = new LinkedList<>(); + traverse(nums, 0, list, new LinkedList<>()); + return list; + + } + + private void traverse(int[] nums, int index, List> list, List currentList) { + + // terminator + if (nums.length == index) { + list.add(currentList); + return; + } + + // process & drill down + List target = new LinkedList<>(currentList); + + target.add(nums[index]); + + traverse(nums, index + 1, list, currentList); + + traverse(nums, index + 1, list, target); + } +} \ No newline at end of file