39. 组合总和 和 面试题 组合之感

 今天问题还是挺严重的,自己以为会的其实都是模棱两可,就包括回溯算法,回溯算法最重要的是对于状态的暂停,状态的汇总,和开始的标志,首先第一题,限制条件是数字之和为target,允许的条件是可以无限次数的读取数组中的元素,但是解集不能重复,所以不妨给他设立标签,就是每轮都进行筛选  代码如下

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.List;

public class Solution {

    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> res = new ArrayList<>();
        int len = candidates.length;

        // 排序是为了提前终止搜索
        Arrays.sort(candidates);

        dfs(candidates, len, target, 0, new ArrayDeque<>(), res);
        return res;
    }

    /**
     * @param candidates 数组输入
     * @param len        输入数组的长度,冗余变量
     * @param residue    剩余数值
     * @param begin      本轮搜索的起点下标
     * @param path       从根结点到任意结点的路径
     * @param res        结果集变量
     */
    private void dfs(int[] candidates,
                     int len,
                     int residue,
                     int begin,
                     Deque<Integer> path,
                     List<List<Integer>> res) {
        if (residue == 0) {
            // 由于 path 全局只使用一份,到叶子结点的时候需要做一个拷贝
            res.add(new ArrayList<>(path));
            return;
        }

        for (int i = begin; i < len; i++) {

            // 在数组有序的前提下,剪枝
            if (residue - candidates[i] < 0) {
                break;
            }

            path.addLast(candidates[i]);
            dfs(candidates, len, residue - candidates[i], i, path, res);
            path.removeLast();

        }
    }
}

每轮都是i   也就是说 每轮都从原地开始找,实在找不到再去i+1 也就是下一轮进行寻找。

 

 

而第二题!限制条件呢  , 主要是长度问题,字符串必须全部读取了,相当于说生成字符串的长度与原来字符串相同,但是每个元素只能读取一次,那么我们就必须进行元素读取的限制了,每次只能读一个,我们就用visited数组,进行元素标记,读取过得就进行标记,进行嵌套读取就行,循环的条件是对于visited数组的遍历,每次都找到没有标记的visited数组就可以,但是有人会问,每次都是从0开始,是怎么一步一步形成所有的字符串呢,解答如下,因为虽然每次都是从0开始,但是我们的标准是对于字符串长度的限制,0长度时候从0开始,1长度也是从0开始,1长度的时候,是对于上一层选取了一个字符进行1长度的筛选。代码如下:

    public String[] permutation(String s) {
        if(s.equals("")) return new String[0];
        char[] schars=s.toCharArray();
        boolean[] visited=new boolean[schars.length];
        Set<String>set=new HashSet<>();
            dfs_per(set,"",visited,schars);

        String[] res=  new String[set.size()];
               return set.toArray(res);
 
    }
    public void dfs_per(Set<String>res,String str,boolean[] visited,char[] sc){
        if(str.length()==sc.length){
            res.add(new String(str));
            System.out.println(str);
            return;
        }
        
        for(int i=0;i<sc.length;i++){
            if(visited[i]==true) continue;
            visited[i]=true;
            dfs_per(res,str+sc[i],visited,sc);
            visited[i]=false;
        }
    }

    意思是 每次循环结束的时候,找到上一层的循环时候,我必须解除这一层的遍历标记,然后默认上一层元素从0变成了1,然后再把1进行标记,再进行搜索,完成了遍历所有元素的任务!!!!!~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值