diff --git a/README.md b/README.md index 1ab38e2..6a466c2 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,17 @@ Java学习笔记,内容包括JVM,spring,hashMap实现源码分析,多线 -## +# 最近在搞啥 + +跑路来深圳了,然后之前一直在忙着重构公司之前的代码(瞎搞着玩) + +原来这边根本不管什么代码风格,更没有什么code review,代码想怎么写就怎么写,还算比较大的公司吧,代码真的奇烂无比,我见过最垃圾的代码了,代码根本没法维护,改个小地方,看半天。 + +然后用目前所学吧,花了两个多月的下班时间和周末,把代码全部改了,业务代码改完了,所以没那么忙了,后面就是他们测试了。代码行数少了一半,类数量少了一半。看着舒服多了 + +后面整个代码风格的文档吧(入职一个月已经写了个60多页的ppt,但是发不出来,后面再整理吧),对比一下之前的代码,对比下自己有没有可以提升的地方 + +主要还是这个项目不重要,内部使用的,出问题也问题不会特别大,整个项目还不算太大,不到13w行代码,而且领导也想整,所以才敢搞。 ## 关于项目 diff --git a/java-note-algorithm/.idea/misc.xml b/java-note-algorithm/.idea/misc.xml index 3ccb27b..b49fb2f 100644 --- a/java-note-algorithm/.idea/misc.xml +++ b/java-note-algorithm/.idea/misc.xml @@ -11,7 +11,7 @@ - + \ No newline at end of file diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_121_BestTimeToBuyAndSellStock.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_121_BestTimeToBuyAndSellStock.java index 03b1d1b..f86c45f 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_121_BestTimeToBuyAndSellStock.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_121_BestTimeToBuyAndSellStock.java @@ -1,36 +1,35 @@ package com.leosanqing.leetcode.easy; /** - *描述 : 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 - * 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。 - * 注意你不能在买入股票前卖出股票。 - * - *示例1: 输入: [7,1,5,3,6,4] - * 输出: 5 - * 解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。 - * 注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。 - * - *示例2 输入: [7,6,4,3,1] - * 输出: 0 - * 解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。 + * 描述 : 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 + * 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。 + * 注意你不能在买入股票前卖出股票。 + *

+ * 示例1: 输入: [7,1,5,3,6,4] + * 输出: 5 + * 解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。 + * 注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。 + *

