【C++】【LeetCode】31. Next Permutation && 46. Permutations

31. Next Permutation

题目

Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.
If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).
The replacement must be in-place, do not allocate extra memory.
Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

一开始题目没有看懂,所以在网上搜了解释。根据百度知道:zhidao.baidu.com/question/530315721.html,C++有一个函数叫做boolean next_permutation(a.begin(),a.end()) ,

该函数是以输入字符串中的字符所构建的按字典顺序全排列中,判断当前字符串之后是否还有下一个字符串
如果next_permutation的执行次数少于全排列的个数,返回true
例如 a=”abc” 全排列有 “abc” “acb” “bac” “bca” “cab” “cba”
执行一次next_permutation 返回true a变成 “acb”
再执行一次next_permutation 返回true a变成 “bac”

当执行到a=”cba” 时 由于这已经是全排列的最后一个字符串,所以 再次执行next_permutation 则返回false。

思路

利用递归,每次如果数组大小大于1,则继续递归查找子数组是否可以进行排列,如果不能进行排列。则将本身与子数组中比自己大且与自己最接近的数组进行交换并且将子数组排序(由于子数组的顺序一定是从大到小排列,所以可以从尾部进行查找),如果子数组中没有数比本身大,则包括本身的数组也不能进行排列。

代码

class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        //如果数组大小小于等于1,则不需要排序
        if (nums.size()<2) {
            return;
        }
        //如果整个数组无法排序,则按照题目要求从小到大排列
        if (helper(nums, 0) == -1) { 
            sort(nums.begin(), nums.end());
        }
    }

    int helper(vector<int>& nums, int start) {
        //如果还有子数组,先进行子数组的递归。
        if (start == nums.size()-1) {
            return -1;
        } 
        if (helper(nums, start + 1) == -1) {
            for (int i = nums.size() - 1; i >= start + 1; i--) {
                if (nums[start] < nums[i]) {
                    swap(nums[start], nums[i]);
                    sort(nums.begin()+start+1, nums.end());
                    return 1;
                }
            }
            return -1;
        }
        return 1;
    }
};

46. Permutations

题目

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]
]

Solution 1

思路

本来想直接用31题的代码得到下一个排列,但是效率好像偏低。C++有一个库函数next_permutation(copy.begin(), copy.end()),可以直接用,所以代码很简单啦!先给num排序,就不用考虑如果排序到结尾的问题。

代码

class Solution {
public:
    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>> result;
        vector<int> copy = nums;
        sort(copy.begin(), copy.end());
        result.push_back(copy);
        while (next_permutation(copy.begin(), copy.end())) {
            result.push_back(copy);
        }

        return result;
    }
};

Solution 2 [参照LeetCode上的solution]

思路

链接:A general approach to backtracking questions in Java (Subsets, Permutations, Combination Sum, Palindrome Partioning)
利用递归思想,每次依照顺序选择数组nums中的一个填入相应的位置,然后继续寻找每一个不相同的元素填入下一个位置,以此类推,得出可能的排列。

代码

class Solution {
public:
    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>> result;
        vector<int> temp;
        backtrack(result, temp, nums);
        return result;
    }

    void backtrack(vector<vector<int>>& result, vector<int>& temp, vector<int>& nums) {
        if (temp.size() == nums.size()) {
            result.push_back(temp);
        } else {
            for (int i = 0; i < nums.size(); i++) {
                if (find(temp.begin(), temp.end(), nums[i]) != temp.end()) {
                    continue;
                }
                temp.push_back(nums[i]);
                backtrack(result, temp, nums);
                temp.erase(temp.end()-1);
            }
        }

    }
};

Solution 3 [参照LeetCode上的solution]

思路

链接:My elegant recursive C++ solution with inline explanation
利用递归思想,每次交换nums数组begin位的数和遍历到的数,然后对begin位以后的数组进行处理,然后交换回来,保持nums数组顺序不变。这种思路是我认为最好理解也最简单的思路。

代码

class Solution {
public:
    vector<vector<int> > permute(vector<int> &num) {
        vector<vector<int> > result;

        permuteRecursive(num, 0, result);
        return result;
    }

    // permute num[begin..end]
    // invariant: num[0..begin-1] have been fixed/permuted
    void permuteRecursive(vector<int> &num, int begin, vector<vector<int> > &result)    {
        if (begin >= num.size()) {
            // one permutation instance
            result.push_back(num);
            return;
        }

        for (int i = begin; i < num.size(); i++) {
            swap(num[begin], num[i]);
            permuteRecursive(num, begin + 1, result);
            // reset
            swap(num[begin], num[i]);
        }
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值