Java-算法-回溯<三>

此篇承接上文:

Java-算法-回溯<一>

Java-算法-回溯<二>

一. 简单介绍

1. 回溯算法简单介绍

        见Java-算法-回溯<一>

2. 回溯算法一般模板

        见Java-算法-回溯<一>

 3. 回溯算法的树型转换

        见Java-算法-回溯<一>

二. leetcode实战

1~11 见Java-算法-回溯<一><二>

12. leetcode47 全排列II

给定一个可包含重复数字的序列 nums按任意顺序 返回所有不重复的全排列。

输入:nums = [1,1,2]
输出:
[[1,1,2],
 [1,2,1],
 [2,1,1]]

class Solution {
    List<List<Integer>> ans = new ArrayList<>();
    int[] used;
    public List<List<Integer>> permuteUnique(int[] nums) {
        List<Integer> path = new ArrayList<>();
        Arrays.sort(nums);
        used = new int[nums.length];
        dfs(nums,path);
        return ans;
    }
    public void dfs(int[] nums, List<Integer> path){
        
        if(path.size() == nums.length){
            ans.add(new ArrayList<Integer>(path));
            return;
        }
        for(int i = 0; i < nums.length; i++){
            if(used[i] == 1 || i > 0 && nums[i] == nums[i-1] && used[i-1] == 1) continue;
            used[i] = 1;
            path.add(nums[i]);
            dfs(nums,path);
            path.remove(path.size() -1);
            used[i] = 0;
        }
    }
}

本题小结:(1)used[i] == 1限定了取过的不能再取

                (2)i > 0 && nums[i] == nums[i-1]意味着在同层遇到了前后相同的情况

                (3)used[i-1] == 1意味着在之前已经取过了,本次不用再取。

 13. 剑指 Offer 38. 字符串的排列

输入一个字符串,打印出该字符串中字符的所有排列。
你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
输入:s = "abc"
输出:["abc","acb","bac","bca","cab","cba"]

输入:
"aab"
输出:
["ab","ba"]
预期结果:
["aba","aab","baa"]

元素是可以重复的,不必进行过滤。

过滤版本

class Solution {
    ArrayList<String> list = new ArrayList<>();
    public String[] permutation(String s) {
        HashSet<Character> set = new HashSet<>();
        for(int i = 0; i < s.length(); i++){
            set.add(s.charAt(i));
        }
        String str = "";
        for(char c : set) str += c;
        dfs(str,0,"");
        String[] strarr = new String[list.size()];
        for(int i = 0; i < list.size(); i++){
            strarr[i] = list.get(i);
        }
        return strarr;
    }
    public void dfs(String str, int index, String temp){
        if(temp.length() == str.length()){
            list.add(temp);
            return;
        }
        for(int i = 0; i < str.length(); i++){
            String v1 = str.substring(i,i+1);
            if(temp.contains(v1)) continue;
            temp += v1;
            dfs(str,i+1,temp);
            temp = temp.substring(0,temp.length()-1);
        }
    }
}

非过滤版本

class Solution {
    ArrayList<String> list = new ArrayList<>();
    int[] used;
    public String[] permutation(String s) {
        used = new int[s.length()];
        char[] c = s.toCharArray();
        Arrays.sort(c);
        String str = "";
        for(char tmp:c) str += tmp;
        dfs(str,"");
        String[] strarr = new String[list.size()];
        for(int i = 0; i < list.size(); i++){
            strarr[i] = list.get(i);
        }
        return strarr;
    }
    public void dfs(String str, String temp){
        if(temp.length() == str.length()){
            list.add(temp);
            return;
        }
        for(int i = 0; i < str.length(); i++){
            if(used[i] == 1 || (i > 0 && str.charAt(i) == str.charAt(i-1)) && used[i-1] == 1 ) continue;
            String v1 = str.substring(i,i+1);
            temp += v1;
            used[i] = 1;
            dfs(str,temp);
            temp = temp.substring(0,temp.length()-1);
            used[i] = 0;
        }
    }
}

本题小结:(1)全排列,且有重复元素,注意过滤条件,同12

                (2)由Arrays.toString的字符串会多出来,【和】,奇奇怪怪不要用,直接拼接

 

14. leetcode494 目标和

给你一个整数数组 nums 和一个整数 target 。

向数组中的每个整数前添加 '+' 或 '-' ,然后串联起所有整数,可以构造一个 表达式 :

例如,nums = [2, 1] ,可以在 2 之前添加 '+' ,在 1 之前添加 '-' ,然后串联起来得到表达式 "+2-1" 。
返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。
输入:nums = [1,1,1,1,1], target = 3
输出:5
解释:一共有 5 种方法让最终目标和为 3 。
-1 + 1 + 1 + 1 + 1 = 3
+1 - 1 + 1 + 1 + 1 = 3
+1 + 1 - 1 + 1 + 1 = 3
+1 + 1 + 1 - 1 + 1 = 3
+1 + 1 + 1 + 1 - 1 = 3

class Solution {
    int count = 0;
    public int findTargetSumWays(int[] nums, int target) {
        dfs(nums,0,0,target);
        return count;
    }
    public void dfs(int[] nums, int index, int path, int target){
        if(index == nums.length){
            if(path == target){
            count++; 
            }
            return;
        }
        //选择
        path += nums[index];
        dfs(nums,index+1,path,target);
        //回来,撤销,选则另一种方法
        path -= nums[index];
        path -= nums[index];
        dfs(nums,index+1,path,target);
    }
}

本题小结:(1)撤销时执行两次path -= nums[index]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值