LeetCode-0607

90. 子集 II(中等)

思路:在深搜的过程中不断加入子集合,并且同层次(同一层for)的搜索里面去掉重复元素

class Solution {

    private List<List<Integer>> res;

    public List<List<Integer>> subsetsWithDup(int[] nums) {

        res = new ArrayList<>();
        List<Integer> ans = new ArrayList<>();
        res.add(new ArrayList<>());

        Arrays.sort(nums);

        dfs(nums,ans,0);
        
        return res;
    }

    public void dfs(int[] nums,List<Integer> ans,int it){
        if(it == nums.length){
            return;
        }
        int last = -11;
        for(int i=it;i<nums.length;i++){
            if(nums[i]==last){
                continue;
            }
            ans.add(nums[i]);
            res.add(new ArrayList<>(ans));
            dfs(nums,ans,i+1);
            ans.remove(ans.size()-1);
            last = nums[i];
        }
    }
}

491. 递增子序列(中等)

思路:大体和之前一样,但是由于不可以自己排序,所以需要用set去重不能用last

class Solution {

    private List<List<Integer>> res;

    public List<List<Integer>> findSubsequences(int[] nums) {

        res = new ArrayList<>();
        List<Integer> path  = new ArrayList<>();

        dfs(nums,path,0);

        return res;
    }


    public void dfs(int[] nums,List<Integer> path,int it){
        if(it == nums.length){
            return ;
        }

        Set<Integer> iset = new HashSet<>();
        
        for(int i=it;i<nums.length;i++){
            if(iset.contains(nums[i])||(path.size()>0&&nums[i]<path.get(path.size()-1))) continue;

            path.add(nums[i]);
            if(path.size()>=2) res.add(new ArrayList<>(path));
            dfs(nums,path,i+1);
            path.remove(path.size()-1);
            
            iset.add(nums[i]);
        }
    }
}

46. 全排列(中等)

思路:dfs,用set去维护不重复,没有顺序,每次for都从0开始,已经存在的元素跳过

class Solution {

    List<List<Integer>> res;

    public List<List<Integer>> permute(int[] nums) {

        res = new ArrayList<>();
        List<Integer> path = new ArrayList<>();
        Set<Integer> iset = new HashSet<>();

        dfs(nums,path,iset);

        return res;
    }

    public void dfs(int[] nums, List<Integer> path,Set<Integer> iset){

        if(path.size()==nums.length){
            res.add(new ArrayList<>(path));
            return ;
        }

        for(int i=0;i<nums.length;i++){
            if(iset.contains(nums[i]))continue;
            
            iset.add(nums[i]);
            path.add(nums[i]);
            
            dfs(nums,path,iset);
            
            iset.remove(nums[i]);
            path.remove(path.size()-1);

        }

    }
}

47. 全排列 II(中等)

思路:因为可能存在重复元素,set维护元素下标,同一层for再用一个set维护不出现重复的排列。

存在问题:执行速度慢,看了一下题解,不用set,用数组标记,同层用排序之后相邻去比较

class Solution {

    List<List<Integer>> res;

    public List<List<Integer>> permuteUnique(int[] nums) {

        res = new ArrayList<>();
        List<Integer> path = new ArrayList<>();
        Set<Integer> iset = new HashSet<>();

        dfs(nums,path,iset);

        return res;
    }


    public void dfs(int[] nums, List<Integer> path,Set<Integer> iset){

        if(path.size()==nums.length){
            res.add(new ArrayList<>(path));
            return ;
        }

        Set<Integer> forset = new HashSet<>();

        for(int i=0;i<nums.length;i++){
            if(iset.contains(i)||forset.contains(nums[i])){
                forset.add(nums[i]);
                continue;
            }
            
            iset.add(i);
            path.add(nums[i]);
           
            
            dfs(nums,path,iset);
            
            iset.remove(i);
            path.remove(path.size()-1);

        }

    }
}
//	官方题解
class Solution {
    boolean[] vis;

    public List<List<Integer>> permuteUnique(int[] nums) {
        List<List<Integer>> ans = new ArrayList<List<Integer>>();
        List<Integer> perm = new ArrayList<Integer>();
        vis = new boolean[nums.length];
        Arrays.sort(nums);
        backtrack(nums, ans, 0, perm);
        return ans;
    }

    public void backtrack(int[] nums, List<List<Integer>> ans, int idx, List<Integer> perm) {
        if (idx == nums.length) {
            ans.add(new ArrayList<Integer>(perm));
            return;
        }
        for (int i = 0; i < nums.length; ++i) {
            if (vis[i] || (i > 0 && nums[i] == nums[i - 1] && !vis[i - 1])) {
                continue;
            }
            perm.add(nums[i]);
            vis[i] = true;
            backtrack(nums, ans, idx + 1, perm);
            vis[i] = false;
            perm.remove(idx);
        }
    }
}

332. 重新安排行程(困难)

思路:欧拉回路。使用map存两城市间的路径,一直选择最小的,虽然不一定是完整通路,但是一定是路径的一部分,所以可以先选择,如果走不完整说明是末尾那段,先写进去;然后再从剩下的路径里面找最小,继续走

class Solution {

    private List<String> res = new ArrayList<>();
    private Map<String,PriorityQueue<String>> map = new HashMap<>();

    public List<String> findItinerary(List<List<String>> tickets) {

        for(List<String> ticket:tickets){
            String start = ticket.get(0);
            String dst = ticket.get(1);

            if(!map.containsKey(start)){
                map.put(start,new PriorityQueue<String>());
            }
            map.get(start).offer(dst);
        }

        dfs("JFK");

        Collections.reverse(res);

        return res;

    }

    public void dfs(String start){
        while(map.containsKey(start)&&map.get(start).size()>0){
            dfs(map.get(start).poll());
        }
        res.add(start);
    }

}

你可能感兴趣的:(LeetCode,leetcode,深度优先,算法)