代码随想录 第二十七天 | ● 39. 组合总和 ● 40.组合总和II ● 131.分割回文串

leetcode:39. 组合总和 - 力扣(LeetCode)

 思路:和组合一样,区别在于可以重复。如果递归里startIndex是starIndex的话,会发生后边都是由全部的数组成的,不是记录一个后往下一个走,这样就去重不了,

 

class Solution {
        LinkedList<Integer> list = new LinkedList<>();
        List<List<Integer>> res = new ArrayList<>();
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        int sum ;
        int startIndex;
        //安数组,所以说0
        backtracking(candidates,target,0,0);
        return  res;


    }

    private void backtracking(int[] candidates, int target, int sum,int startIndex) {
        //大于目标值退出
        if(sum > target){
            return;
        }
        //等于目标值记录并退出
        if(sum == target){
            res.add(new ArrayList<>(list));
            return;
        }
        //单层逻辑,遍历一遍,每次将遇到的数sum+=,递归,-=和删除是去重也是回溯,
        for(int i = startIndex ; i < candidates.length; i++){
            list.add(candidates[i]);
            sum += candidates[i];
            backtracking(candidates,target,sum,i);
            sum -= candidates[i];
            list.removeLast();
        }



    }
}

leetcode:39. 组合总和 - 力扣(LeetCode) 太狠了哥,放弃

class Solution {
  LinkedList<Integer> path = new LinkedList<>();
  List<List<Integer>> ans = new ArrayList<>();
  boolean[] used;
  int sum = 0;

  public List<List<Integer>> combinationSum2(int[] candidates, int target) {
    used = new boolean[candidates.length];
    // 加标志数组,用来辅助判断同层节点是否已经遍历
    Arrays.fill(used, false);
    // 为了将重复的数字都放到一起,所以先进行排序
    Arrays.sort(candidates);
    backTracking(candidates, target, 0);
    return ans;
  }

  private void backTracking(int[] candidates, int target, int startIndex) {
    if (sum == target) {
      ans.add(new ArrayList(path));
    }
    for (int i = startIndex; i < candidates.length; i++) {
      if (sum + candidates[i] > target) {
        break;
      }
      // 出现重复节点,同层的第一个节点已经被访问过,所以直接跳过
      if (i > 0 && candidates[i] == candidates[i - 1] && !used[i - 1]) {
        continue;
      }
      used[i] = true;
      sum += candidates[i];
      path.add(candidates[i]);
      // 每个节点仅能选择一次,所以从下一位开始
      backTracking(candidates, target, i + 1);
      used[i] = false;
      sum -= candidates[i];
      path.removeLast();
    }
  }
}

 leetcode:131. 分割回文串 - 力扣(LeetCode)

[object Object]substring (索引,索引)左闭右开,用来提取字符串的一个方法

验证是否是回文串,只需要验证从开头和结尾是否相同字母或数字

private boolean isPalindrome(String s , int a , int b){
        for(int i = a , j = b;i < j ;i++,j--){
            if(s.charAt(a) != s.charAt(b)){
                return false;
            }
        }
        return true;
    }

思路:和组合差不多,1,验证回文串,2,回溯,这回不需要重复数字了,直接用 i +1 遍历

class Solution {
        LinkedList<String> list = new LinkedList();
        List<List<String>> res = new ArrayList<>();
    public List<List<String>> partition(String s) {
        int startIndex = 0;
        backtracking(s,0);
        return res;
    }
    //回溯需要字符串和下一索引
    public  void backtracking(String s ,int StartIndex){
        //分割字符串的目的,如果起始位置大于s的大小,说明找到了一组分割方案
        if(StartIndex >= s.length()){
            res.add(new ArrayList<>(list));
            return;
        }
        //回溯判断回文串
        for(int i = StartIndex ; i < s.length() ; i++){
            if(isPalindrome(s,StartIndex,i)){
                list.addLast(s.substring(StartIndex,i+1));
            }else {
                continue;
            }
            //起始位置后移,保证不重复
            backtracking(s,i + 1);
            list.removeLast();

        }
    }
    private boolean isPalindrome(String s , int a , int b){
        for(int i = a , j = b;i < j ;i++,j--){
            if(s.charAt(i) != s.charAt(j)){
                return false;
            }
        }
        return true;
    }

}

 

posted @ 2024-03-26 15:53  22软工冷薄  阅读(1)  评论(0编辑  收藏  举报