zoukankan      html  css  js  c++  java
  • 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

    题目开始不理解,上网搜了才知道,意思是:比如1 2 3 按顺序全排列

    1 2 3 ->1 3 2-> 2 1 3-> 2 3 1-> 3 1 2-> 3 2 1
    
    给一个排列组合,找到它的下一个排列,比如给1 3 2,输出它的下一个排列:2 1 3
    
                        给3 2 1,没有下一个,就重新回到第一个排列:1 2 3
    

      

    怎么来做?

    在网上看到一个例子:http://m.blog.csdn.net/nomasp/article/details/49913627

    6 5 4 8 7 5 1
    首先肯定从后面开始看,1和5调换了没有用。
    
    7、5和1调换了也没有效果,因此而发现了8、7、5、1是递减的。
    
    如果想要找到下一个排列,找到递增的位置是关键。
    
    因为在这里才可以使其增长得更大。
    
    于是找到了4,显而易见4过了是5而不是8或者7更不是1。
    
    因此就需要找出比4大但在这些大数里面最小的值,并将其两者调换。
    
    那么整个排列就成了:6 5 5 8 7 4 1
    
    最后一步将后面的8 7 4 1做一个反转。
    

      

    据说维基百科可以搜到解决算法,早在很久以前有人发现了解决这种问题的最佳方法:

    法一:

    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 

    1、找到最大的下标k,使得nums[k] < nums[k + 1]。如果没有知道这样一个下标,说明这个排列是完全递减序列,那么只要把整个序列反转即可。|

      例如:输入[3, 2, 1],是完全递减的,那么它的下一个排列就是  [1, 2, 3];                                                                                                       |

    2、从后往前找,找到k之后满足nums[k] < nums[l]的最大下标i。即:nums[k] < nums[l] && k< i;                                                                           |

    3、交换nums[k] = nums[l]的值;此处可以使用swap函数:swap(nums[k], nums[l]);                                                                                              |

    4、把数组下标从k+1到最后一个元素的序列反转。可以使用reverse函数:reverse(nums.begin() + k + 1, nums.end())                                          |

    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    class Solution {
    public:
    
    void nextPermutation(vector<int>& nums) {
            int k = -1;
            for (int i = nums.size() - 2; i >= 0; i--) {  //1、找到最大的下标k,使得nums[k] < nums[k + 1]
                if (nums[i] < nums[i + 1]) {
                    k = i;
                    break;
                }
            } 
            if (k == -1) {                               //如果没有知道这样一个下标,把整个序列反转即可
                reverse(nums.begin(), nums.end());
                return;
            }
            int l = -1;
            for (int i = nums.size() - 1; i > k; i--) {  //从后往前找,找到k之后满足nums[k] < nums[l]的最大的下标i。
                if (nums[i] > nums[k]) {
                    l = i;
                    break;
                } 
            } 
            swap(nums[k], nums[l]);   //交换nums[k] = nums[l]的值;
            reverse(nums.begin() + k + 1, nums.end());   //把数组下标从k+1到最后一个元素的序列反转。
        }
    }; 

    法二:

    最后可能都想不到,这里有个排列组合的函数可以解决这道题的问题.....

    void nextPermutation(vector<int>& nums) {
        next_permutation(begin(nums), end(nums));
    }

    一行代码。

  • 相关阅读:
    JVM运行时数据区与JVM堆内存模型小结
    Java Management Extensions (JMX)
    ubuntu 中 搭建 C编程环境
    个人使用的电脑软件
    Navicat Premium 12 安装 与 激活
    利用 canvas 实现压缩图片
    barcode模块: plus.barcode.scan 进行扫描图片出现无法识别二维码,打印的错误信息是code:8,message:''
    win10 出现 No AMD graphics driver is installed or the AMD driver is not functioning properly .....
    H5项目 使用Cropper.js 实现图片 裁剪 操作 (APP端)
    Java 正则表达式获取两个字符中间的内容
  • 原文地址:https://www.cnblogs.com/hozhangel/p/7841421.html
Copyright © 2011-2022 走看看