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

一行代码。

 

posted @ 2017-11-16 09:46  hozhangel  阅读(147)  评论(0编辑  收藏  举报