算法Day20 | Leetcode39. 组合总和、40.组合总和II、131.分割回文串

39. 组合总和

力扣链接

思路

回溯,同一个元素可以重复取,那调用的时候就传自己进去。数组递增,所以当加起来的和大于target就可以返回了。

代码

class Solution {
    List<List<Integer>> result=new ArrayList<>();
    List<Integer> path=new ArrayList<>();
    int sum=0;
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        find(candidates,target,0);
        return result;
    }

    public void find(int[] candidates, int target,int startIndex){
        if(sum>target) return;
        if(sum==target){
            result.add(new ArrayList<>(path));
            return;
        }

        for(int i=startIndex;i<candidates.length;i++){
            path.add(candidates[i]);
            sum+=candidates[i];
            find(candidates,target,i);
            path.remove(path.size()-1);
            sum-=candidates[i];
        }
    }
}

40.组合总和II

力扣链接

思路

回溯,给的数组不是递增,所以要调用一下库函数排序(1.方便确认返回条件 2.可以避免取到重复组合)跟上面不一样的元素不能重复取,但是它可以提供重复元素(通过标记函数是否使用过,来剪枝。排序后,当前元素如果与前一个元素相同,并且前一个元素没有处于被使用状态,那就continue【因为我们取元素是往后取的,前一个元素没有被使用就相当于,当前元素的组合肯定和前一个元素组合相同,不是两个元素同时取的情况】)

代码

class Solution {
    List<List<Integer>> result=new ArrayList<>();
    List<Integer> path=new ArrayList<>();
    int[] haveUsed;
    int sum=0;
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        haveUsed=new int[candidates.length];
        Arrays.sort(candidates);
        find(candidates,target,0);
        return result;
    }

    public void find(int[] candidates, int target,int startIndex){
        if(sum==target){
            result.add(new ArrayList<>(path));
            return;
        }

        for(int i=startIndex;i<candidates.length;i++){
            if(sum+candidates[i]>target) break;
            if(i>0 && candidates[i]==candidates[i-1] && haveUsed[i-1]==0) continue;
            path.add(candidates[i]);
            sum+=candidates[i];
            haveUsed[i]=1;
            find(candidates,target,i+1);
            path.removeLast();
            sum-=candidates[i];
            haveUsed[i]=0;
        }
    }
}

131.分割回文串

力扣链接

思路

回溯,与上面不同的是,传的是固定的数组,但是这里传的是分割后的字符串,是一直在改变的,把startindex看作是隔板,一直划分。

代码

class Solution {
    List<List<String>> result=new ArrayList<>();
    List<String> pathList=new ArrayList<>();
    String path="";
    public List<List<String>> partition(String s) {
        find(s,0);
        return result;
    }

    public void find(String s,int startIndex){
        if(startIndex>=s.length()){
            result.add(new ArrayList<>(pathList));
        }

        for(int i=startIndex;i<s.length();i++){
            int len=path.length();
            path=s.substring(startIndex,i+1);
            if(!charge(path)) continue;
            pathList.add(path);
            find(s,i+1);
            pathList.remove(pathList.size()-1);
        }
    }

    public boolean charge(String s){
        int left=0;
        int right=s.length()-1;
        while(left<=right){
            if(s.charAt(left)!=s.charAt(right)) return false;
            left++;
            right--;
        }
        return true;
    }
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值