day24 131. 分割回文串&&40. 组合总和 II&&39. 组合总和

    1. 分割回文串
      问题描述
      给定一个字符串 s,将字符串分割成若干个子字符串,使得每个子字符串都是回文串。返回所有可能的分割方式。
      解题思路
      使用深度优先搜索(DFS)和回溯法:
      使用递归函数 dfsPartition,从字符串的起始位置开始尝试分割。
      对于每个可能的分割点,检查当前子字符串是否为回文。
      如果是回文,则将其加入当前路径,并递归处理剩余部分。
      如果到达字符串末尾且所有子字符串均为回文,则将当前路径加入结果列表。

//131. 分割回文串
public List<List> partition(String s) {
List<List> res = new ArrayList<>();
LinkedList stack = new LinkedList<>();
dfsPartition(res, stack, s, 0);
return res;
}
private void dfsPartition(List<List> res,LinkedList stack,String s,int start){
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 方法是从栈顶(链表头部)移除元素。

    1. 组合总和 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;
      LinkedList stack = new LinkedList<>();
      dfsCombinationSum2(candidates,target,res,stack,0);
      return res;
      }
      private void dfsCombinationSum2(int[] candidates, int target, List<List> res,LinkedList stack,int start) {
      if (sum2
      target) {
      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();
      }
      }
    1. 组合总和
      问题描述
      给定一个数组 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;
      LinkedList stack = 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();
      }
      }
posted @   123木头人-10086  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示