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

    一行代码。

  • 相关阅读:
    Redis之scan
    MySQL中查看Blob类型的字段内容
    Redis之布隆过滤器BloomFilter
    Redis中的位图结构
    Redis之GeoHash根据经纬度距离排序
    .net 手写实现一个简单实体数据验证
    GogsWindows Server下配合Jenkins自动化发布
    C#的winform控件命名规范[转载]
    GogsWindows Server下搭建Git服务器
    Jenkins构建基于.NET Framework的web程序
  • 原文地址:https://www.cnblogs.com/hozhangel/p/7841421.html
Copyright © 2020-2023  润新知