Leetcode——46全排列、47全排列2(回溯法)

46.给定一个没有重复数字的序列,返回其所有可能的全排列。

说明:解集不能包含重复的子集。

示例:

输入: [1,2,3]
输出:
[
  [1,2,3],
  [1,3,2],
  [2,1,3],
  [2,3,1],
  [3,1,2],
  [3,2,1]
]

【思路】
拿到这个题第一反应就是回溯法,要搞清回溯法具体的过程,我们可以通过画一个树形图来理解。需要分析清楚题目的是,对于该排列问题,只要我们按照顺序选取数组,最主要的是上一层出现的数字,下一层不能再出现。
在这里插入图片描述
注意:

1、在每一层,我们都有若干条分支供我们选择。由于是排序问题,之前使用过的数字,在下一层中不能再选取,那么从当前层走到下一层的时候,我们就要问一问自己,哪些数字已经使用过。在编码实现中,可以使用一个布尔型数组 used,用于记录之前哪些数字使用过。

2、在程序执行到上面这棵树的叶子结点的时候,此时递归到底,方法要返回了,对于这个最后一层选取的数,要做两件事情:(1)释放对它的占用;(2)将它从当前选取放进的排列中弹出。当前,在每一层的方法执行完毕,要返回的时候,都需要这么做。这两点可以简单概括为“状态重置”。

参考链接:https://leetcode-cn.com/problems/two-sum/solution/hui-su-suan-fa-python-dai-ma-java-dai-ma-by-liweiw/
【实现代码】

class Solution {
    public List<List<Integer>> permute(int[] nums) {
        int len=nums.length;
        List<List<Integer>> res=new ArrayList<>();
        boolean[] used=new boolean[len];
        if(len==0) return res;
        generatePermution(nums,used,0,len,new Stack<>(),res);
        return res;
    }
    
    private void generatePermution(int[] nums,boolean[] visited,int curSize,int len,Stack<Integer> path,List<List<Integer>> res){
        if(curSize==len){
            //此时path已经保存了nums中所有数字已经成为一个排列
            res.add(new ArrayList<>(path));
            return;
        }
        for(int i=0;i<len;i++){
            if(!visited[i]){
                path.push(nums[i]);
                visited[i]=true;
                generatePermution(nums,visited,curSize+1,len,path,res);
                path.pop();
                visited[i]=false;
            }
        }
    }
    
}

47.给定一个可包含重复数字的序列,返回所有不重复的全排列。

示例:

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

【思路】
感觉和未重复的程序大体差别没有很大,现在就是需要判断重复的数字如何进行处理。首先对数组进行排序,排序之后。在进入一个新的分支之前,看一看这个数是不是和之前的数一样,如果这个数和之前的数一样,并且之前的数还未使用过,那接下来如果走这个分支,就会使用到之前那个和当前一样的数,就会发生重复,此时分支和之前的分支一模一样。(因为前一个数之前已经走过了,所以未使用的话接下来要走的分支就和之前的一样。)
参考链接:https://leetcode-cn.com/problems/two-sum/solution/hui-su-suan-fa-python-dai-ma-java-dai-ma-by-liwe-2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
【实现代码】

package array;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;

public class Permution {

	
	
	
	public static void main(String[] args){
		int[] nums=new int[]{1,1,2};
        List<List<Integer>> res=new ArrayList<>();
        res=permuteUnique(nums);
        for(int i=0;i<res.size();i++){
        	System.out.println(res.get(i));
        }
	}

	private static List<List<Integer>> permuteUnique(int[] nums) {
		 int len=nums.length;
	        List<List<Integer>> res=new ArrayList<>();
	        boolean[] used=new boolean[len];
	        if(len==0) return res;
	        Arrays.sort(nums);
	        findPermution(nums,used,0,len,new Stack<>(),res);
	        return res;
	}

	private static void findPermution(int[] nums, boolean[] used, int depth, int len, Stack<Integer> stack,
			List<List<Integer>> res) {
		// TODO Auto-generated method stub
		if(depth==len){
			res.add(new ArrayList<Integer>(stack));
			return;
		}
		for(int i=0;i<len;i++){
			if(!used[i]){
				if(i>0&&nums[i]==nums[i-1]&&!used[i-1]){
					continue;
				}
				used[i]=true;
				stack.add(nums[i]);
				findPermution(nums, used, depth+1, len, stack, res);
				stack.pop();
				used[i]=false;
			}
		}
		
	}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值