diff --git a/src/main/java/array/ValidMountainArray.java b/src/main/java/array/ValidMountainArray.java new file mode 100644 index 0000000..409fd3e --- /dev/null +++ b/src/main/java/array/ValidMountainArray.java @@ -0,0 +1,42 @@ +package array; +/** + * 题目: 941. 有效的山脉数组 (validMountainArray) + * 描述:给定一个整数数组 arr,如果它是有效的山脉数组就返回 true,否则返回 false。 + * + * 让我们回顾一下,如果 arr 满足下述条件,那么它是一个山脉数组: + * + * arr.length >= 3 + * 在 0 < i < arr.length - 1 条件下,存在 i 使得: + * arr[0] < arr[1] < ... arr[i-1] < arr[i] + * arr[i] > arr[i+1] > ... > arr[arr.length - 1] + + 示例 1: + 输入:arr = [2,1] + 输出:false + + + * 链接:https://leetcode.cn/problems/valid-mountain-array/ + */ +public class ValidMountainArray { + public boolean validMountainArray(int[] arr) { + if (arr.length < 3) { // 此时,一定不是有效的山脉数组 + return false; + } + // 双指针 + int left = 0; + int right = arr.length - 1; + // 注意防止指针越界 + while (left + 1 < arr.length && arr[left] < arr[left + 1]) { + left++; + } + // 注意防止指针越界 + while (right > 0 && arr[right] < arr[right - 1]) { + right--; + } + // 如果left或者right都在起始位置,说明不是山峰 + if (left == right && left != 0 && right != arr.length - 1) { + return true; + } + return false; + } +} diff --git a/src/main/java/backtrack/FindSubsequences.java b/src/main/java/backtrack/FindSubsequences.java new file mode 100644 index 0000000..45b5db2 --- /dev/null +++ b/src/main/java/backtrack/FindSubsequences.java @@ -0,0 +1,55 @@ +package backtrack; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * 题目: 491. 非递减子序列 (findSubsequences) + * 描述:给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。 + * 数组中可能含有重复元素,如出现两个整数相等,也可以视作递增序列的一种特殊情况。 + + 示例 1: + 输入:nums = [4,6,7,7] + 输出:[[4,6],[4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7],[6,7,7],[7,7]] + + * 链接:https://leetcode.cn/problems/palindrome-partitioning/ + */ +//不会做 +public class FindSubsequences { + /** + * 用一个局部 Set used 来去重,保证同一深度只选一次相同的数字。 + * 只有当当前路径为空或新加入的数字 ≥ 路径最后一个数字时,才继续深入。 + * 每次路径长度达到 ≥2 时,就收集一组结果。 + * @param nums + * @return + */ + public List> findSubsequences(int[] nums) { + List> res = new ArrayList<>(); + backtrack(nums, 0, new ArrayList<>(), res); + return res; + } + + private void backtrack(int[] nums, int start, List path, List> res) { + // 只要当前 path 长度 ≥2,就把它加入结果集 + if (path.size() >= 2) { + res.add(new ArrayList<>(path)); + } + // 用来在本层去重,防止同一层重复使用相同数字 这一步太妙了!!! + Set used = new HashSet<>(); + for (int i = start; i < nums.length; i++) { + // 如果本层已经用过 nums[i],跳过 + if (used.contains(nums[i])) continue; + // 如果 path 为空或满足非递减条件,就可以选 nums[i] + if (path.isEmpty() || nums[i] >= path.get(path.size() - 1)) { + used.add(nums[i]); + path.add(nums[i]); + // 递归到下一层,从 i+1 开始选 + backtrack(nums, i + 1, path, res); + // 撤销选择 + path.remove(path.size() - 1); + } + } + } +} diff --git a/src/main/java/backtrack/RestoreIpAddresses.java b/src/main/java/backtrack/RestoreIpAddresses.java index 6d070eb..0bab581 100644 --- a/src/main/java/backtrack/RestoreIpAddresses.java +++ b/src/main/java/backtrack/RestoreIpAddresses.java @@ -1,5 +1,6 @@ package backtrack; + import java.util.ArrayList; import java.util.List; @@ -17,23 +18,41 @@ import java.util.List; * 链接:https://leetcode.cn/problems/restore-ip-addresses/ */ public class RestoreIpAddresses { - void dfs(Listres,Listpath,String s,int minStep){ - if(path.size()==4){ - StringBuilder sb=new StringBuilder(); - sb.append(path.get(0)); - for (int i = 1; i < path.size(); i++) { - sb.append('.').append(path.get(i)); + public List restoreIpAddresses(String s) { + List res = new ArrayList<>(); + dfs(s, 0, 0, new StringBuilder(), res); + return res; + } + + private void dfs(String s, int start, int segment, StringBuilder sb, List res) { + // 如果已经凑够 4 段,且正好遍历完字符串 + if (segment == 4) { + if (start == s.length()) { + // 去掉最后多余的 “.” + res.add(sb.substring(0, sb.length() - 1)); } - res.add(sb.toString()); + return; } - for (int i = minStep; i < s.length(); i++) { - + // 剩余字符太少或太多,提前剪枝 + int remain = s.length() - start; + if (remain < (4 - segment) || remain > (4 - segment) * 3) return; //很妙 + + // 尝试长度为 1、2、3 的子段 + for (int len = 1; len <= 3 && start + len <= s.length(); len++) { + String part = s.substring(start, start + len); + if (!isValidPart(part)) continue; + + int before = sb.length(); + sb.append(part).append('.'); + dfs(s, start + len, segment + 1, sb, res); + // 回溯:删除 “数字 + 点” 的长度 + sb.delete(before, sb.length()); } } - public List restoreIpAddresses(String s) { - Listres=new ArrayList<>(); - Listpath=new ArrayList<>(); - StringBuilder sb=new StringBuilder(); - return null; + + private boolean isValidPart(String part) { + // 单字符“0”合法,多于 1 位时不能以 0 开头,且数值 ≤ 255 + if (part.length() > 1 && part.startsWith("0")) return false; + return Integer.parseInt(part) <= 255; } }