Share a wonderful Likun question --- the next arrangement

31. Next permutation - LeetCode

 What we have to do is to exchange a smaller number on the left with a larger number on the right, and make  "the smaller number as close to the right as possible, and the larger number as small as possible"

And after the exchange, it is very important to let the numbers on i to n-1 increase from small to large. Only in this way can we ensure the smallest increase

 The farther to the right , the smaller the changed position, and the change in tens is definitely smaller than the change caused by hundreds and thousands

When changing, I definitely want to be able to become bigger again, and there are fewer people who want to become bigger as much as possible.

With these foundations, we can write this question:

Let's start from the back and look for the first case where nums[ i-1 ] < nums[ i ], then in the interval from i to n-1, it must be in descending order, because none of the previous conditions are met Well, so we can    find the first element j from the back interval i to n-1 from the back to the front, satisfying nums[ i-1 ] < nums[ j ], and then exchange the values ​​of these two numbers

After the exchange, this interval is still in descending order. We only need to flip the reverse to get the ascending order. This complexity is also O(n). If we use sort, the complexity is O(nlogn). The outer traversal is O(n), and the inner one is reversed. These two are juxtaposed, which is equivalent to at most two traversals, which is 2 * O(n), which means that the time complexity can reach O(n). It's really wonderful!

//两次扫描
    void nextPermutation(vector<int>& nums) {
        int n=nums.size();
        for(int i=n-1;i>0;--i){
            if(nums[i-1]<nums[i]){//找到第一个i-1 < i的位置
                //i到n-1上肯定是降序
                //从i到n-1上从后向前找到第一个满足nums[i-1]<nums[j]的数,这个数就是这里面最小的,而且大于nums[i-1]的数,交换以后这个区间还是降序的,reverse之后就能满足升序
                for(int j=n-1;j>=i;--j){
                    if(nums[i-1]<nums[j]){
                        int tmp=nums[i-1];//交换
                        nums[i-1]=nums[j];
                        nums[j]=tmp;
                        //翻转    i 到 n-1 这个区间,就能让这个区间升序
                        //sort(nums.begin()+i,nums.end())
                        reverse(nums.begin()+i,nums.end());
                        return;
                    }
                }
            }
        }
        //如果没有返回则说明需要从到到尾翻转
        reverse(nums.begin(),nums.end());
    }

When we use sort:

And we used reverse words:

 

 As you can see, reverse is really seconds

Guess you like

Origin blog.csdn.net/flyingcloud6/article/details/129856511