代码随想录训练营day27|回溯:39.组合总和、40.组合总和2、131.分割回文串

39.组合总和

思路:递归结束条件就是找到了这个target,并将结果放进去。至于超过target的情况就break,不找了。因为从小到大,接着找只会越来越大。其他情况就是小于那么先将当前的candidate[i] 放进temp 接着backtracing下一个数。
关键点:注意是可以重复的所以,在递归的时候的i不应去加1了。要是加一就是不重复的代码。

class Solution {
    List<List<Integer>> ans = new ArrayList<>();
    LinkedList<Integer> temp = new LinkedList<>();
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        // 这里的是可以重复使用
        Arrays.sort(candidates); // 要先进行排序 从小到大。不然第一个就超出了后面就不运行了
        backtracking(candidates, target,0,ans,temp);
        return ans;


    }
    public void backtracking(int[] candidates, int target, int index, List<List<Integer>> ans, LinkedList<Integer> temp){
        if(target == 0){
            ans.add(new ArrayList(temp));
            return;
        }
        for(int i=index;i<candidates.length;i++){
            if(target - candidates[i]<0){
                break;
            }
            temp.add(candidates[i]);
            backtracking(candidates,target-candidates[i],i,ans,temp); // 因为可以重复,所以i 不用+1
            temp.remove(temp.size() -1);
            }
        }

    }

LeetCode40组合总和2

思路:这里的区别主要是去重
而且是对每一层中不可以去重复数。节点内可以重复的。
这里没有使用一个辅助数组,只是在for循环的逻辑加了一个判断,前后不可以数字相等。
在这里插入图片描述

class Solution {
    List<List<Integer>> ans = new ArrayList<>();
    LinkedList<Integer> temp = new LinkedList<>();
    public List<List<Integer>> combinationSum2(int[] candidates, int target){
        // 本题candidates 中的每个数字在每个组合中只能使用一次。
        // 本题数组candidates的元素是有重复的,而39.组合总和 (opens new window)是无重复元素的数组candidates

        // 这题多了一层去重的逻辑
        Arrays.sort(candidates);
        backtracing(candidates, target, 0, ans, temp);
        return ans;
    }
    public void backtracing(int[] candidates, int target, int index, List<List<Integer>> ans, LinkedList<Integer> temp){
        if(target == 0){
            ans.add(new ArrayList(temp));
        }
        for(int i=index;i<candidates.length;i++){
            if(target - candidates[i]<0){
                break;
            }
            if(i>index && candidates[i] == candidates[i-1]){ // 加了一个逻辑来判断这个数之前是否选过。而且这里的去重是对每一层里面不能选重复的,而不是叶子里不能选重复的。按照那个图来理解。
                continue;
            }
            temp.add(candidates[i]);
            backtracing(candidates, target-candidates[i], i+1, ans, temp); // 元素只能使用一次,因此i+1
            temp.remove(temp.size() - 1);
        }
    }
}

LeetCode131分割回文串

关于String的处理函数要熟悉
在Java中,String类提供了许多用于处理字符串的常见函数。以下是一些常用的String函数:

  1. length(): 返回字符串的长度。

    String str = "Hello";
    int length = str.length(); // length = 5
    
  2. charAt(int index): 返回字符串中指定索引位置的字符。

    String str = "Hello";
    char ch = str.charAt(1); // ch = 'e'
    
  3. substring(int beginIndex): 返回从指定索引位置开始到字符串末尾的子字符串。

    String str = "Hello";
    String subStr = str.substring(1); // subStr = "ello"
    
  4. substring(int beginIndex, int endIndex): 返回从指定的开始索引位置到指定的结束索引位置之间的子字符串。

    String str = "Hello";
    String subStr = str.substring(1, 4); // subStr = "ell"
    
  5. equals(String anotherString): 比较两个字符串是否相等。

    String str1 = "Hello";
    String str2 = "hello";
    boolean isEqual = str1.equals(str2); // isEqual = false
    
  6. equalsIgnoreCase(String anotherString): 忽略大小写,比较两个字符串是否相等。

    String str1 = "Hello";
    String str2 = "hello";
    boolean isEqual = str1.equalsIgnoreCase(str2); // isEqual = true
    
  7. indexOf(String str): 返回指定子字符串第一次出现的索引位置。

    String str = "Hello world";
    int index = str.indexOf("world"); // index = 6
    
  8. lastIndexOf(String str): 返回指定子字符串最后一次出现的索引位置。

    String str = "Hello world";
    int index = str.lastIndexOf("o"); // index = 7
    
  9. replace(char oldChar, char newChar): 将字符串中的指定字符替换为新的字符。

    String str = "Hello";
    String newStr = str.replace('l', 'L'); // newStr = "HeLLo"
    
  10. toLowerCase(): 将字符串转换为小写。

    String str = "Hello";
    String lowerCaseStr = str.toLowerCase(); // lowerCaseStr = "hello"
    
  11. toUpperCase(): 将字符串转换为大写。

    String str = "Hello";
    String upperCaseStr = str.toUpperCase(); // upperCaseStr = "HELLO"
    

这只是一些常见的String函数示例,Java的String类还提供了许多其他有用的函数,可以根据具体的需求选择适当的函数进行字符串处理。

思路:

  • 切割问题可以抽象为组合问题
  • 如何模拟那些切割线
  • 切割问题中递归如何终止
  • 在递归循环中如何截取子串
  • 如何判断回文
    和组合一致,横向for的时候依次向后面选(划分)。只不过在内部要判断从当前index开始到后面每个字符能不能组成回文。
    满足回文的情况就添加到temp 并递归回溯。
class Solution {
    List<List<String>> ans = new ArrayList<>();
    LinkedList<String> temp = new LinkedList<>();
    public List<List<String>> partition(String s) {
        backtracing(s,0);
        return ans;
    }
    public void backtracing(String s, int index){
        if(index == s.length()){ // index是便利s中的元素,如果index已经超过了s.length 表示有结果了
            ans.add(new ArrayList(temp));
        }
        for(int i=index;i<s.length();i++){
            if(isPalindrome(s, index, i)){ // 从每个index开始遍历后面的字符 判断是否为回文
                String strSub = s.substring(index, i+1); // 左闭右开
                temp.add(strSub);
                backtracing(s, i+1);
                temp.removeLast();
            }
            // else{
            //     continue; // 如果不是回文,则下面的代码也不执行,并且跳到下一个
            // }
            

        }
    }
    private boolean isPalindrome(String s, int start, int end){ // 判断是否为回文的基础方法,这里可以用动态规划来做优化。
        for(int i=start,j=end;i<j;i++,j--){
            if(s.charAt(i) != s.charAt(j)){
                return false;
            }
        }
        return true;
    }
}    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值