6.8 回溯+数组
This commit is contained in:
parent
5871e339f1
commit
a26333688a
42
src/main/java/array/ValidMountainArray.java
Normal file
42
src/main/java/array/ValidMountainArray.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
55
src/main/java/backtrack/FindSubsequences.java
Normal file
55
src/main/java/backtrack/FindSubsequences.java
Normal file
@ -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<Integer> used 来去重,保证同一深度只选一次相同的数字。
|
||||
* 只有当当前路径为空或新加入的数字 ≥ 路径最后一个数字时,才继续深入。
|
||||
* 每次路径长度达到 ≥2 时,就收集一组结果。
|
||||
* @param nums
|
||||
* @return
|
||||
*/
|
||||
public List<List<Integer>> findSubsequences(int[] nums) {
|
||||
List<List<Integer>> res = new ArrayList<>();
|
||||
backtrack(nums, 0, new ArrayList<>(), res);
|
||||
return res;
|
||||
}
|
||||
|
||||
private void backtrack(int[] nums, int start, List<Integer> path, List<List<Integer>> res) {
|
||||
// 只要当前 path 长度 ≥2,就把它加入结果集
|
||||
if (path.size() >= 2) {
|
||||
res.add(new ArrayList<>(path));
|
||||
}
|
||||
// 用来在本层去重,防止同一层重复使用相同数字 这一步太妙了!!!
|
||||
Set<Integer> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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(List<String>res,List<String>path,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<String> restoreIpAddresses(String s) {
|
||||
List<String> res = new ArrayList<>();
|
||||
dfs(s, 0, 0, new StringBuilder(), res);
|
||||
return res;
|
||||
}
|
||||
|
||||
private void dfs(String s, int start, int segment, StringBuilder sb, List<String> 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<String> restoreIpAddresses(String s) {
|
||||
List<String>res=new ArrayList<>();
|
||||
List<String>path=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;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user