diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/second/T47_114_Flatten.java b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T47_114_Flatten.java index be1b240..6228ff1 100644 --- a/Leecode/src/main/java/com/markilue/leecode/hot100/second/T47_114_Flatten.java +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T47_114_Flatten.java @@ -20,19 +20,39 @@ public class T47_114_Flatten { TreeNode temp = root; - while (temp.right != null||temp.left!=null) { + while (temp.right != null || temp.left != null) { if (temp.left != null) { TreeNode cur = temp.left; while (cur.right != null) { cur = cur.right;//寻找左子树的最右节点 } - cur.right=temp.right; + cur.right = temp.right; temp.right = temp.left; - temp.left=null; + temp.left = null; } else { temp = temp.right; } } } + + //二刷:本质上就是找到左子树的最右节点,把他的右子树拼到这个最右节点上 + public void flatten1(TreeNode root) { + if (root == null) { + return; + } + if (root.left != null) { + TreeNode left = root.left; + while (left.right != null) { + left = left.right; + } + left.right = root.right; + root.right = root.left; + root.left = null; + } + flatten1(root.right); + + } + + } diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/second/T48_121_MaxProfit.java b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T48_121_MaxProfit.java new file mode 100644 index 0000000..e99b582 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T48_121_MaxProfit.java @@ -0,0 +1,60 @@ +package com.markilue.leecode.hot100.second; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hot100.second + *@Author: markilue + *@CreateTime: 2023-05-09 10:00 + *@Description: + * TODO 力扣121 买卖股票的最佳时机: + * 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 + * 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 + * 返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。 + *@Version: 1.0 + */ +public class T48_121_MaxProfit { + + //只能某一天买入:贪心 + public int maxProfit(int[] prices) { + int min = prices[0]; + int maxProfit = 0; + int cur; + + for (int i = 1; i < prices.length; i++) { + cur = prices[i] - min; + if (cur > maxProfit) maxProfit = cur; + if (min > prices[i]) min = prices[i]; + } + + return maxProfit; + + } + + //只能某一天买入:动态规划 + public int maxProfit1(int[] prices) { + + int[][] dp = new int[prices.length][2]; + dp[0][0] = 0; + dp[0][1] = -prices[0]; + for (int i = 1; i < prices.length; i++) { + dp[i][0] = Math.max(dp[i - 1][0], prices[i] + dp[i - 1][1]); + dp[i][1] = Math.max(-prices[i], dp[i - 1][1]); + } + + return Math.max(dp[prices.length - 1][0], dp[prices.length - 1][1]); + } + + + //只能某一天买入:滚动数组优化 + public int maxProfit2(int[] prices) { + + int dp0 = 0; + int dp1 = -prices[0]; + for (int i = 1; i < prices.length; i++) { + dp0 = Math.max(dp0, prices[i] + dp1); + dp1 = Math.max(-prices[i], dp1); + } + + return Math.max(dp0, dp1); + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/second/T49_124_MaxPathSum.java b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T49_124_MaxPathSum.java new file mode 100644 index 0000000..7fc9d18 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T49_124_MaxPathSum.java @@ -0,0 +1,64 @@ +package com.markilue.leecode.hot100.second; + +import com.markilue.leecode.tree.TreeNode; +import com.markilue.leecode.tree.TreeUtils; +import org.junit.Test; + +import java.util.Arrays; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hot100.second + *@Author: markilue + *@CreateTime: 2023-05-09 10:16 + *@Description: TODO 力扣124 二叉树中的最大路径和: + *@Version: 1.0 + */ +public class T49_124_MaxPathSum { + + @Test + public void test() { + TreeNode root = TreeUtils.structureTree(Arrays.asList(-10, 9, 20, null, null, 15, 7), 0); + System.out.println(maxPathSum(root)); + } + + + int maxSum = Integer.MIN_VALUE; + + + /** + * 本质上就是:计算完左右子树的最大和,来确定要左边还是要右边,然后继续遍历;而当前位置的最大就是左右之和+自己或者左边或者右边 + * @param root + * @return + */ + public int maxPathSum(TreeNode root) { + maxSum = root.val; + getMax(root); + + return maxSum; + + } + + /** + * 获取当前节点位置的最大和 + * @param root + * @return + */ + public int getMax(TreeNode root) { + if (root == null) { + return 0; + } + + int left = Math.max(getMax(root.left), 0); + int right = Math.max(getMax(root.right), 0); + + //为什么不考虑不要当前的:因为,不要当前的在子树当中就已经考虑过了 + int curMax = root.val + left + right; + if (maxSum < curMax) maxSum = curMax; + + return root.val+Math.max(left,right); + + + } + +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/second/T50_128_LongestConsecutive.java b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T50_128_LongestConsecutive.java index 72b6b3d..3dd17ec 100644 --- a/Leecode/src/main/java/com/markilue/leecode/hot100/second/T50_128_LongestConsecutive.java +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T50_128_LongestConsecutive.java @@ -1,5 +1,7 @@ package com.markilue.leecode.hot100.second; +import org.junit.Test; + import java.math.BigDecimal; import java.math.RoundingMode; import java.util.HashMap; @@ -18,6 +20,12 @@ import java.util.HashSet; */ public class T50_128_LongestConsecutive { + @Test + public void test() { + int[] nums = {100, 4, 200, 1, 3, 2}; + System.out.println(longestConsecutive2(nums)); + } + /** * 思路:用hashset记录所有,记录最大的值 @@ -78,7 +86,7 @@ public class T50_128_LongestConsecutive { //从最小值开始遍历寻找合适的 for (Integer s : set) { - if(!set.contains(s-1)){//只从最小的开始找 + if (!set.contains(s - 1)) {//只从最小的开始找 int cur = 1; int tempHight = s; while (set.contains(tempHight + 1)) { @@ -95,5 +103,32 @@ public class T50_128_LongestConsecutive { return result; + } + + //二刷:利用hashset来使用O(1)获取其邻接的值 + public int longestConsecutive2(int[] nums) { + + HashSet set = new HashSet<>(); + for (int num : nums) { + set.add(num); + } + + int maxLength = 0; + + //挨个遍历:注意这里用set遍历,速度会快很多 + for (int num : set) { + if (!set.contains(num - 1)) { + int curLength = 1; + while (set.contains(num + 1)) { + curLength++; + num++; + } + if (curLength > maxLength) maxLength = curLength; + } + } + + return maxLength; + + } } diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/second/T51_136_SingleNumber.java b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T51_136_SingleNumber.java new file mode 100644 index 0000000..0ab13f4 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T51_136_SingleNumber.java @@ -0,0 +1,33 @@ +package com.markilue.leecode.hot100.second; + +import org.junit.Test; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hot100.second + *@Author: markilue + *@CreateTime: 2023-05-09 10:54 + *@Description: TODO 力扣136 只出现一次的数字 + *@Version: 1.0 + */ +public class T51_136_SingleNumber { + + @Test + public void test(){ + int[] nums={2,2,1}; +// int[] nums={2}; + System.out.println(singleNumber(nums)); + } + + //只出现一次,其他都两次,可以考虑使用位运算:异或,异或两次相同的数就会变为原来的数 + public int singleNumber(int[] nums) { + + int cur = 0;//0异或任何数,都等于那个数 + for (int num : nums) { + cur ^= num; + } + + return cur; + + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/second/T52_139_WordBreak.java b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T52_139_WordBreak.java new file mode 100644 index 0000000..7a86d7c --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T52_139_WordBreak.java @@ -0,0 +1,107 @@ +package com.markilue.leecode.hot100.second; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hot100.second + *@Author: markilue + *@CreateTime: 2023-05-09 11:03 + *@Description: TODO 力扣139 单词拆分 + *@Version: 1.0 + */ +public class T52_139_WordBreak { + + @Test + public void test() { + String s = "leetcode"; + List wordDict = Arrays.asList("leet", "code"); + System.out.println(wordBreak(s, wordDict)); + } + + @Test + public void test1() { + String s = "applepenapple"; + List wordDict = Arrays.asList("apple", "pen"); + System.out.println(wordBreak(s, wordDict)); + } + + //7ms + public boolean wordBreak(String s, List wordDict) { + + //以i开头,以j结尾的s能否凑出来 + boolean[] dp = new boolean[s.length() + 1]; + dp[0] = true; + HashSet set = new HashSet<>(wordDict); + + for (int i = 0; i < dp.length; i++) { + for (int j = i; j >= 0; j--) { + if (dp[j] && set.contains(s.substring(j, i))) { + dp[i] = true; + } + } + } + + return dp[s.length()]; + + } + + + //3ms + public boolean wordBreak1(String s, List wordDict) { + + //以i开头,以j结尾的s能否凑出来 + boolean[] dp = new boolean[s.length() + 1]; + dp[0] = true; + + for (int i = 0; i < dp.length; i++) { + for (String s1 : wordDict) { + int length = s1.length(); + if (i >= length) dp[i] |= dp[i - length] && s1.equals(s.substring(i - length, i)); + if (dp[i]) break; + } + } + return dp[s.length()]; + + } + + + //回溯+记忆化搜索 + int[] memo; + + public boolean wordBreak2(String s, List wordDict) { + memo = new int[s.length() + 1]; + Arrays.fill(memo, -1); + return dfs(s, wordDict, s.length()); + } + + public boolean dfs(String s, List wordDict, int i) { + + if (i == 0) { + memo[i] = 1; + return true; + } + if (memo[i] != -1) { + return memo[i] == 1; + } + + boolean flag = false; + for (String s1 : wordDict) { + int length = s1.length(); + if(i>=length)flag |= dfs(s, wordDict, i - length)&&s1.equals(s.substring(i-length,i)); + if (flag) { + memo[i] = 1; + return flag; + } + } + memo[i] = 0; + return false; + + } + + +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/second/T53_141_HasCycle.java b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T53_141_HasCycle.java new file mode 100644 index 0000000..929adab --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T53_141_HasCycle.java @@ -0,0 +1,50 @@ +package com.markilue.leecode.hot100.second; + +import com.markilue.leecode.listnode.ListNode; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hot100.second + *@Author: markilue + *@CreateTime: 2023-05-09 11:36 + *@Description: + * TODO 力扣141 环形链表: + *@Version: 1.0 + */ +public class T53_141_HasCycle { + + //快慢指针判断一个链表是否有环 + public boolean hasCycle(ListNode head) { + if (head == null) { + return false; + } + + ListNode fake = new ListNode(); + fake.next = head; + + ListNode slow = fake.next; + ListNode fast = fake.next.next; + while (fast != null && fast.next != null && fast != slow) { + fast = fast.next.next; + slow = slow.next; + } + + return fast != slow; + + } + + //优秀写法 + public boolean hasCycle1(ListNode head) { + ListNode fast = head; + ListNode slow = head; + + while (fast != null && fast.next != null) { + fast = fast.next.next; + slow = slow.next; + if (fast == slow) return true; + } + + return false; + + } +}