diff --git a/Big_data_example/Kafka/src/main/java/com/atguigu/kafka/consumer/KafkaConsumerDemo.java b/Big_data_example/Kafka/src/main/java/com/atguigu/kafka/consumer/KafkaConsumerDemo.java index ce339e9..a8217a8 100644 --- a/Big_data_example/Kafka/src/main/java/com/atguigu/kafka/consumer/KafkaConsumerDemo.java +++ b/Big_data_example/Kafka/src/main/java/com/atguigu/kafka/consumer/KafkaConsumerDemo.java @@ -13,7 +13,7 @@ import java.util.List; import java.util.Properties; /** - * kafka消费者 + * kafka消费者:自动提交offset * * */ diff --git a/Big_data_example/Kafka/src/main/java/com/atguigu/kafka/interceptor/TimeStampInterceptor.java b/Big_data_example/Kafka/src/main/java/com/atguigu/kafka/interceptor/TimeStampInterceptor.java index 3274b49..721457a 100644 --- a/Big_data_example/Kafka/src/main/java/com/atguigu/kafka/interceptor/TimeStampInterceptor.java +++ b/Big_data_example/Kafka/src/main/java/com/atguigu/kafka/interceptor/TimeStampInterceptor.java @@ -15,7 +15,7 @@ import java.util.Map; public class TimeStampInterceptor implements ProducerInterceptor { /** - * 拦截器的黑心处理方法 + * 拦截器的核心处理方法 * @param record 被拦截处理的消息 * @return */ diff --git a/Leecode/src/main/java/com/markilue/leecode/dynamic/second/T17_WordBreak.java b/Leecode/src/main/java/com/markilue/leecode/dynamic/second/T17_WordBreak.java new file mode 100644 index 0000000..418f4a5 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/dynamic/second/T17_WordBreak.java @@ -0,0 +1,119 @@ +package com.markilue.leecode.dynamic.second; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.dynamic.second + *@Author: markilue + *@CreateTime: 2023-02-20 09:40 + *@Description: + * TODO 力扣139 单词拆分: + * 给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。 + * 注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。 + *@Version: 1.0 + */ +public class T17_WordBreak { + + @Test + public void test(){ + String s = "leetcode"; + List wordDict = new ArrayList<>(Arrays.asList("leet", "code")); + System.out.println(wordBreak(s,wordDict)); + } + + + + /** + * 思路: 难点:查分之后如何去和wordDict中的单词进行匹配;如果匹配应该从何处进行匹配? + * TODO DP五部曲: + * 1.dp定义: dp[i][j]表示使用words[0-i]能否匹配上s[0-j] + * 2.dp状态转移方程: dp[i][j] :使用当前这个word或者不使用当前这个word + * dp[i][j]=dp[i-1][j] || dp[i][j-word[i].length]&&s[j-word[i].length - j]==words[i] + * 3.dp初始化: dp[i][0]=true + * 4.dp遍历顺序: 先遍历s再遍历words 因为words里面的单词可以重复使用 + * 5.dp举例推导: + * 速度击败71.9% 内存击败74.85% 6ms + * @param s + * @param wordDict + * @return + */ + public boolean wordBreak(String s, List wordDict) { + + boolean[] dp = new boolean[s.length() + 1]; + dp[0] = true; + + for (int i = 0; i < dp.length; i++) { + for (int j = 0; j < wordDict.size(); j++) { + int length = wordDict.get(j).length(); + if (i >= length) dp[i] |= (dp[i - length] && isEqual(i, length, s, wordDict.get(j))); + } + } + return dp[s.length()]; + + } + + public boolean isEqual(int j, int length, String s, String wordDict) { + + return wordDict.equals(s.substring(j - length, j)); + + } + + + /** + * 官方一维dp优化: 1.for循环优化;2.等于true不需要继续遍历words往下判断了 + * 速度击败93.3% 内存击败92.28% 2ms + * @param s + * @param wordDict + * @return + */ + public boolean wordBreak1(String s, List wordDict) { + + boolean[] dp = new boolean[s.length() + 1]; + dp[0] = true; + + for (int i = 1; i <= s.length(); i++) { + for (String word : wordDict) { + int len = word.length(); + if (i >= len && dp[i - len] && word.equals(s.substring(i - len, i))) { + dp[i] = true;// + break; + } + } + } + + return dp[s.length()]; + + } + + + /** + * 官方最快:回溯+记忆化搜索 + * 速度击败100% 内存击败99.56% + * @param s + * @param wordDict + * @return + */ + public boolean wordBreak3(String s, List wordDict) { + int[] memo = new int[s.length()]; + Arrays.fill(memo, -1); + return check(s, 0, wordDict, memo); + } + + private boolean check(String s, int idx, List wordDict, int[] memo) { + if (idx == s.length()) return true; + if (memo[idx] != -1) return memo[idx] != 0;//记忆化回溯 + for (String word : wordDict) + if (s.startsWith(word, idx) && check(s, idx + word.length(), wordDict, memo)) { + memo[idx] = 1;//找到了 + return true; + } + //没找到 + memo[idx] = 0; + return false; + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/dynamic/second/T18_Rob.java b/Leecode/src/main/java/com/markilue/leecode/dynamic/second/T18_Rob.java new file mode 100644 index 0000000..02f8ea7 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/dynamic/second/T18_Rob.java @@ -0,0 +1,74 @@ +package com.markilue.leecode.dynamic.second; + +import org.junit.Test; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.dynamic.second + *@Author: markilue + *@CreateTime: 2023-02-20 10:39 + *@Description: + * TODO 力扣198题 打家劫舍: + * 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 + * 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 + *@Version: 1.0 + */ +public class T18_Rob { + + @Test + public void test(){ + int[] nums ={1,2,3,1}; + System.out.println(rob(nums)); + } + + /** + * 思路: 打家劫舍问题: 本质上可以分为 : 偷不偷当前,在偷和不偷之间找最优 + * TODO DP五部曲: + * 1.dp定义: dp[i][0]表示不偷i的最大值 ;dp[i][1]表示偷i的最大值 + * 2.dp状态转移方程: + * 1.dp[i][0] 不偷当前 : 昨天偷了今天不偷 或者 昨天没偷今天偷了 + * dp[i][0]=max(dp[i-1][0],dp[i-1][1]) + * 2.dp[i][1] 偷当前: 昨天没偷今天偷了 + * dp[i][1]=dp[i-1][0]+nums[i] + * 3.dp初始化:dp[0][0]=0; dp[0][1]=nums[0] + * 4.dp遍历顺序:从前往后 + * 5.dp举例推导: + * @param nums + * @return + */ + public int rob(int[] nums) { + + int[][] dp = new int[nums.length][2]; + dp[0][0]=0; dp[0][1]=nums[0]; + + for (int i = 1; i < dp.length; i++) { + dp[i][0]=Math.max(dp[i-1][0],dp[i-1][1]); + dp[i][1]=dp[i-1][0]+nums[i]; + } + + return Math.max(dp[dp.length-1][0],dp[dp.length-1][1]); + + } + + + /** + * 滚动数组优化 + * @param nums + * @return + */ + public int rob1(int[] nums) { + + + int dp0=0; int dp1=nums[0]; + int temp=0; + + for (int i = 1; i < nums.length; i++) { + temp=dp0; + dp0=Math.max(dp0,dp1); + dp1=temp+nums[i]; + } + + return Math.max(dp0,dp1); + + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/dynamic/second/T19_Rob.java b/Leecode/src/main/java/com/markilue/leecode/dynamic/second/T19_Rob.java new file mode 100644 index 0000000..57fb11c --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/dynamic/second/T19_Rob.java @@ -0,0 +1,104 @@ +package com.markilue.leecode.dynamic.second; + +import org.junit.Test; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.dynamic.second + *@Author: markilue + *@CreateTime: 2023-02-20 10:57 + *@Description: + * TODO 力扣213题 打家劫舍II: + * 你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。 + * 这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。 + * 同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。 + * 给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额 + *@Version: 1.0 + */ +public class T19_Rob { + + @Test + public void test(){ + int[] nums={2,3,2}; + System.out.println(rob(nums)); + } + + /** + * 思路:与T18的不同之处在于:是环形的,收尾相连 :所以分别考虑只要第一个的时候,和只要最后一个的时候;结果出现在这两个之中最大的那个 + * TODO DP五部曲: 与之前一致,只不过一个只考虑不要最后一个;一个只考虑不要第一个 + * 速度击败2.92% 内存击败48.19% + * @param nums + * @return + */ + public int rob(int[] nums) { + if (nums.length == 1) { + return nums[0];//只有一个的情况直接返回 + } + + int[][] dp = new int[nums.length][2];//考虑不要最后一个的情况 + int[][] dp1 = new int[nums.length][2];//考虑不要第一个的情况 + dp[0][0] = 0; + dp[0][1] = nums[0]; + dp1[1][0] = 0; + dp1[1][1] = nums[1]; + + for (int i = 1; i < nums.length-1; i++) { + //不考虑最后一个 + dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1]); + dp[i][1] = dp[i - 1][0] + nums[i]; + + + //不考虑第一个 + dp1[i + 1][0] = Math.max(dp1[i][0], dp1[i][1]); + dp1[i + 1][1] = dp1[i][0] + nums[i + 1]; + + } + int max= Math.max(dp[nums.length - 2][0],dp[nums.length - 2][1]); + int max1=Math.max(dp1[nums.length -1][0],dp1[nums.length -1][1]); + + + return Math.max(max, max1); + + + } + + + /** + * 一维dp优化 + * @param nums + * @return + */ + public int rob1(int[] nums) { + if (nums.length == 1) { + return nums[0];//只有一个的情况直接返回 + } + + + int dp0 = 0;//考虑不要最后一个的情况 + int dp1 = nums[0]; + int temp=0; + int dp10 = 0;//考虑不要第一个的情况 + int dp11 = nums[1]; + int temp1=0; + + for (int i = 1; i < nums.length-1; i++) { + //不考虑最后一个 + temp=dp0; + dp0 = Math.max(dp0, dp1); + dp1 = temp + nums[i]; + + + //不考虑第一个 + temp1=dp10; + dp10 = Math.max(dp10, dp11); + dp11 = temp1 + nums[i + 1]; + + } + int max= Math.max(dp0,dp1); + int max1=Math.max(dp10,dp11); + + return Math.max(max, max1); + + + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/dynamic/second/T20_Rob.java b/Leecode/src/main/java/com/markilue/leecode/dynamic/second/T20_Rob.java new file mode 100644 index 0000000..652c1ee --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/dynamic/second/T20_Rob.java @@ -0,0 +1,58 @@ +package com.markilue.leecode.dynamic.second; + +import com.markilue.leecode.tree.TreeNode; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.dynamic.second + *@Author: markilue + *@CreateTime: 2023-02-20 11:50 + *@Description: + * TODO 力扣337 打家劫舍III: + * 小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root 。 + * 除了 root 之外,每栋房子有且只有一个“父“房子与之相连。 + * 一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 + * 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。 + * 给定二叉树的 root 。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额 。 + *@Version: 1.0 + */ +public class T20_Rob { + + + /** + * 思路: 不同之处在于 二叉树地区应该如何处理,所以后续遍历,遍历完子节点之后考虑当前节点是否偷 + * TODO DP五部曲: + * 1.dp定义: dp[i][0]表示当前节点不偷的最大收益;dp[i][1]表示当前节点偷的最大收益 + * 2.dp状态转移方程: + * 1.dp[i][0]不偷:子节点不偷 或者偷的最大 之和 + * 2.dp[i][1]偷:子节点中不偷之和 + * + * 3.dp初始化:碰到null节点 则 dp[i][0]=0; dp[i][1]=0; + * 4.dp遍历顺序:后续遍历,最后在考虑当前节点的问题 + * 5.dp举例推导: + * 速度击败100% 内存击败76.93% + * @param root + * @return + */ + public int rob(TreeNode root) { + + int[] root1 = robSub(root); + return Math.max(root1[0], root1[1]); + + } + + + public int[] robSub(TreeNode root) { + if (root == null) { + return new int[]{0, 0}; + } + + int[] left = robSub(root.left); + int[] right = robSub(root.right); + int noSteal = Math.max(left[0], left[1]) + Math.max(right[0], right[1]); + int Steal = left[0] + right[0] + root.val; + + return new int[]{noSteal, Steal}; + + } +}