From 2d9f4774f0359f5233293e3d7e4e675a514ecf2e Mon Sep 17 00:00:00 2001 From: liu13 <1099976891@qq.com> Date: Wed, 20 Mar 2019 10:14:26 +0800 Subject: [PATCH] 20190320 --- code/lc112.java | 30 ++++++++++++++++++++++++++++++ code/lc113.java | 2 +- code/lc124.java | 2 +- code/lc129.java | 28 ++++++++++++++++++++++++++++ code/lc151.java | 19 +++++++++++++++++++ code/lc236.java | 6 +++--- code/lc239.java | 6 +++--- code/lc268.java | 4 ++-- code/lc279.java | 2 +- code/lc287.java | 3 ++- code/lc303.java | 1 + code/lc337.java | 3 ++- code/lc378.java | 1 + code/lc395.java | 2 +- code/lc416.java | 3 ++- code/lc437.java | 26 ++++---------------------- code/lc448.java | 2 +- code/lc494.java | 5 ++++- code/lc538.java | 13 +++++-------- code/lc543.java | 2 +- code/lc560.java | 1 + code/lc617.java | 8 +++----- 22 files changed, 116 insertions(+), 53 deletions(-) create mode 100644 code/lc112.java create mode 100644 code/lc129.java create mode 100644 code/lc151.java diff --git a/code/lc112.java b/code/lc112.java new file mode 100644 index 0000000..c3bdd82 --- /dev/null +++ b/code/lc112.java @@ -0,0 +1,30 @@ +package code; +/* + * 112. Path Sum + * 题意:是否存在跟到叶子节点的和为sum + * 难度:Easy + * 分类: + * 思路: + * Tips:lc112, lc113, lc437, lc129, lc124, lc337 + * 总结一下 lc112 找跟到叶子和为sum的路径是否存在 + * lc113 把lc112的路径找出来 + * lc437 是任意一条向下走的路径 + * lc129 计算所有的和 + * lc124 任意一条路径 + * lc337 树的dp + */ +public class lc112 { + public class TreeNode { + int val; + TreeNode left; + TreeNode right; + TreeNode(int x) { + val = x; + } + } + public boolean hasPathSum(TreeNode root, int sum) { + if(root==null) return false; + if(root.val==sum&&root.left==null&&root.right==null) return true; + return hasPathSum(root.left, sum-root.val)||hasPathSum(root.right, sum-root.val); + } +} diff --git a/code/lc113.java b/code/lc113.java index 6d555e2..b8515e0 100644 --- a/code/lc113.java +++ b/code/lc113.java @@ -8,7 +8,7 @@ import java.util.List; * 难度:Medium * 分类:Tree, Depth-first Search * 思路:回溯,注意因为节点上可能正值,可能负值,所以不能剪枝 - * Tips:lc124 + * Tips:lc112, lc113, lc437, lc129, lc124, lc337 */ public class lc113 { public class TreeNode { diff --git a/code/lc124.java b/code/lc124.java index 3546ba7..2548775 100644 --- a/code/lc124.java +++ b/code/lc124.java @@ -6,7 +6,7 @@ package code; * 分类:Tree, Depth-first Search * 思路:因为二叉树只有两个节点,一条路径可以想象成倒V字,从低层的某个节点一路向上,到达一个顶点,再一路向下,理解了这一点,整道题就好解了。 * Tips:用了一个全局变量存储最后结果,因为函数返回的是直线路径上的最优解,而不是V字路径最优解 - * lc133 + * lc112, lc113, lc437, lc129, lc124, lc337, lc543 */ public class lc124 { public class TreeNode { diff --git a/code/lc129.java b/code/lc129.java new file mode 100644 index 0000000..736ddb4 --- /dev/null +++ b/code/lc129.java @@ -0,0 +1,28 @@ +package code; +/* + * 129. Sum Root to Leaf Numbers + * 题意:一条路径上的数字组成一个数字,求所有从跟到叶子的路径和 + * 难度:Medium + * 分类:Tree, Depth-first Search + * 思路:dfs + * Tips:lc112, lc113, lc437, lc129, lc124, lc337 + */ +public class lc129 { + public class TreeNode { + int val; + TreeNode left; + TreeNode right; + TreeNode(int x) { + val = x; + } + } + public int sumNumbers(TreeNode root) { + if(root==null) return 0; + return helper(root, 0); + } + public int helper(TreeNode root, int sum){ + if(root==null) return 0; //一条路径,另一边返回0 + if(root.left==null&&root.right==null) return sum*10+root.val; //这点注意,是叶子节点直接返回了 + return helper(root.left, sum*10+root.val) + helper(root.right, sum*10+root.val); + } +} diff --git a/code/lc151.java b/code/lc151.java new file mode 100644 index 0000000..9b7f9f0 --- /dev/null +++ b/code/lc151.java @@ -0,0 +1,19 @@ +package code; + +import java.util.Arrays; +import java.util.Collections; +/* + * 151. Reverse Words in a String + * 题意:反转字符串中的单词 + * 难度:Medium + * 分类:String + * 思路:难点在中间的空格可能是多个空格,注意如何解决 + * Tips: + */ +public class lc151 { + public String reverseWords(String s) { + String[] words = s.trim().split(" +"); //+号匹配多个 + Collections.reverse(Arrays.asList(words)); + return String.join(" ", words); + } +} diff --git a/code/lc236.java b/code/lc236.java index 24539b1..fb0b274 100644 --- a/code/lc236.java +++ b/code/lc236.java @@ -35,7 +35,7 @@ public class lc236 { parent.put(root, null); stack.push(root); - while (!parent.containsKey(p) || !parent.containsKey(q)) { + while (!parent.containsKey(p) || !parent.containsKey(q)) { //遍历了一遍节点,把节点的父节点信息记录了一下 TreeNode node = stack.pop(); if (node.left != null) { parent.put(node.left, node); @@ -47,11 +47,11 @@ public class lc236 { } } Set ancestors = new HashSet<>(); - while (p != null) { + while (p != null) { //p的路径节点添加到hashset中 ancestors.add(p); p = parent.get(p); } - while (!ancestors.contains(q)) + while (!ancestors.contains(q)) //第一个hashset中遇到的节点,就是最近公共祖先 q = parent.get(q); return q; } diff --git a/code/lc239.java b/code/lc239.java index 1b33167..3044d85 100644 --- a/code/lc239.java +++ b/code/lc239.java @@ -1,10 +1,10 @@ package code; /* * 239. Sliding Window Maximum - * 题意:滑动窗口最大值 + * 题意:滑动窗口中最大值 * 难度:Hard * 分类:Heap - * 思路:用双向队列,保证队列里是递增的。单调队列,好好学习一下。 + * 思路:用双向队列,保证队列里是递减的。单调队列,好好学习一下。 * Tips:与lc84做比较,84是递增栈 */ import java.util.ArrayDeque; @@ -25,7 +25,7 @@ public class lc239 { return new int[]{}; int[] res = new int[nums.length-k+1]; int cur = 0; - Deque dq = new ArrayDeque(); + Deque dq = new ArrayDeque(); //队列里是递减的 for (int i = 0; i < nums.length ; i++) { if( !dq.isEmpty() && dq.peekFirst()<=i-k) dq.removeFirst(); diff --git a/code/lc268.java b/code/lc268.java index abd2552..30e4f4f 100644 --- a/code/lc268.java +++ b/code/lc268.java @@ -7,7 +7,7 @@ package code; * 思路:两种巧妙的方法,时间空间都是O(1) * 异或 * 求和以后,减去所有 - * Tips: + * Tips:lc268 lc448 lc287 */ public class lc268 { public int missingNumber(int[] nums) { @@ -16,7 +16,7 @@ public class lc268 { return res; } public int missingNumber2(int[] nums) { - int res = nums.length; + int res = nums.length; //异或上长度 for(int i=0; i mem){ if(root==null) return 0; - if(mem.containsKey(root)) //用mem去记忆一下资情况的结果,防止重复计算 + if(mem.containsKey(root)) //用mem去记忆一下子情况的结果,防止重复计算 return mem.get(root); int val =0; if(root.left!=null){ diff --git a/code/lc378.java b/code/lc378.java index e9d398e..07076ef 100644 --- a/code/lc378.java +++ b/code/lc378.java @@ -11,6 +11,7 @@ import java.util.PriorityQueue; * 思路:两种思路。 1是类似多个有序链表合并的思路,优先队列。 * 2是二分,二分的是val,看比这个val小的数是不是k * Tips:lc23方法很像 + * lc240 */ public class lc378 { class Cell{ diff --git a/code/lc395.java b/code/lc395.java index 1270e8e..2867448 100644 --- a/code/lc395.java +++ b/code/lc395.java @@ -23,7 +23,7 @@ public class lc395 { if( cur_uni_char==i && less_than_k_char==i) res = Math.max(res, right-left); - else if(cur_uni_char>i){ //左边推进 + else if(cur_uni_char>i){ //左边推进。不在外边加上一个循环的话,就不知道怎么推荐左指针了。 while(cur_uni_char!=i){ map[s.charAt(left)-'a']--; if(map[s.charAt(left)-'a']==0) cur_uni_char--; diff --git a/code/lc416.java b/code/lc416.java index 896aad1..ee1d578 100644 --- a/code/lc416.java +++ b/code/lc416.java @@ -9,7 +9,8 @@ import java.util.HashSet; * 思路:题意可以转换为用任意个元素组成的和等于数组和/2。可以和 lc1, lc15 3-Sum 对比。 * 0,1背包问题,递推比较简单,所以空间可以压缩成一维 * 自己想的思路其实和压缩后的0,1背包类似,但没想到该问题可以抽象为0,1背包 - * Tips: + * dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i]] + * Tips:lc416, lc494 */ public class lc416 { public static void main(String[] args) { diff --git a/code/lc437.java b/code/lc437.java index 1bf0e30..36a8326 100644 --- a/code/lc437.java +++ b/code/lc437.java @@ -12,35 +12,19 @@ import java.util.HashMap; * 递归的时候用减是否==0的方式,而不是+==sum的方式 * 和lc560有共同的思想,每个节点只需遍历一遍就可以了 * 虽然是Easy题,做好也不简单 + * lc112, lc113, lc437, lc129, lc124, lc337 + * lc303, lc437, lc560 */ public class lc437 { public static class TreeNode { int val; TreeNode left; TreeNode right; - TreeNode(int x) { val = x; } } - public static void main(String[] args) { - TreeNode node10 = new TreeNode(10); - TreeNode node5 = new TreeNode(5); - TreeNode node3 = new TreeNode(3); - TreeNode node2 = new TreeNode(2); - TreeNode node1 = new TreeNode(1); - TreeNode noden3 = new TreeNode(-3); - TreeNode node11 = new TreeNode(11); - node10.left = node5; - node10.right = noden3; - node5.left = node3; - node5.right = node2; - node2.right = node1; - noden3.right = node11; - System.out.println(pathSum2(node10, 8)); - } - public static int pathSum(TreeNode root, int sum) { //该节点作为起点 if (root == null) return 0; @@ -48,10 +32,8 @@ public class lc437 { } public static int dfs(TreeNode root, int sum) { //一条路径向下走 - if (root == null) - return 0; - if (root.val == sum) - return 1 + dfs(root.left, sum - root.val) + dfs(root.right, sum - root.val);//不要直接返回1,因为可能后边节点,或节点和为0 + if (root == null) return 0; + if (root.val == sum) return 1 + dfs(root.left, sum - root.val) + dfs(root.right, sum - root.val);//不要直接返回1,因为可能后边节点,或节点和为0 return dfs(root.left, sum - root.val) + dfs(root.right, sum - root.val); } diff --git a/code/lc448.java b/code/lc448.java index 802765b..364b76b 100644 --- a/code/lc448.java +++ b/code/lc448.java @@ -9,7 +9,7 @@ import java.util.List; * 难度:Easy * 分类:Array * 思路:把对应的数字放到对应的位置,最后遍历一遍,如果位置和数字不对应,则为缺失的值。 - * Tips: + * Tips:lc268 lc448 lc287 */ public class lc448 { public static void main(String[] args) { diff --git a/code/lc494.java b/code/lc494.java index 8bed557..26718d3 100644 --- a/code/lc494.java +++ b/code/lc494.java @@ -5,7 +5,10 @@ package code; * 难度:Medium * 分类:Dynamic Programming, Depth-first Search * 思路:可以用递归+mem的方法。也可以转化为0,1背包问题,注意dp的时候把下标移位。另一种方法是转化为子数组的和为(target + sum(nums))/2的问题,求解方法类似lc416 - * Tips:多抽象总结一下相关的问题,如何抽象出背包。对于这个数字,要么+,要么-,就两种情况。 + * Tips:多抽象总结一下相关的问题,如何抽象出背包。对于这个数字,要么+,要么-,就两种情况。https://leetcode.com/problems/target-sum/discuss/97335/Short-Java-DP-Solution-with-Explanation + * dp[i][j] 表示前i个元素和为j的方案个数 + * dp[i][j] = dp[i-1][j-nums[j]] + dp[i-1][j+nums[j]] //加减两种方案加起来 + * lc416, lc494 */ public class lc494 { public int findTargetSumWays(int[] nums, int S) { diff --git a/code/lc538.java b/code/lc538.java index e8a616d..2c9e782 100644 --- a/code/lc538.java +++ b/code/lc538.java @@ -17,14 +17,11 @@ public class lc538 { } int sum = 0; public TreeNode convertBST(TreeNode root) { - helper(root); + if(root==null) return null; + convertBST(root.right); + sum += root.val; + root.val = sum; + convertBST(root.left); return root; } - public void helper(TreeNode root){ - if(root==null) return; - helper(root.right); - root.val = root.val + sum; - sum = root.val; - helper(root.left); - } } diff --git a/code/lc543.java b/code/lc543.java index 08c543b..6e77a3c 100644 --- a/code/lc543.java +++ b/code/lc543.java @@ -1,7 +1,7 @@ package code; /* * 543. Diameter of Binary Tree - * 题意:树种的最长路径 + * 题意:树中的最长路径 * 难度:Easy * 分类:Tree * 思路:和lc124思路一样,但lc124是Hard,这道竟然是Easy,哈哈哈 diff --git a/code/lc560.java b/code/lc560.java index fd75474..f5eb844 100644 --- a/code/lc560.java +++ b/code/lc560.java @@ -9,6 +9,7 @@ import java.util.HashMap; * 分类:Array, Hash Table * 思路:求出累加和存在hashmap中,如果当前hashmap中存在sum-k,那么就是一个解 * Tips:经典思路,记一下。lc437有类似思想。 + * lc303, lc437, lc560 */ public class lc560 { public int subarraySum(int[] nums, int k) { diff --git a/code/lc617.java b/code/lc617.java index 0927852..52913b2 100644 --- a/code/lc617.java +++ b/code/lc617.java @@ -42,13 +42,11 @@ public class lc617 { } public TreeNode mergeTrees2(TreeNode t1, TreeNode t2) { - if (t1 == null) - return t2; - if (t2 == null) - return t1; - t1.val += t2.val; + if(t1==null) return t2; //这里注意一下,比较难想明白,可以记一下 + if(t2==null) return t1; t1.left = mergeTrees(t1.left, t2.left); t1.right = mergeTrees(t1.right, t2.right); + t1.val += t2.val; return t1; } } -- GitLab