常见算法问题之NextPermutation

本文详细解析了LeetCode第31题“下一个排列”的问题,并提供了一种有效的C++实现方案。该算法通过寻找特定位置进行元素交换并反转部分序列来获得下一个字典序排列。

题目来源于leetcode 31


1. 问题描述

依据字典序升序,找出序列的下一序列。例如(左边是输入,右边是输出):

1 2 3 --- 1 3 2
1 5 1 --- 5 1 1
3 2 1 --- 1 2 3

2. 算法描述
for (i = 0; i < size(array); i++)
    j = max{i | array[i] < array[i + 1]};

for (i = 0; i < size(array); i++)
    k = max{i | array[i] > array[j]};

swap(j, k);
reverse(array, j+1, array(end));


3. C++实现
#include <iostream>
#include <vector>

using namespace std;

class Solution {
public:
    void nextPermutation(vector<int>& nums) 
    {
        vector<int>::iterator i, j, k, reverse_start = nums.begin();
        bool is_found = 0; //若原序列恰好是降序,则reverse范围是整个序列

        for (i = nums.begin(), j = i; i != nums.end() - 1; i++)
        {
            if (*i < *(i + 1))
            {
                j = i;
                is_found = 1; 
            }
        }

        if (is_found != 0)
        {
            for (i = nums.begin(); i != nums.end(); i++)
            {
                if (*j < *i)
                    k = i;
            }
            reverse_start = j + 1;
            swap(j, k);
        }

        reverse(nums, reverse_start);
    }

private:
    void reverse(vector<int>& nums, vector<int>::iterator start)
    {
        vector<int>::iterator i = start;
        vector<int>::iterator j = nums.end() - 1;

        while (i < j)
        {
            swap(i, j);
            i++;
            j--;
        }
    }

    void swap(vector<int>::iterator i, vector<int>::iterator j)
    {
        int temp = *i;
        *i = *j;
        *j = temp;
    }
};

int main()
{
    const int n = 3;
    int b[n] = {3, 2, 1};
    vector<int> a(b, b + n);

    Solution S;
    S.nextPermutation(a);

    vector<int>::iterator iter;
    for (iter = a.begin(); iter != a.end(); iter++)
    {
        cout << *iter << ' ';
    }
    cout << endl;

    return 0;
}

参考:
1. 字典序:http://www.cnblogs.com/pmars/p/3458289.html
2. LeetCode原题:https://leetcode.com/problems/next-permutation/
3. C++ vector使用:http://blog.youkuaiyun.com/liunian17/article/details/7435781

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值