【算法题】全排列,字典序

参考

全排列:


/*
 * 递归输出序列的全排列
 */
void FullArray(char* array, size_t array_size, unsigned int index)
{
    if(index >= array_size)
    {
        for(unsigned int i = 0; i < array_size; ++i)
        {
            cout << array[i] << ' ';
        }

        cout << '\n';

        return;
    }

    for(unsigned int i = index; i < array_size; ++i)
    {
        swap(array, i, index);

        FullArray1(array, array_size, index + 1);

        swap(array, i, index);
    }
}

字典序:


使用字典序输出全排列的思路是,首先输出字典序最小的排列,然后输出字典序次小的排列,……,最后输出字典序最大的排列。这里就涉及到一个问题,对于一个已知排列,如何求出其字典序中的下一个排列。这里给出算法。

  • 对于排列a[1…n],找到所有满足a[k]<a[k+1](0<k<n-1)的k的最大值,如果这样的k不存在,则说明当前排列已经是a的所有排列中字典序最大者,所有排列输出完毕。

  • 在a[k+1…n]中,寻找满足这样条件的元素l,使得在所有a[l]>a[k]的元素中,a[l]取得最小值。也就是说a[l]>a[k],但是小于所有其他大于a[k]的元素,如果有相同的a[l],取最后的一个
    交换a[l]与a[k].

  • 对于a[k+1…n],反转该区间内元素的顺序。也就是说a[k+1]与a[n]交换,a[k+2]与a[n-1]交换,……,这样就得到了a[1…n]在字典序中的下一个排列。

这里我们以排列a[1…8]=13876542为例,来解释一下上述算法。首先我们发现,1(38)76542,括号位置是第一处满足a[k]<a[k+1]的位置,此时k=2。所以我们在a[3…8]的区间内寻找比a[2]=3大的最小元素,找到a[7]=4满足条件,交换a[2]和a[7]得到新排列14876532,对于此排列的3~8区间,反转该区间的元素,将a[3]-a[8],a[4]-a[7],a[5]-a[6]分别交换,就得到了13876542字典序的下一个元素14235678。下面是该算法的实现代码


#include <iostream>
#include <vector>
#include <limits.h>
#include <algorithm>

using namespace std;


vector<int> NextDic(vector<int>& vec)
{
    vector<int> next(vec);
    int last_(0);

    for (int i = next.size()-1; i >= 1;--i)
    {
        if (vec[i] > vec[i - 1])
        {
            last_ = i-1;
            break;
        }
    }

    if (last_ == 0&&vec[last_]>=vec[last_+1])
    {
        next.clear();
        return next;
    }
    int first_big_index(last_+1);
    for (auto i = first_big_index; i < vec.size();++i)
    {
        if (vec[i]>vec[last_]&& vec[i]<=vec[first_big_index] )
        {
            first_big_index = i;
        }
    }
    swap(next[last_], next[first_big_index]);
    int left = last_ + 1, right = next.size() - 1;
    while (left <right)
    {
        swap(next[left], next[right]);
        left++;
        right--;
    }

    return next;
}
void func(vector<int> & vec)
{
    sort(vec.begin(), vec.end());
    vector<int> next = vec;
    while (!next.empty())
    {
        for (auto i = 0; i < next.size();++i)
        {
            cout << next[i] << " ";
        }
        cout << endl;
        next = NextDic(next);
    }
}

int main()
{
    vector<int> vec{ 2, 1, 2 };
    func(vec);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值