+ * 示例2 输入: [7,6,4,3,1] + * 输出: 0 + * 解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。 */ public class _121_BestTimeToBuyAndSellStock { /** - * * 直接暴力求解,遍历两次数组,求出最优解 */ - public static int violence(int[] prices){ - if(prices == null || prices.length ==0){ + public static int violence(int[] prices) { + if (prices == null || prices.length == 0) { return 0; } int maxProfit = 0; for (int i = 0; i < prices.length; i++) { - for (int j = i+1; j < prices.length; j++) { - if(prices[j]-prices[i] >maxProfit){ - maxProfit = prices[j]-prices[i]; + for (int j = i + 1; j < prices.length; j++) { + if (prices[j] - prices[i] > maxProfit) { + maxProfit = prices[j] - prices[i]; } } @@ -40,31 +39,29 @@ public static int violence(int[] prices){ /** - * 动态规划: - * 1.定义一个从最开始到当前位置的最小值 - * 2.计算今天减去最小值的值,也就是当天的利润 - * 3.比较当天的利润和之前的最大利润 + * 动态规划: + * 1.定义一个从最开始到当前位置的最小值 + * 2.计算今天减去最小值的值,也就是当天的利润 + * 3.比较当天的利润和之前的最大利润 */ - public static int dp(int[] prices){ - if(prices == null || prices.length == 0) + public static int dp(int[] prices) { + if (prices == null || prices.length == 0) return 0; - int mixProfit = Integer.MAX_VALUE; + int minProfit = Integer.MAX_VALUE; int maxProfit = 0; - for (int i = 0; i < prices.length; i++) { + for (int price : prices) { //找到最小值 - mixProfit = Math.min(mixProfit,prices[i]); + minProfit = Math.min(minProfit, price); //比较当天的利润和最大利润 - maxProfit = Math.max(maxProfit,(prices[i]-mixProfit)); - + maxProfit = Math.max(maxProfit, (price - minProfit)); } return maxProfit; - } public static void main(String[] args) { - int a[] ={7,6,4,3,1}; + int[] a = {7, 6, 4, 3, 1}; System.out.println(violence(a) == dp(a)); } } diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_122_BestTimeToBuyAndSellStock2.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_122_BestTimeToBuyAndSellStock2.java index 18b80b6..7851f2a 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_122_BestTimeToBuyAndSellStock2.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/easy/_122_BestTimeToBuyAndSellStock2.java @@ -2,42 +2,43 @@ /** * 描述: 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 - * 设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。 - * 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 - * + * 设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。 + * 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 + *

* 示例1: 输入: [7,1,5,3,6,4] - * 输出: 7 - * 解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。 - * 随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。 + * 输出: 7 + * 解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。 + * 随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。 * 示例2: 输入: [1,2,3,4,5] - * 输出: 4 - * 解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。 - * 注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。 - * 因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。 - * + * 输出: 4 + * 解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。 + * 注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。 + * 因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。 + *

* 思路:使用两个变量 一个valley表示当天天数中最低价, - * 一个peek表示当前所有的天数中的最高价 - * 因为我们可以买卖股票且是不用付手续费的,也就是我们可以卖了这一只股票,然后再把它买回来 - * 所以上面示例2中,5-1和 (2-1)+(3-2)+(4-3)+(5-4)的效果是一样的,所以顶峰就找递增的,底就找递减的 - * + * 一个peek表示当前所有的天数中的最高价 + * 因为我们可以买卖股票且是不用付手续费的,也就是我们可以卖了这一只股票,然后再把它买回来 + * 所以上面示例2中,5-1和 (2-1)+(3-2)+(4-3)+(5-4)的效果是一样的,所以顶峰就找递增的,底就找递减的 */ public class _122_BestTimeToBuyAndSellStock2 { public int maxProfit(int[] prices) { - if(prices.length == 0 || prices == null) + if (prices == null || prices.length == 0) return 0; - int valley = prices[0],peek = prices[0]; - int i =0; + + int valley = prices[0], peek = prices[0]; + int i = 0; int maxProfit = 0; - while(i < prices.length-1){ - while(i=prices[i+1]) + + while (i < prices.length - 1) { + while (i < prices.length - 1 && prices[i] >= prices[i + 1]) i++; valley = prices[i]; - while(i letterCombinations(String digits) { - List list = new LinkedList<>(); - if(digits == null || "".equals(digits)){ - return list; + if (digits.length() == 0) { + return new ArrayList<>(); } - char[] charArray = digits.toCharArray(); - char[][] map = { - {}, - {}, - {'a', 'b', 'c'}, - {'d', 'e', 'f'}, - {'g', 'h', 'i'}, - {'j', 'k', 'l'}, - {'m', 'n', 'o'}, - {'p', 'q', 'r', 's'}, - {'t', 'u', 'v'}, - {'w', 'x', 'y', 'z'}, - }; + List answer = new ArrayList<>(); - backtrack(charArray, list, map, new StringBuilder(), 0); - return list; + backtrace(answer, 0, new StringBuilder(), digits); + return answer; } - - private static void backtrack(char[] digits, List list, char[][] map, StringBuilder sb, int offset) { - if (offset == digits.length) { - list.add(sb.toString()); + private static void backtrace(List answer, int position, StringBuilder sb, String digits) { + if (sb.length() == digits.length()) { + answer.add(new String(sb)); return; } - // 获得 map 的索引 - int index = digits[offset] - '0'; - // 遍历每个按键的所有情况 - for (int i = 0; i < map[index].length; i++) { - // 挨个追加值 - sb.append(map[index][i]); - backtrack(digits, list, map, sb, offset + 1); - // 删除 + for (int j = 0; j < num[digits.charAt(position) - '0'].length; j++) { + sb.append(num[digits.charAt(position) - '0'][j]); + backtrace(answer, position + 1, sb, digits); sb.deleteCharAt(sb.length() - 1); } } diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_33_search_in_rotated_sorted_array.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_33_search_in_rotated_sorted_array.java index 8312a85..6f5fef4 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_33_search_in_rotated_sorted_array.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_33_search_in_rotated_sorted_array.java @@ -49,7 +49,6 @@ public static int search(int[] nums, int target) { return -1; } - int left = 0, right = nums.length - 1; while (left <= right) { int mid = left + (right - left) / 2; @@ -90,20 +89,20 @@ private static int search2(int[] nums, int target) { int mid = left + (right - left) / 2; // 说明 mid 和 target 在同一侧 - if ((nums[mid] - nums[nums.length-1]) * (target - nums[nums.length-1]) > 0) { + if ((nums[mid] - nums[nums.length - 1]) * (target - nums[nums.length - 1]) > 0) { if (target > nums[mid]) { left = mid + 1; } else { right = mid; } - }else if(target - nums[nums.length-1] > 0){ + } else if (target - nums[nums.length - 1] > 0) { // target 在左侧 right = mid; - }else{ - left = mid+1; + } else { + left = mid + 1; } } - if(nums[left] == target){ + if (nums[left] == target) { return left; } diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_39_combination_sum.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_39_combination_sum.java index 936ab1b..f8d1d5b 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_39_combination_sum.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_39_combination_sum.java @@ -8,24 +8,23 @@ * @Author: rtliu * @Date: 2020/7/13 下午2:29 * @Package: com.leosanqing.leetcode.medium.array - * @Description: - * Given a set of candidate numbers (candidates) (without duplicates) and a target number (target), - * find all unique combinations in candidates where the candidate numbers sums to target. - * The same repeated number may be chosen from candidates unlimited number of times. - * - * - * 给定一组候选编号(候选)(无重复)和目标编号(target), - * 在候选人编号总和为目标的候选人中找到所有唯一组合。 - * 可以从候选人无限制的次数中选择相同的重复号码。 - *` Note: - *` All numbers (including target) will be positive integers. - *` The solution set must not contain duplicate combinations. - *` Example 1: - *` Input: candidates = [2,3,6,7], target = 7, - *` A solution set is: [ [7], [2,2,3] ] - *` Example 2: - *` Input: candidates = [2,3,5], target = 8, - *` A solution set is: [ [2,2,2,2], [2,3,3], [3,5] ] + * @Description: Given a set of candidate numbers (candidates) (without duplicates) and a target number (target), + * find all unique combinations in candidates where the candidate numbers sums to target. + * The same repeated number may be chosen from candidates unlimited number of times. + *

+ *

+ * 给定一组候选编号(候选)(无重复)和目标编号(target), + * 在候选人编号总和为目标的候选人中找到所有唯一组合。 + * 可以从候选人无限制的次数中选择相同的重复号码。 + * ` Note: + * ` All numbers (including target) will be positive integers. + * ` The solution set must not contain duplicate combinations. + * ` Example 1: + * ` Input: candidates = [2,3,6,7], target = 7, + * ` A solution set is: [ [7], [2,2,3] ] + * ` Example 2: + * ` Input: candidates = [2,3,5], target = 8, + * ` A solution set is: [ [2,2,2,2], [2,3,3], [3,5] ] * @Version: 1.0 */ public class _39_combination_sum { @@ -33,40 +32,42 @@ public class _39_combination_sum { public static void main(String[] args) { int[] nums = {2, 3, 6, 7}; - combinationSum(nums,7); + combinationSum(nums, 7); } /** * 这种的做多了,就会发现基本都是一个套路,递归调用 + * * @param candidates * @param target * @return */ - public static List> combinationSum(int[] candidates, int target) { - + public static List> combinationSum(int[] candidates, int target) { List> answer = new ArrayList<>(); + + // 先排序 Arrays.sort(candidates); - backTrace(answer, new ArrayList<>(), candidates, 0, target); + + backtrace(answer, candidates, target, new ArrayList<>(), 0); return answer; } - - private static void backTrace(List> answer, List list, int[] candidates, int position, int remain) { - if (remain < 0) { + private static void backtrace(List> answer, int[] candidates, int target, List list, int position) { + if (target < 0) { return; - } else if (remain == 0) { + } + + if (target == 0) { answer.add(new ArrayList<>(list)); return; } for (int i = position; i < candidates.length; i++) { list.add(candidates[i]); - backTrace(answer, list, candidates, i, remain - candidates[i]); + backtrace(answer, candidates, target - candidates[i], list, i); list.remove(list.size() - 1); } - - } } diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_46_permutations.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_46_permutations.java index ddf7d6a..de36af7 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_46_permutations.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_46_permutations.java @@ -8,10 +8,10 @@ * @Date: 2020/7/14 上午9:36 * @Package: com.leosanqing.leetcode.medium.array * @Description: 1 - *` Given a collection of distinct integers, return all possible permutations. - *` Example: - *` Input: [1,2,3] - *` Output: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ] + * ` Given a collection of distinct integers, return all possible permutations. + * ` Example: + * ` Input: [1,2,3] + * ` Output: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ] * @Version: 1.0 */ public class _46_permutations { @@ -20,37 +20,29 @@ public static void main(String[] args) { System.out.println(permute(new int[]{1, 2, 3})); } - public static List> permute(int[] nums) { List> answer = new ArrayList<>(); - backTrace(answer, new ArrayList<>(), nums); + backtrace(answer, nums, new ArrayList<>()); return answer; - } - /** - * 递归遍历 - * @param answer - * @param list - * @param nums - */ - private static void backTrace(List> answer, List list, int[] nums) { + + private static void backtrace(List> answer, int[] nums, List list) { if (list.size() == nums.length) { answer.add(new ArrayList<>(list)); return; } + for (int num : nums) { - // 如果有这个数字,就跳过 if (list.contains(num)) { continue; } + list.add(num); - backTrace(answer, list, nums); + backtrace(answer, nums, list); list.remove(list.size() - 1); } - - } } diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_48_rotate_image.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_48_rotate_image.java index 4f3f4e5..807d56d 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_48_rotate_image.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_48_rotate_image.java @@ -49,24 +49,24 @@ public static void main(String[] args) { /** * 分成两步进行旋转 - * + *

* 1 2 3 * 4 5 6 * 7 8 9 - * + *

* 1 4 7 * 2 5 8 * 3 6 9 - * + *

* 7 4 1 * 8 5 2 * 9 6 3 * - * * @param matrix */ public static void rotate(int[][] matrix) { int temp; + for (int i = 0; i < matrix.length; i++) { for (int j = i; j < matrix[0].length; j++) { temp = matrix[i][j]; @@ -83,4 +83,27 @@ public static void rotate(int[][] matrix) { } } } + + + public static void rotate1(int[][] matrix) { + int temp; + for (int i = 0; i < matrix.length; i++) { + for (int j = i; j < matrix[0].length; j++) { + if (i == j) { + continue; + } + temp = matrix[i][j]; + matrix[i][j] = matrix[j][i]; + matrix[j][i] = temp; + } + } + + for (int i = 0; i < matrix.length; i++) { + for (int j = 0; j < matrix[0].length / 2; j++) { + temp = matrix[i][j]; + matrix[i][j] = matrix[i][matrix[0].length - j - 1]; + matrix[i][matrix[0].length - j - 1] = temp; + } + } + } } diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_49_group_anagrams.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_49_group_anagrams.java index 8f08101..ef9489a 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_49_group_anagrams.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_49_group_anagrams.java @@ -25,6 +25,7 @@ public static void main(String[] args) { String[] strings = {"eat", "tea", "tan", "ate", "nat", "bat"}; System.out.println(groupAnagrams(strings)); } + public static List> groupAnagrams(String[] strs) { List> answer = new ArrayList<>(); @@ -43,7 +44,7 @@ public static List> groupAnagrams(String[] strs) { List list = map.getOrDefault(s, new ArrayList<>()); list.add(str); - map.put(s,list); + map.put(s, list); } return new ArrayList<>(map.values()); diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_55_jump_game.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_55_jump_game.java index 4d3e7fa..a274d72 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_55_jump_game.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_55_jump_game.java @@ -53,16 +53,14 @@ public static void main(String[] args) { * @return */ public static boolean canJump(int[] nums) { - int reachable = 0; - for (int i = 0; i < nums.length; ++i) { - // 当 i 大于 reachable 说明这个地方不可达,那肯定有问题 - if (i > reachable) { + int max = 0; + for (int i = 0; i < nums.length; i++) { + if (i > max) { return false; } - reachable = Math.max(reachable, i + nums[i]); + // 算出能到达的最远距离 + max = Math.max(max, i + nums[i]); } return true; } - - } diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_56_merge_intervals.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_56_merge_intervals.java index ee710ef..4343b06 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_56_merge_intervals.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_56_merge_intervals.java @@ -23,29 +23,32 @@ * @Version: 1.0 */ public class _56_merge_intervals { - public int[][] merge(int[][] intervals) { - if (intervals.length <= 1) { - return intervals; - } - - // 先进行排序,这样才能一个个进行合并 + /** + * 先对给定的数组进行排列 + * @param intervals + * @return + */ + public static int[][] merge(int[][] intervals) { + // 先排序 Arrays.sort(intervals, Comparator.comparingInt(i -> i[0])); - List list = new ArrayList<>(); + List answer = new ArrayList<>(); - int[] newInterval = intervals[0]; - list.add(intervals[0]); for (int[] interval : intervals) { - if (interval[0] <= newInterval[1]) { - newInterval[1] = Math.max(newInterval[1], interval[1]); + int left = interval[0]; + int right = interval[1]; + + if (answer.isEmpty()) { + answer.add(new int[]{left, right}); + continue; + } + + if (answer.get(answer.size() - 1)[1] < left) { + answer.add(new int[]{left, right}); } else { - // 让他指向下一个 - newInterval = interval; - list.add(newInterval); + answer.get(answer.size() - 1)[1] = Math.max(answer.get(answer.size() - 1)[1], right); } } - - - return list.toArray(new int[list.size()][]); + return answer.toArray(new int[answer.size()][]); } } diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_62_unique_paths.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_62_unique_paths.java index eb66422..b1dc68a 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_62_unique_paths.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_62_unique_paths.java @@ -31,36 +31,34 @@ */ public class _62_unique_paths { public static void main(String[] args) { - System.out.println(uniquePaths(3,3)); + System.out.println(uniquePaths(3, 3)); + System.out.println(uniquePaths(3, 7)); } /** - * 这个解法和 64题 类似 都是使用 DP + * 使用动态规划,机器人只能向下或者向右,所以当前到当前坐标的可能性就是 上边坐标的可能性加上左边坐标的可能性 * - * @param cols - * @param rows + * @param m + * @param n * @return */ - public static int uniquePaths(int cols, int rows) { - int[] cur = new int[cols]; - int[] pre = new int[cols]; + public static int uniquePaths(int m, int n) { + int[] pre = new int[m]; + int[] cur = new int[m]; - // 第一行 到达每个节点只有一条道路 所以每个都设置成 1 - for (int i = 0; i < cols; i++) { - pre[i] = 1; + for (int i = 0; i < m; i++) { cur[i] = 1; + pre[i] = 1; } - // 第一列 到达的路径只有从上面走的一种,所以也全是1,可以不用管,上面已经设置过 - for (int i = 1; i < rows; i++) { - for (int j = 1; j < cols; j++) { - // 能到达的可能性就是 上边的 + 左边的 可能性 + for (int i = 1; i < m; i++) { + for (int j = 1; j < n; j++) { cur[j] = cur[j - 1] + pre[j]; } pre = cur; } - return cur[cols - 1]; + return cur[m - 1]; } } diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_64_minimum_path_sum.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_64_minimum_path_sum.java index 1300269..d57c29a 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_64_minimum_path_sum.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_64_minimum_path_sum.java @@ -29,62 +29,26 @@ public static void main(String[] args) { {1, 1, 1, 10} }; - System.out.println(minPathSum(ints) == minPathSum1(ints)); + System.out.println(minPathSum(ints)); } - public static int minPathSum(int[][] grid) { - int m = grid.length, n = grid[0].length; - int[] dp = new int[n]; - dp[0] = grid[0][0]; - // 第一层特殊处理,因为他没有上一层 - for (int j = 1; j < n; j++) { - dp[j] = dp[j - 1] + grid[0][j]; - } - for (int i = 1; i < m; i++) { - for (int j = 0; j < n; j++) { - if (j == 0) { - // 最左边的一列,只有上面的路径可以达到 - dp[j] += grid[i][j]; - } else { - // 因为dp数组他更新了,这样子 dp[j-1] 就是 grid[i][j] 左边的路径之和,dp[j] 就是他上面的那个路径之和 - dp[j] = grid[i][j] + Math.min(dp[j], dp[j - 1]); - } - } - } - - return dp[n - 1]; - } - - - private static int minPathSum1(int[][] grid) { - if (grid.length <= 0) { - return 0; + private static int minPathSum(int[][] grid) { + for (int i = 1; i < grid.length; i++) { + grid[i][0] += grid[i - 1][0]; } - int[] result = new int[grid[0].length]; - - // 第一层 特殊处理 - for (int i = 0; i < grid[0].length; i++) { - if (i == 0) { - result[0] = grid[0][i]; - } else { - result[i] = result[i - 1] + grid[0][i - 1]; - } + for (int i = 1; i < grid[0].length; i++) { + grid[0][i] += grid[0][i - 1]; } for (int i = 1; i < grid.length; i++) { - // 第一列特殊处理 - for (int j = 0; j < grid[0].length; j++) { - if (j == 0) { - result[0] = grid[i][0] + result[0]; - } else { - result[j] = grid[i][j] + Math.min(result[j], result[j - 1]); - } + for (int j = 1; j < grid[0].length; j++) { + grid[i][j] += Math.min(grid[i - 1][j], grid[i][j - 1]); } } - return result[grid[0].length - 1]; + return grid[grid.length - 1][grid[0].length - 1]; } diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_75_sort_colors.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_75_sort_colors.java index 338715b..4a90260 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_75_sort_colors.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_75_sort_colors.java @@ -24,17 +24,47 @@ public static void sortColors(int[] nums) { int n2 = -1, n1 = -1, n0 = -1; for (int i = 0; i < nums.length; i++) { - if(nums[i] == 0){ + if (nums[i] == 0) { nums[++n2] = 2; nums[++n1] = 1; nums[++n0] = 0; - }else if(nums[i] == 1){ + } else if (nums[i] == 1) { nums[++n2] = 2; nums[++n1] = 1; - }else if(nums[i] == 2){ + } else if (nums[i] == 2) { nums[++n2] = 2; } } } + + + /** + * 使用两个指针,p1指向0,p2指向2 + * 然后遍历,找到0就和 P1上的数字交换,找到2就和p2上的数字交换 + * + * 但是这个时候有一个情况是,2交换后仍可能是2 + * 参考 0 2 1 2 1 0 2 自己手动交换一下就知道,所以才有 while里面的内容 + * @param nums + */ + public static void sortColors1(int[] nums) { + int n1 = 0; + int n2 = nums.length - 1; + + for (int i = 0; i <= n2; i++) { + // 交换过后 此时 nums[i] 可能是 0,也可能是2 ,还需要再继续交换 + while (i <= n2 && nums[i] == 2) { + int temp = nums[i]; + nums[i] = nums[n2]; + nums[n2] = temp; + --n2; + } + if (nums[i] == 0) { + int temp = nums[i]; + nums[i] = nums[n1]; + nums[n1] = temp; + ++n1; + } + } + } } diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_79_word_search.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_79_word_search.java index 805ce0a..ff5adfd 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_79_word_search.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_79_word_search.java @@ -25,7 +25,7 @@ * @Version: 1.0 */ public class _79_word_search { - static boolean flag = false; + public static void main(String[] args) { @@ -43,48 +43,50 @@ public static void main(String[] args) { public static boolean exist(char[][] board, String word) { - if (board == null || board.length == 0) { - return false; - } boolean[][] isUsed = new boolean[board.length][board[0].length]; for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[0].length; j++) { - if (word.charAt(0) == board[i][j] && bfs(board, word, i, j, 0, isUsed)) { + if(backtrace(board, word, i, j, 0, isUsed)){ return true; } } } + return false; } + private static boolean backtrace(char[][] board, String word, int x, int y, int index, boolean[][] isUsed) { - private static boolean bfs(char[][] board, String word, int x, int y, int index, boolean[][] isUsed) { - - if (x >= 0 && x < board.length && y >= 0 && y < board[0].length) { - if (isUsed[x][y]) { - return false; - } + // 超出边界 + if (x > board.length - 1 || y > board[0].length - 1 || x < 0 || y < 0) { + return false; + } - if (word.charAt(index) == board[x][y]) { - isUsed[x][y] = true; - if (index == word.length() - 1) { - return true; - } + if (isUsed[x][y]) { + return false; + } - if (bfs(board, word, x - 1, y, index + 1, isUsed) - || bfs(board, word, x, y + 1, index + 1, isUsed) - || bfs(board, word, x + 1, y, index + 1, isUsed) - || bfs(board, word, x, y - 1, index + 1, isUsed) - ) { - return true; - } + if (board[x][y] != word.charAt(index)) { + return false; + } - isUsed[x][y] = false; + isUsed[x][y] = true; + if (index == word.length() - 1) { + return true; + } - } - return false; + if ( + backtrace(board, word, x + 1, y, index + 1, isUsed) + || backtrace(board, word, x - 1, y, index + 1, isUsed) + || backtrace(board, word, x, y - 1, index + 1, isUsed) + || backtrace(board, word, x, y + 1, index + 1, isUsed) + ) { + return true; } + + isUsed[x][y] = false; + return false; } diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_90_subsetsII.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_90_subsetsII.java index 8c822ec..ac96f93 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_90_subsetsII.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/array/_90_subsetsII.java @@ -1,5 +1,7 @@ package com.leosanqing.leetcode.medium.array; +import com.alibaba.fastjson.JSON; + import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -20,7 +22,8 @@ public class _90_subsetsII { public static void main(String[] args) { - subsetsWithDup(new int[]{1, 2, 2}); + + System.out.println(JSON.toJSONString(subsetsWithDup(new int[]{1, 2, 2}))); } public static List> subsetsWithDup(int[] nums) { @@ -41,12 +44,7 @@ public static List> subsetsWithDup(int[] nums) { private static void backTrace(List> answer, List list, int[] nums, int position, int max) { if (list.size() == max) { - answer.add(new ArrayList<>(list)); - -// if(!answer.contains(new ArrayList<>(list))){ -// } - return; } @@ -61,5 +59,4 @@ private static void backTrace(List> answer, List list, in } - } diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_142_linked_list_cycleII.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_142_linked_list_cycleII.java index 2f9fa9d..472e9d3 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_142_linked_list_cycleII.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_142_linked_list_cycleII.java @@ -5,40 +5,41 @@ * @Date: 2020/8/4 下午4:50 * @Package: com.leosanqing.leetcode.medium.list * @Description: 1 - *` Given a linked list, return the node where the cycle begins. - *` If there is no cycle, return null. - *` To represent a cycle in the given linked list, - *` we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. - *` If pos is -1, then there is no cycle in the linked list. - *` Note: Do not modify the linked list. - *` Example 1: - *` Input: head = [3,2,0,-4], pos = 1 - *` Output: tail connects to node index 1 - *` Explanation: - *` There is a cycle in the linked list, where tail connects to the second node. - *` Example 2: - *` Input: head = [1,2], pos = 0 - *` Output: tail connects to node index 0 - *` Explanation: - *` There is a cycle in the linked list, where tail connects to the first node. + * ` Given a linked list, return the node where the cycle begins. + * ` If there is no cycle, return null. + * ` To represent a cycle in the given linked list, + * ` we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. + * ` If pos is -1, then there is no cycle in the linked list. + * ` Note: Do not modify the linked list. + * ` Example 1: + * ` Input: head = [3,2,0,-4], pos = 1 + * ` Output: tail connects to node index 1 + * ` Explanation: + * ` There is a cycle in the linked list, where tail connects to the second node. + * ` Example 2: + * ` Input: head = [1,2], pos = 0 + * ` Output: tail connects to node index 0 + * ` Explanation: + * ` There is a cycle in the linked list, where tail connects to the first node. * @Version: 1.0 */ public class _142_linked_list_cycleII { + public ListNode detectCycle(ListNode head) { ListNode slow = head; ListNode fast = head; - while (fast!=null && fast.next!=null){ - fast = fast.next.next; + while (fast != null && fast.next != null) { slow = slow.next; + fast = fast.next.next; - if (fast == slow){ - ListNode slow2 = head; - while (slow2 != slow){ + if (slow == fast) { + ListNode n = head; + while (slow != n) { slow = slow.next; - slow2 = slow2.next; + n = n.next; } - return slow; + return n; } } return null; diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_19_remove_Nth_node_from_end_of_list.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_19_remove_Nth_node_from_end_of_list.java index 0f6eaaa..8f3a2ba 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_19_remove_Nth_node_from_end_of_list.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_19_remove_Nth_node_from_end_of_list.java @@ -5,13 +5,13 @@ * @Date: 2020/7/7 下午3:47 * @Package: com.leosanqing.leetcode.medium.list * @Description: Given a linked list, remove the n-th node from the end of list and return its head. - * - * - *` `Example: - *` ` Give linked list: 1->2->3->4->5, and n = 2. - *` ` After removing the second node from the end, the linked list becomes - *` ` 1->2->3->5. - *` ` Note: Given n will always be valid. + *

+ *

+ * ` `Example: + * ` ` Give linked list: 1->2->3->4->5, and n = 2. + * ` ` After removing the second node from the end, the linked list becomes + * ` ` 1->2->3->5. + * ` ` Note: Given n will always be valid. * @Version: 1.0 */ public class _19_remove_Nth_node_from_end_of_list { @@ -23,37 +23,29 @@ public static void main(String[] args) { /** * 思路就是使用两个节点,一个快节点先走 n步,然后快节点走到最后,后面的那个节点就是我们要去掉的节点 * 设置一个虚拟头结点,可以帮助我们解决边界值问题 + * * @param head * @param n * @return */ public ListNode removeNthFromEnd(ListNode head, int n) { + ListNode fakeHead = new ListNode(); + + ListNode slow = fakeHead; + ListNode fast = fakeHead; - // 设置一个虚拟的头结点,便于后面做边界值判断 - ListNode fakeHead = new ListNode(); fakeHead.next = head; - // 快节点,用于记录n - ListNode fastNode = head; for (int i = 0; i < n; i++) { - fastNode = fastNode.next; - } - ListNode pre = fakeHead; - ListNode curr = head; - while (fastNode != null) { - fastNode = fastNode.next; - pre = curr; - curr = curr.next; + fast = fast.next; } - - pre.next = curr.next; - + while (fast.next != null) { + fast = fast.next; + slow = slow.next; + } + slow.next = slow.next.next; return fakeHead.next; } - - - - } diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_2_addTwoNumbers.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_2_addTwoNumbers.java index e5c5fd5..888c5d4 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_2_addTwoNumbers.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_2_addTwoNumbers.java @@ -29,45 +29,44 @@ public static void main(String[] args) { ListNode node5 = new ListNode(1, node4); ListNode node6 = new ListNode(3, node5); - _2_addTwoNumbers addTwoNumbers = new _2_addTwoNumbers(); - addTwoNumbers.addTwoNumbers(node3, node6); + ListNode listNode1 = addTwoNumbers(node3, node6); } - public ListNode addTwoNumbers(ListNode l1, ListNode l2) { - ListNode curr1 = l1; - ListNode curr2 = l2; - // 新建一个链表 - ListNode result = new ListNode(); - ListNode curr = result; + public static ListNode addTwoNumbers(ListNode l1, ListNode l2) { + + ListNode cur1 = l1; + ListNode cur2 = l2; + + ListNode head = new ListNode(); + ListNode cur = head; - int sum = 0; - // 进位 int carry = 0; - while (curr1 != null || curr2 != null) { - // 如果链1 和 链2 没有位数了 - if (curr1 == null) { - curr1 = new ListNode(0); + // 定义在这里不需要新建对象 + int sum; + + while (cur1 != null || cur2 != null) { + if (cur1 == null) { + cur1 = new ListNode(0); } - if (curr2 == null) { - curr2 = new ListNode(0); + if (cur2 == null) { + cur2 = new ListNode(0); } - sum = curr1.val + curr2.val + carry; + // 计算位数之和 + sum = carry + cur1.val + cur2.val; + // 是否大于0 carry = sum / 10; + cur.next = new ListNode(sum % 10); - curr.next = new ListNode(sum % 10); - curr = curr.next; - - curr1 = curr1.next; - curr2 = curr2.next; + cur = cur.next; + cur1 = cur1.next; + cur2 = cur2.next; } - // 如果最高位加起来大于10,就需要新来一个节点 if (carry != 0) { - curr.next = new ListNode(1); + cur.next = new ListNode(1); } - return result.next; - + return head.next; } } diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_78_subsets.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_78_subsets.java index 42c87b8..0bffeea 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_78_subsets.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_78_subsets.java @@ -1,5 +1,7 @@ package com.leosanqing.leetcode.medium.list; +import com.alibaba.fastjson.JSON; + import java.util.ArrayList; import java.util.List; @@ -17,42 +19,34 @@ */ public class _78_subsets { public static void main(String[] args) { - subsets(new int[]{1,2,3}); + System.out.println(JSON.toJSONString(subsets(new int[]{1, 2, 3}))); } + /** + * 这个真的太经典了,回溯的经典题型,你会发现有很多很多这种的题 + * + * @param nums + * @return + */ public static List> subsets(int[] nums) { - List> answer = new ArrayList<>(); - answer.add(new ArrayList<>()); - if (nums.length == 0) { - return answer; - } - for (int i = 1; i <= nums.length; i++) { - backTrace(answer, new ArrayList<>(), nums, i, 0); + for (int i = 0; i <= nums.length; i++) { + backtrace(answer, new ArrayList<>(), i, nums, 0); } return answer; - } - /** - * 这个我已经不想说了,太多一样的解法了 - * @param answer - * @param list - * @param nums - * @param max - * @param position - */ - private static void backTrace(List> answer, List list, int[] nums, int max, int position) { + private static void backtrace(List> answer, List list, int max, int[] nums, int position) { if (list.size() == max) { answer.add(new ArrayList<>(list)); return; } + for (int i = position; i < nums.length; i++) { list.add(nums[i]); - - backTrace(answer, list, nums, max, i + 1); + backtrace(answer, list, max, nums, i + 1); list.remove(list.size() - 1); } } diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_92_reverseLinkedList2.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_92_reverseLinkedList2.java index c3fde15..c5d337c 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_92_reverseLinkedList2.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/list/_92_reverseLinkedList2.java @@ -5,15 +5,14 @@ * @Date: 2020/6/1 下午7:01 * @Package: com.leosanqing.leetcode.medium * @Description: Reverse a linked list from position m to n. Do it in one-pass. - * 对反转给定范围的链表节点进行反转,只遍历一遍 - * - * Note: 1 ≤ m ≤ n ≤ length of list. - * - * Example: - * - * Input: 1->2->3->4->5->NULL, m = 2, n = 4 - * Output: 1->4->3->2->5->NULL - * + * 对反转给定范围的链表节点进行反转,只遍历一遍 + *

+ * Note: 1 ≤ m ≤ n ≤ length of list. + *

+ * Example: + *

+ * Input: 1->2->3->4->5->NULL, m = 2, n = 4 + * Output: 1->4->3->2->5->NULL * @Version: 1.0 */ public class _92_reverseLinkedList2 { @@ -52,20 +51,4 @@ public ListNode reverseBetween(ListNode head, int m, int n) { } - static class ListNode { - int val; - ListNode next; - - ListNode() { - } - - ListNode(int val) { - this.val = val; - } - - ListNode(int val, ListNode next) { - this.val = val; - this.next = next; - } - } } diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_139_word_break.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_139_word_break.java index 9df7513..b16fbac 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_139_word_break.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_139_word_break.java @@ -1,7 +1,9 @@ package com.leosanqing.leetcode.medium.string; -import java.util.*; -import java.util.stream.Collectors; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; /** * @Author: rtliu @@ -35,75 +37,44 @@ */ public class _139_word_break { + static Set set; + public static void main(String[] args) { String s = "leetcode"; - wordBreak(s, Arrays.asList("leet", "code")); + System.out.println(wordBreak(s, Arrays.asList("leet", "code"))); } public static boolean wordBreak(String s, List wordDict) { - return dfs(s, 0, new HashSet<>(wordDict), new HashSet<>()); + set = new HashSet<>(wordDict); + return backtrace(s, 0, new HashSet<>()); } - private static boolean backTrace(String s, int position, Set wordSet, Set set) { - // 如果到最后了 肯定完全匹配了, - // 因为这个position 是坐标,比如 上面的leetcode ,position 为 8,那么他已经完全匹配完了的,因为position为7时就已经匹配完了 + private static boolean backtrace(String s, int position, Set words) { if (position == s.length()) { return true; } - // 如果有这个坐标,那么就说明后面的试过了无效,可以直接返回 - if (set.contains(position)) { + // 如果存在,则说明已经尝试过这种方法,就直接返回 + if (words.contains(position)) { return false; } for (int i = position + 1; i <= s.length(); i++) { - String substring = s.substring(position, i); - if (!wordSet.contains(substring)) { + if (!set.contains(s.substring(position, i))) { continue; } - if (backTrace(s, i, wordSet, set)){ + if (backtrace(s, i, words)) { return true; - }else { - set.add(i); } + words.add(i); } - set.add(position); - - return false; - - } - - - private static boolean dfs(String s, int index, Set dict, Set set) { - // base case - if (index == s.length()) { - return true; - } - // check memory - if (set.contains(index)) { - return false; - } - // recursion - for (int i = index + 1; i <= s.length(); i++) { - String t = s.substring(index, i); - if (!dict.contains(t)) { - continue; - } - if (dfs(s, i, dict, set)) { - return true; - } else { - set.add(i); - } - } - - - set.add(index); + words.add(position); return false; } } diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_22_generate_parentheses.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_22_generate_parentheses.java index 18f4fe3..2b746b8 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_22_generate_parentheses.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_22_generate_parentheses.java @@ -31,31 +31,30 @@ public static void main(String[] args) { public static List generateParenthesis(int n) { List list = new ArrayList<>(); - - StringBuilder sb = new StringBuilder(); - - helper(list, sb, 0, 0, n); + backtrace(list, new StringBuilder(), 0, 0, n); return list; } - private static void helper(List list, StringBuilder sb, int open, int close, int max) { - if (open == max && close == max) { - list.add(sb.toString()); + private static void backtrace(List result, StringBuilder sb, int left, int right, int max) { + if (left == max && right == max) { + result.add(sb.toString()); return; } - if (open < max) { + + if (left <= max) { sb.append("("); - helper(list, sb, open + 1, close, max); - sb.setLength(sb.length() - 1); + backtrace(result, sb, left + 1, right, max); + sb.deleteCharAt(sb.length() - 1); } - // 注意这里,close < open ,这样就避免了 出现类似 ()))(( 的情况 - if (close < open ) { + // 避免出现 ())这种情况 + if (right < left) { sb.append(")"); - helper(list, sb, open, close + 1, max); - sb.setLength(sb.length() - 1); + backtrace(result, sb, left, right + 1, max); + sb.deleteCharAt(sb.length() - 1); } + } } diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_31_next_permutation.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_31_next_permutation.java new file mode 100644 index 0000000..ecdabb3 --- /dev/null +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_31_next_permutation.java @@ -0,0 +1,70 @@ +package com.leosanqing.leetcode.medium.string; + +import com.alibaba.fastjson.JSON; + +import java.util.Arrays; + +/** + * @description: ` 实现获取 下一个排列 的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。 + * ` + * ` 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。 + * ` + * ` 必须 原地 修改,只允许使用额外常数空间。 + * ` + * ` 示例 1: + * ` + * ` 输入:nums = [1,2,3] + * ` 输出:[1,3,2] + * ` 示例 2: + * ` + * ` 输入:nums = [3,2,1] + * ` 输出:[1,2,3] + * ` 示例 3: + * ` + * ` 输入:nums = [1,1,5] + * ` 输出:[1,5,1] + * ` 示例 4: + * ` + * ` 输入:nums = [1] + * ` 输出:[1] + * @author: rtliu + * @date: 2021/4/8 2:07 下午 + */ +public class _31_next_permutation { + public static void main(String[] args) { + nextPermutation(new int[]{1, 3, 2}); + } + + /** + * 1.从右到左找升序数字 + * 2.找到右边比当前数字大的数字,两个交换位置 + * 3.右边数字再重新升序排列 + * + * @param nums + */ + public static void nextPermutation(int[] nums) { + + for (int i = nums.length - 1; i > 0; i--) { + if (nums[i] < nums[i - 1]) { + continue; + } + + for (int j = nums.length - 1; j >= i; j--) { + if (nums[i - 1] > nums[j]) { + continue; + } + + // 从后面找比 num 大的数字,交换 + int temp = nums[i - 1]; + nums[i - 1] = nums[j]; + nums[j] = temp; + + Arrays.sort(nums, i, nums.length); + return; + + } + + } + Arrays.sort(nums); + } +} diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_3_longest_substring_without_repeating_characters.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_3_longest_substring_without_repeating_characters.java new file mode 100644 index 0000000..9f0589e --- /dev/null +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_3_longest_substring_without_repeating_characters.java @@ -0,0 +1,66 @@ +package com.leosanqing.leetcode.medium.string; + +import java.util.HashMap; +import java.util.Map; + +/** + * @description: Given a string s, find the length of the longest substring without repeating characters. + *

+ * 给定字符串s,找到最长子字符串的长度而不重复字符。 + *

+ * ` Example 1: + *

+ * ` Input: s = "abcabcbb" + * ` Output: 3 + * ` Explanation: The answer is "abc", with the length of 3. + * ` Example 2: + *

+ * ` Input: s = "bbbbb" + * ` Output: 1 + * ` Explanation: The answer is "b", with the length of 1. + * ` Example 3: + *

+ * ` Input: s = "pwwkew" + * ` Output: 3 + * ` Explanation: The answer is "wke", with the length of 3. + * ` Notice that the answer must be a substring, "pwke" is a subsequence and not a substring. + * ` Example 4: + *

+ * ` Input: s = "" + * ` Output: 0 + *

+ * ` @author: rtliu + * ` @date: 2021/4/6 3:41 下午 + */ +public class _3_longest_substring_without_repeating_characters { + public static void main(String[] args) { + System.out.println(lengthOfLongestSubstring("abba")); + } + + /** + * 这个是典型的滑动窗口类的题型 + * + * 我们遇到相同的字符就丢弃之前字符左边的所有字符 + * @param s + * @return + */ + public static int lengthOfLongestSubstring(String s) { + Map map = new HashMap<>(s.length() * 2); + + int result = 0; + int head = 0; + + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + + if (map.containsKey(c) && head < map.get(c)) { + head = map.get(c); + } + // i+1 表示当前字符的实际位置 + result = Math.max(i + 1 - head, result); + map.put(c, i + 1); + } + + return result; + } +} diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_5_longestPalindromicSubstring.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_5_longestPalindromicSubstring.java index 7957c4f..464db5c 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_5_longestPalindromicSubstring.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/string/_5_longestPalindromicSubstring.java @@ -20,42 +20,32 @@ */ public class _5_longestPalindromicSubstring { public static void main(String[] args) { - _5_longestPalindromicSubstring substring = new _5_longestPalindromicSubstring(); String s = "abasasaiug"; - System.out.println(substring.longestPalindrome(s)); + System.out.println(longestPalindrome(s)); } - private String longestPalindrome(String s) { + public static String longestPalindrome(String s) { if (s.length() < 2) { return s; } - String maxStr = ""; - + String longStr = ""; for (int i = 0; i < s.length(); i++) { - // s1 表示 sas 这种 ,s2 表示 saas 这种 - String s1 = extend(s, i, i), s2 = extend(s, i, i + 1); - if (maxStr.length() < s1.length()) { - maxStr = s1; + String s1 = findStr(s, i, i); + String s2 = findStr(s, i, i + 1); + + if (s1.length() > longStr.length()) { + longStr = s1; } - if (maxStr.length() < s2.length()) { - maxStr = s2; + if (s2.length() > longStr.length()) { + longStr = s2; } } - - return maxStr; + return longStr; } - - /** - * 以 i j 为中心,对称找回文 - * @param s 输入的字符串 - * @param i - * @param j - * @return - */ - private String extend(String s, int i, int j) { + private static String findStr(String s, int i, int j) { for (; i >= 0 && j < s.length(); i--, j++) { if (s.charAt(i) != s.charAt(j)) { break; diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/struct/_146_LRU_Cache.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/struct/_146_LRU_Cache.java new file mode 100644 index 0000000..c0ad5f0 --- /dev/null +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/struct/_146_LRU_Cache.java @@ -0,0 +1,131 @@ +package com.leosanqing.leetcode.medium.struct; + +import java.util.HashMap; +import java.util.Map; + +/** + * @description: 运用你所掌握的数据结构,设计和实现一个  LRU (最近最少使用) 缓存机制 。 + * 实现 LRUCache 类: + *

+ * LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存 + * int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。 + * void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。 + *

+ * 进阶:你是否可以在 O(1) 时间复杂度内完成这两种操作? + *

+ * 示例: + *

+ * 输入 + * ["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"] + * [[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]] + * 输出 + * [null, null, null, 1, null, -1, null, -1, 3, 4] + *

+ * 解释 + * LRUCache lRUCache = new LRUCache(2); + * lRUCache.put(1, 1); // 缓存是 {1=1} + * lRUCache.put(2, 2); // 缓存是 {1=1, 2=2} + * lRUCache.get(1); // 返回 1 + * lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3} + * lRUCache.get(2); // 返回 -1 (未找到) + * lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3} + * lRUCache.get(1); // 返回 -1 (未找到) + * lRUCache.get(3); // 返回 3 + * lRUCache.get(4); // 返回 4 + * @author: rtliu + * @date: 2021/4/25 9:57 上午 + */ +public class _146_LRU_Cache { + public static void main(String[] args) { + LRUCache lruCache = new LRUCache(1); + lruCache.put(2,1); + System.out.println(lruCache.get(2)); + } + + static class DLinkedNode { + int value; + int key; + DLinkedNode pre; + DLinkedNode next; + + public DLinkedNode() { + } + + public DLinkedNode(int key, int value) { + this.value = value; + this.key = key; + } + } + + static class LRUCache { + private Map map = new HashMap<>(); + private int size; + private int capacity; + private DLinkedNode head; + private DLinkedNode tail; + + public LRUCache(int capacity) { + this.size = 0; + this.capacity = capacity; + + // 使用虚拟的头尾节点,防止出现极限问题 + head = new DLinkedNode(); + tail = new DLinkedNode(); + head.next = tail; + tail.pre = head; + } + + public int get(int key) { + DLinkedNode node = map.get(key); + if (node == null) { + return -1; + } + moveToHead(node); + return node.value; + } + + public void put(int key, int value) { + DLinkedNode node = map.get(key); + if (node == null) { + DLinkedNode dLinkedNode = new DLinkedNode(key, value); + map.put(key, dLinkedNode); + + // 设置 头节点 + addToHead(dLinkedNode); + + ++size; + if (size > capacity) { + map.remove(removeTail().key); + --size; + } + } else { + node.value = value; + moveToHead(node); + } + } + + private DLinkedNode removeTail() { + DLinkedNode pre = tail.pre; + removeNode(pre); + return pre; + } + + private void removeNode(DLinkedNode node) { + node.pre.next = node.next; + node.next.pre = node.pre; + } + + private void addToHead(DLinkedNode dLinkedNode) { + dLinkedNode.pre = head; + dLinkedNode.next = head.next; + + head.next.pre = dLinkedNode; + head.next = dLinkedNode; + } + + private void moveToHead(DLinkedNode dLinkedNode) { + removeNode(dLinkedNode); + addToHead(dLinkedNode); + } + } +} diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_102_binary_tree_level_order_traversal.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_102_binary_tree_level_order_traversal.java index 5ec776e..a11fa00 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_102_binary_tree_level_order_traversal.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_102_binary_tree_level_order_traversal.java @@ -1,5 +1,7 @@ package com.leosanqing.leetcode.medium.tree; +import com.alibaba.fastjson.JSON; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -33,32 +35,31 @@ public static void main(String[] args) { treeNode.right = new TreeNode(20); treeNode.right.left = new TreeNode(1); treeNode.right.right = new TreeNode(7); - levelOrder(treeNode); + + System.out.println(JSON.toJSONString(levelOrder(treeNode))); } public static List> levelOrder(TreeNode root) { List> answer = new ArrayList<>(); - backTrace(answer, 0, root); + backtrace(answer, 0, root); return answer; } - - private static void backTrace(List> answer, int depth, TreeNode root) { - if (root == null) { + private static void backtrace(List> answer, int depth, TreeNode node) { + if (node == null) { return; } - if (answer.size() > depth) { - answer.get(depth).add(root.val); - } else { + if (depth >= answer.size()) { List list = new ArrayList<>(); - list.add(root.val); - answer.add(new ArrayList<>(list)); + list.add(node.val); + answer.add(list); + } else { + answer.get(depth).add(node.val); } - backTrace(answer, depth + 1, root.left); - backTrace(answer, depth + 1, root.right); - + backtrace(answer, depth + 1, node.left); + backtrace(answer, depth + 1, node.right); } } diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_105_construct_binary_tree_from_preorder_and_inorder_traversal.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_105_construct_binary_tree_from_preorder_and_inorder_traversal.java index 741deba..c2dd3ea 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_105_construct_binary_tree_from_preorder_and_inorder_traversal.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_105_construct_binary_tree_from_preorder_and_inorder_traversal.java @@ -1,5 +1,8 @@ package com.leosanqing.leetcode.medium.tree; +import java.util.HashMap; +import java.util.Map; + /** * @Author: rtliu * @Date: 2020/7/28 下午7:29 @@ -27,7 +30,7 @@ public static void main(String[] args) { int[] inorder = {11, 2, 14, 9, 8, 3, 16, 15, 20, 22, 7}; - TreeNode treeNode1 = backTrace(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1); +// TreeNode treeNode1 = backTrace(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1); TreeNode treeNode = buildTree(preorder, inorder); @@ -35,27 +38,37 @@ public static void main(String[] args) { } + private static Map indexMap; + public static TreeNode buildTree(int[] preorder, int[] inorder) { - return backTrace(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1); + + // 构造哈希映射,帮助我们快速定位根节点 + indexMap = new HashMap<>(preorder.length * 2); + for (int i = 0; i < preorder.length; i++) { + indexMap.put(inorder[i], i); + } + return backtrace(preorder, 0, preorder.length - 1, inorder, 0, preorder.length - 1); } - private static TreeNode backTrace(int[] preorder, int preStart, int preEnd, int[] inorder, int inStart, int inEnd) { - if (preStart > preorder.length - 1 || inStart > inEnd) { + private static TreeNode backtrace(int[] preorder, int preStart, int preEnd, int[] inorder, int inStart, int inEnd) { + if (preStart > preEnd) { return null; } - TreeNode root = new TreeNode(preorder[preStart]); - // 找到 inOrder 中 的索引 - int inIndex = 0; + // 在中序遍历中定位根节点 + int inorderRoot = indexMap.get(preorder[preStart]); - for (int i = inStart; i <= inEnd; i++) { - if (root.val == inorder[i]) { - inIndex = i; - } - } + // 先把根节点建立出来 + TreeNode root = new TreeNode(preorder[preStart]); + // 得到左子树中的节点数目 + int sizeLeftSubtree = inorderRoot - inStart; + // 递归地构造左子树,并连接到根节点 + // 先序遍历中「从 左边界+1 开始的 sizeLeftSubtree」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素 + root.left = backtrace(preorder, preStart + 1, preStart + sizeLeftSubtree, inorder, inStart, inorderRoot - 1); + // 递归地构造右子树,并连接到根节点 + // 先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素 + root.right = backtrace(preorder, preStart + sizeLeftSubtree + 1, preEnd, inorder, inorderRoot + 1, inEnd); - root.left = backTrace(preorder, preStart + 1, preEnd, inorder, inStart, inIndex - 1); - root.right = backTrace(preorder, preStart + inIndex - inStart + 1, preEnd, inorder, inIndex + 1, inEnd); return root; } } diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_114_flatten_binary_tree_to_linked_list.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_114_flatten_binary_tree_to_linked_list.java index 94aea7f..3a72eab 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_114_flatten_binary_tree_to_linked_list.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_114_flatten_binary_tree_to_linked_list.java @@ -32,20 +32,24 @@ public void flatten(TreeNode root) { if (root == null) { return; } + TreeNode left = root.left; TreeNode right = root.right; - root.left = null; + right.left = null; + flatten(left); flatten(right); root.right = left; + // 找到 左子树 最后一个节点,将其连接上 TreeNode cur = root; while (cur.right != null) { cur = cur.right; } cur.right = right; + } } diff --git a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_98_validate_binary_search_tree.java b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_98_validate_binary_search_tree.java index e6970a0..f96d6b5 100644 --- a/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_98_validate_binary_search_tree.java +++ b/java-note-algorithm/src/main/java/com/leosanqing/leetcode/medium/tree/_98_validate_binary_search_tree.java @@ -1,7 +1,5 @@ package com.leosanqing.leetcode.medium.tree; -import java.util.Stack; - /** * @Author: rtliu * @Date: 2020/7/27 上午10:31 @@ -50,9 +48,24 @@ private static boolean backTrace(TreeNode treeNode, Integer min, Integer max) { // 左子树一定小于父节点,右子树一定大于父节点 if ((max != null && treeNode.val >= max) - || (min != null && treeNode.val <= min )) { + || (min != null && treeNode.val <= min)) { return false; } return backTrace(treeNode.left, min, treeNode.val) && backTrace(treeNode.right, treeNode.val, max); } + + private static boolean backtrace(TreeNode treeNode, Integer max, Integer min) { + if (treeNode == null) { + return true; + } + + if ( + (max != null && treeNode.val >= max) + || (min != null && treeNode.val <= min) + ) { + return false; + } + return backtrace(treeNode.left, max, treeNode.val)&&backtrace(treeNode.right, treeNode.val, min); + } + }