拿下回溯算法

写在前面

参考:https://leetcode-cn.com/problems/permutations/solution/hui-su-suan-fa-python-dai-ma-java-dai-ma-by-liweiw/

例题

leetcode46 全排列

答题链接:https://leetcode-cn.com/problems/permutations/
题目描述:给定一个没有重复数字的序列,返回其所有可能的全排列。
python实现

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        def dfs(nums: list, flag: list, tempList: list, ret):
        	'''
        	params nums: 给定输入数字序列
        	params flag: 该次dfs时还未使用的数字
        	params tempList: 该次dfs时输入数组
        	params ret: 最终输出全排列结果
        	'''
            if len(tempList) == len(nums):   #遍历到底时, 将该列表加入结果
                ret.append(tempList[:])    # 可以试试直接将tempList放入ret, 查看结果
                return
            for i in range(len(nums)):
                if flag[i]:    # 如果该数字还未被使用
                    tempList.append(nums[i])    # 将该数字加入临时数组
                    flag[i] = False   # 该数字已经使用
                    dfs(nums, flag, tempList, ret)  # 递归调用

                    flag[i] = True  # 回溯
                    tempList.pop()  # 回溯
        
        flag = [True] * len(nums)
        ret = []
        dfs(nums, flag, [], ret)
        return ret

Java实现

class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> ret = new LinkedList<>();
        List<Integer> tempList = new LinkedList<>();
        boolean[] flag = new boolean[nums.length];
        Arrays.fill(flag, true);
        dfs(nums, flag, tempList, ret);
        return ret;
    }
    
    public void dfs(int[] nums, boolean[] flag, List<Integer> tempList, List<List<Integer>> ret) {
        if (nums.length == tempList.size()) {
            ret.add(new LinkedList<>(tempList));
        }

        for (int i = 0; i < nums.length; i++) {
            if (flag[i]) {
                tempList.add(nums[i]);
                flag[i] = false;

                dfs(nums, flag, tempList, ret);

                flag[i] = true;
                tempList.remove(tempList.size() - 1);
            }
        }
    }
}

leetcode47 全排列2

答题链接:https://leetcode-cn.com/problems/permutations-ii/
题目描述:给定一个可包含重复数字的序列 nums ,按任意顺序返回所有不重复的全排列。
相比于上一题,该题增加了包含重复数字的条件,那么结果中会增加重复的序列。因此可以在结果中将相同的排列删除;或者在每次dfs枚举位置时进行剪枝处理,判断该数字是否被枚举过,如果枚举过则不必再进行dfs。
Java实现

class Solution {
    public List<List<Integer>> permuteUnique(int[] nums) {
        List<List<Integer>> ret = new LinkedList<>();
        List<Integer> tempList = new LinkedList<>();

        boolean[] flag = new boolean[nums.length];
        Arrays.fill(flag, true);

        dfs(nums, flag, tempList, ret);
        
        return ret;
    }

    public void dfs(int[] nums, boolean[] flag, List<Integer> tempList, List<List<Integer>> ret) {
        if (nums.length == tempList.size()) {
            ret.add(new LinkedList<>(tempList));
            return;
        }
        Set<Integer> numSet = new HashSet<>();  //使用集来存储该位置枚举过的数字
        for (int i = 0; i < nums.length; i++) {
            if (flag[i] && !numSet.contains(nums[i])) {  // 如果该位置没被枚举过且该数字没被枚举过
                flag[i] = false;
                tempList.add(nums[i]);
                numSet.add(nums[i]);

                dfs(nums, flag, tempList, ret);

                flag[i] = true;
                tempList.remove(tempList.size() - 1);
            }
        }
    }
}

leetcode39 组合总和

答题链接:https://leetcode-cn.com/problems/combination-sum/
题目描述:给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。candidates 中的数字可以无限制重复被选取。
python实现

class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:

        def dfs(candidates: list, tempList: list, numSum: int, ret, index: int):
            if numSum == target:
                ret.append(tempList[:])
                return

            for i in range(index, len(candidates)):   
                if numSum + candidates[i] <= target:
                    tempList.append(candidates[i])
                    numSum += candidates[i]

                    dfs(candidates, tempList, numSum, ret, i)

                    numSum -= candidates[i]
                    tempList.pop()
                else:
                    break
        
        candidates.sort()  # 先排序方便剪枝
        ret = []
        dfs(candidates, [], 0, ret, 0)
        return ret

Java实现

class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> ret = new LinkedList<>();
        List<Integer> tempList = new LinkedList<>();
        Arrays.sort(candidates);
        dfs(candidates, tempList, 0, ret, 0, target);

        return ret;
    }


    public void dfs(int[] candidates, List<Integer> tempList, int tempSum, List<List<Integer>> ret, int index, int target) {
        if (tempSum == target) {
                ret.add(new LinkedList<>(tempList));
                return;
                }
        for (int i = index; i < candidates.length; i++) {
            tempSum += candidates[i];
            if (tempSum <= target) {
                tempList.add(candidates[i]);

                dfs(candidates, tempList, tempSum, ret, i, target);

                tempList.remove(tempList.size() - 1);
                tempSum -= candidates[i];
            } else {
                break;
            }
        }
    }
}

leetcode40 组合总和2

答题链接:https://leetcode-cn.com/problems/combination-sum-ii/
题目描述:给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。candidates 中的每个数字在每个组合中只能使用一次。

class Solution:
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:

        def dfs(candidates, tempList, tempSum, index, ret):
            if tempSum == target:
                ret.append(tempList[:])
                return 
            
            numSet = set()
            for i in range(index, len(candidates)):
                if tempSum + candidates[i] <= target and candidates[i] not in numSet:
                    tempSum += candidates[i]
                    tempList.append(candidates[i])
                    numSet.add(candidates[i])

                    dfs(candidates, tempList, tempSum, i+1, ret)

                    tempSum -= candidates[i]
                    tempList.pop()
                elif tempSum + candidates[i] > target:
                    break
                else:
                    continue
        
        candidates.sort()
        ret = []
        dfs(candidates, [], 0, 0, ret)
        return ret
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值