LeetCode 31 Next Permutation / 60 Permutation Sequence [Permutation]

LeetCode 31 Next Permutation / 60 Permutation Sequence [Permutation] <c++>

LeetCode 31 Next Permutation

给出一个序列,求其下一个排列
STL中有std::next_permutation这个方法可以直接拿来用
也可以写一个实现程序:

  1. 从右往左遍历序列,找到第一个nums[i-1]<num[i]的位置,记p = i-1
  2. 如果第一步没有找到,说明整个序列满足单调递减,也就是最大的排列,那么倒置序列,return即可。
  3. 再次从右往左遍历序列,找到第一个nums[i]>nums[p]的位置,std::swap(nums[i],nums[p])
  4. 此时从p位置开始到序列最右端一定满足单调递减,倒置这一部分,使其字典序最小,所得序列即为下一个排列。
class Solution {
public:
    void nextPermutation(std::vector<int>& nums) {
        int p = -1;
        for(int i = nums.size()-1; i>=0; i--) 
            if(i-1>=0 && nums[i]>nums[i-1]){
                p = i-1;
                break;
            }
        if(p==-1){
            std::reverse(nums.begin(),nums.end());
            return;
        }
        for(int i = nums.size()-1; i>=0; i--) 
            if(nums[i]>nums[p]){
                std::swap(nums[i],nums[p]);
                break;
            }
        std::reverse(nums.begin()+p+1,nums.end());
    }
};

LeetCode 60 Permutation Sequence

求长度为n的序列(1~n)全排列的第k大排列
如果不停调用std::next_permutation肯定会超时。
利用康托展开,所有排列按照字典序排序后,按顺序编号,称为康托编码
那么根据序列长度和编号求解序列,实际就是解码过程。
编码解码详见 https://blog.csdn.net/synapse7/article/details/16901489

class Solution {
public:
    std::string getPermutation(int n, int k) {
        std::string ans;
        std::string seq0(n,'0');
        for(int i = 0; i<n; i++){ // seq0: 1~n minimal permutation
            seq0[i] += i+1;
        }
        int base = 1;
        for(int i = 1; i<n; i++) base *= i;
        k--;
        for(int i = 0; i<n-1; k %= base, base/=n-i-1, i++){
            auto pos = seq0.begin()+k/base;
            ans.push_back(*pos);
            seq0.erase(pos);
        }
        ans.push_back(seq0[0]);
        return ans;
    }
};

猜你喜欢

转载自www.cnblogs.com/NeilThang/p/10343101.html