-
- 分割回文串
问题描述
给定一个字符串 s,将字符串分割成若干个子字符串,使得每个子字符串都是回文串。返回所有可能的分割方式。
解题思路
使用深度优先搜索(DFS)和回溯法:
使用递归函数 dfsPartition,从字符串的起始位置开始尝试分割。
对于每个可能的分割点,检查当前子字符串是否为回文。
如果是回文,则将其加入当前路径,并递归处理剩余部分。
如果到达字符串末尾且所有子字符串均为回文,则将当前路径加入结果列表。
- 分割回文串
//131. 分割回文串
public List<List
List<List
LinkedList
dfsPartition(res, stack, s, 0);
return res;
}
private void dfsPartition(List<List
if (starts.length()){
res.add(new ArrayList<>(stack));
return;
}
for (int i=1; start+i<=s.length(); i++){//i决定截取字符串的长度
//左闭右开
String str=s.substring(start,start+i);
if (!isPalindrome(str)) continue;
//在 Java 的 LinkedList 中,push 方法是将元素添加到栈顶(即链表的头部),而 pop 方法是从栈顶(链表头部)移除元素。
//因此如果使用栈的操作会导致内部集合的元素顺序相反。
stack.add(str);
dfsPartition(res,stack,s,start+i);
stack.removeLast();
}
}
private boolean isPalindrome(String s) {
if (s.length()1) return true;
int left =0,right=s.length()-1;
while (left<right){
if (s.charAt(left)!=s.charAt(right)) {
return false;
}
left++;
right--;
}
return true;
}
注意点:回溯使用 stack.add 和 stack.removeLast,避免使用 push 和 pop 导致顺序问题。
在 Java 的 LinkedList 中,push 方法是将元素添加到栈顶(即链表的头部),而 pop 方法是从栈顶(链表头部)移除元素。
-
- 组合总和 II
问题描述
给定一个数组 candidates 和一个目标值 target,找出数组中所有和为目标值的组合。数组中的数字可以重复使用,但每个数字只能使用一次。
解题思路
对数组进行排序,便于去重。
使用深度优先搜索(DFS)和回溯法:
从当前索引开始,尝试选择每个数字。
如果当前路径的和等于目标值,则将其加入结果列表。
跳过重复的数字,避免重复组合。
使用全局变量 sum2 记录当前路径的和。
注意点
去重:通过 if (i > start && candidates[i] == candidates[i - 1]) continue 跳过重复的数字。
提前终止:如果当前路径的和超过目标值,直接返回。
全局变量:使用 sum2 记录当前路径的和,但需要在递归前后正确更新其值。
//40. 组合总和 II
private int sum2=0;
public List<List> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
List<List> res = new ArrayList<>();
if(candidates.length0) return res;
LinkedListstack = new LinkedList<>(); target) {
dfsCombinationSum2(candidates,target,res,stack,0);
return res;
}
private void dfsCombinationSum2(int[] candidates, int target, List<List> res,LinkedList stack,int start) {
if (sum2
res.add(new ArrayList<>(stack));
return;
}
if(stack.size()candidates.length) return;
for(int i=start; i<candidates.length; i++) {
if(i>start && candidates[i]candidates[i-1]) continue;
if(sum2+candidates[i]>target) return;
sum2+=candidates[i];
stack.push(candidates[i]);
dfsCombinationSum2(candidates, target, res, stack, i+1);
sum2-=candidates[i];
stack.pop();
}
}
- 组合总和 II
-
- 组合总和
问题描述
给定一个数组 candidates 和一个目标值 target,找出数组中所有和为目标值的组合。数组中的数字可以重复使用。
解题思路
对数组进行排序(可选,但有助于剪枝)。
使用深度优先搜索(DFS)和回溯法:
从当前索引开始,尝试选择每个数字。
如果当前路径的和等于目标值,则将其加入结果列表。
如果当前路径的和超过目标值,则提前终止。
允许重复使用当前数字,因此递归时传递相同的索引。
注意点
剪枝:如果当前路径的和超过目标值,直接返回。
重复使用数字:递归时传递相同的索引 i,允许重复使用当前数字。
回溯:使用 stack.push 和 stack.pop 管理当前路径。
//39. 组合总和
public List<List> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
List<List> result = new ArrayList<>();
if(candidates.length == 0) return result;
LinkedListstack = new LinkedList<>();
dfCombinationSum(candidates,target,result,stack,0,0);
return result;
}
private void dfCombinationSum(int[] candidates, int target,List<List> result, LinkedList stack,int sum,int start) {
if (sum == target) {
result.add(new ArrayList<>(stack));
return;
} else if (sum>target) {
return;
}
for (int i =start; i < candidates.length; i++) {
if(sum+candidates[i]>target) return;
stack.push(candidates[i]);
dfCombinationSum(candidates, target, result, stack, sum+candidates[i],i);
stack.pop();
}
}
- 组合总和