全排列问题

          求一个数组或者string的全排列是很经典的问题。解决此类问题,首先在自己大脑思考,通常自己求一个数组的全排列会怎么求,比如arr[1, 2, 3],答案是:[1, 2, 3]、[1, 3, 2]、[2, 1, 3]、[2, 3, 1]、[3, 2, 1]、[3, 1, 2]。思路就是:从第一个字符开始和后面的字符进行交换,再从第二个字符开始和后面的进行交换,再第n-1和第n个交换。这样能够保证不会遗漏一些排列。

46Permutations---利用回溯来做全排列

题目描述:

Given a collection of distinct numbers, return all possible permutations.

For example,
[1,2,3] have the following permutations:

[
  [1,2,3],
  [1,3,2],
  [2,1,3],
  [2,3,1],
  [3,1,2],
  [3,2,1]
]


题目解析:

1.此题求全排列,并且数组中没有重复的数,那么其实比较简单。依次交换不会出现重复解。
2. 利用递归回溯来做,交换完一个位置到最后求出解返回后。复原,再依次交换当前位置和下一个交换位置,保证遍历到所有解。

代码如下:

class Solution {
public:
    // 使用递归回溯来解决此问题:此题没有重复字符,可以这样写
    void permute(vector<int>& nums, int size, int start, vector<vector<int>> &out)
    {
        if(start == size-1)
        {
            out.push_back(nums);
            return;
        }
        for(int i=start; i<size; ++i)
        {
            // 交换
            int temp = nums[i];
            nums[i] = nums[start];
            nums[start] = temp;
            // 递归求解
            permute(nums, size, start+1, out);
            // 回溯复原
             temp = nums[i];
            nums[i] = nums[start];
            nums[start] = temp;   
        }
        return;
    }
    vector<vector<int>> permute(vector<int>& nums) 
    {
        vector<vector<int>> out;
        if(nums.empty())
            return out;
        permute(nums, nums.size(), 0, out);
        
        return out;
    }
};

47Permutations II---递归回溯

问题描述:

Given a collection of numbers that might contain duplicates, return all possible unique permutations.

For example,
[1,1,2] have the following unique permutations:

[
  [1,1,2],
  [1,2,1],
  [2,1,1]
]

问题解析:

1. 此题也是求全排列。较上一题的不同点是此题的arr中可能出现重复数字。
2.因此此题需要在递归回溯时候做处理,首先,两个位置的数字相同就没有必要交换了,因为交换完结果是一样的,节省递归次数,直接跳过当前被交换位置就行。
3. 其次,在结果集中做个处理,使用set来存储结果集,避免出现重复结果。


代码如下:

class Solution {
public:
    // 使用递归回溯来解决此问题
    void permute(vector<int>& nums, int size, int start, set<vector<int>> &out)
    {
        if(start == size-1)
        {
            out.insert(nums);
            return;
        }
        for(int i=start; i<size; ++i)
        {
            if(i!=start && nums[i] == nums[start])
                continue;
            int temp = nums[i];
            nums[i] = nums[start];
            nums[start] = temp;
            permute(nums, size, start+1, out);
             temp = nums[i];
            nums[i] = nums[start];
            nums[start] = temp;   
        }
        return;
    }

    vector<vector<int>> permuteUnique(vector<int>& nums) 
    {
        set<vector<int>> out;
        permute(nums, nums.size(), 0, out);
        
        return vector<vector<int>>(out.begin(), out.end());
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值