zoukankan      html  css  js  c++  java
  • 代码题(45)— 下一个排列、第k个排列

    1、31. 下一个排列

    实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。

    如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。

    必须原地修改,只允许使用额外常数空间。

    以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
    1,2,3 → 1,3,2
    3,2,1 → 1,2,3
    1,1,5 → 1,5,1

    这道题让我们求下一个排列顺序,有题目中给的例子可以看出来,如果给定数组是降序,则说明是全排列的最后一种情况,则下一个排列就是最初始情况,可以参见之前的博客 Permutations 全排列。我们再来看下面一个例子,有如下的一个数组

    1  2  7  4  3  1

    下一个排列为:

    1  3  1  2  4  7

    那么是如何得到的呢,我们通过观察原数组可以发现,如果从末尾往前看,数字逐渐变大,到了2时才减小的,然后我们再从后往前找第一个比2大的数字,是3,那么我们交换2和3,再把此时3后面的所有数字转置一下即可,步骤如下:

    1  2  7  4  3  1

    1  2  7  4  3  1

    1  3  7  4  2  1

    1  3  1  2  4  7

    class Solution {
    public:
        void nextPermutation(vector<int>& nums) {
            if(nums.empty())
                return ;
            int n=nums.size();
            int i=n-2,j=n-1;
            while(i>=0 && nums[i]>=nums[i+1])// 从后向前,找到第一个违反升序的数的位置
                i--;
            if(i>=0)
            {
                while(j>=0 && nums[j]<=nums[i]) // 从后向前,找到第一个大于该数的值的位置
                    j--;
                swap(nums[i],nums[j]); // 交换二者的值
            }
            reverse(nums.begin() + i + 1, nums.end()); //将后面的数重新排序
        }
    };

    2、60. 第k个排列

    给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。

    按大小顺序列出所有排列情况,并一一标记,当 = 3 时, 所有排列如下:

    1. "123"
    2. "132"
    3. "213"
    4. "231"
    5. "312"
    6. "321"

    给定 n 和 k,返回第 k 个排列。

    说明:

    • 给定 n 的范围是 [1, 9]。
    • 给定 的范围是[1,  n!]。

    示例 1:

    输入: n = 3, k = 3
    输出: "213"
    

    示例 2:

    输入: n = 4, k = 9
    输出: "2314"

      我们可以发现,每一位上1,2,3,4分别都出现了6次,当第一位上的数字确定了,后面三位上每个数字都出现了2次,当第二位也确定了,后面的数字都只出现了1次,当第三位确定了,那么第四位上的数字也只能出现一次,那么下面我们来看k = 17这种情况的每位数字如何确定,由于k = 17是转化为数组下标为16。

    class Solution {
    public:
        string getPermutation(int n, int k) {
            string res;
            string nums = "123456789";
            vector<int> f(n, 1);
            for (int i = 1; i < n; ++i)
                f[i] = f[i - 1] * i;
            k--;//因为下标从0开始。
            
            for (int i = n - 1; i >= 0; --i)
            {
                int temp = k/f[i];
                k = k%f[i];
                res.push_back(nums[temp]);
                nums.erase(temp, 1);
            }
            return res;
        }
    };
  • 相关阅读:
    算法题汇集
    C# WinForm MDI左右分栏 多文档
    DDoS和CC攻击的区别
    搭建java程序写的博客Jpress
    U盘图标DIY方法
    磁盘空间不够用?教你一键清理电脑重复文件Duplicate File Finder
    给WordPress文章页URL赋予.html后缀
    使用七牛云和PicGo搭建图床
    wordpress好用的Markdown插件WP Editor.MD
    虚拟主机、VPS、云服务器三者的区别
  • 原文地址:https://www.cnblogs.com/eilearn/p/9482141.html
Copyright © 2011-2022 走看看