• 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));
    }

    一行代码。

  • 相关阅读:
    fastText文本分类算法
    迁移学习综述
    Doc2vec实现原理
    skip-thought vector 实现Sentence2vector
    IRT模型的参数估计方法(EM算法和MCMC算法)
    解决不能再jupyter notebook中使用tensorflow
    TensorFlow——循环神经网络基本结构
    React项目使用React-Router
    初始化一个React项目(TypeScript环境)
    TypeScript TSLint(TypeScript代码检查工具)
  • 原文地址:https://www.cnblogs.com/hozhangel/p/7841421.html
Copyright © 2020-2023  润新知