一、下一个排列

首先,STL提供了两个用来计算排列组合关系的算法,分别是next_permutation和prev_permutation。

next_permutation(nums.begin(),nums.end());//下一个排列

prev_permutation(nums.begin(),nums.end())//上一个排列

当返回为1时,表示找到了下一全排列;返回0时,表示无下一全排列

1.1下一个排列算法过程

(1)从右到左,找到第一个违反递增趋势的分区数;例如下图的6。

(2)从右到左,找到第一个比分区数大的改变数;例如下图的7。

(3)交换分区数和改变数;例如下图的6和7交换。

(4)颠倒分区数索引的右边所有数字。例如下图的7之后的元素。

1.2 STL源码剖析中的算法过程

(1)首先从最尾端开始往前寻找两个相邻元素,令第一元素为*i,第二元素为*ii,且满足*i<*ii。

(2)找到这样一组相邻元素后,再从最尾端开始往前检验,找出第一个大于*i的元素,令为*j,将i,j元素对调(swap)。

(3)再将ii之后的所有元素颠倒(reverse)排序。

1.3 版本一实现细节(C指针实现)

template<calss BidrectionalIterator>
bool next_permutation(BidrectionalIterator first,BidrectionalIterator last)
{
if(first == lase) return false; /* 空区间 */
BidrectionalIterator i = first;
++i;
if(i == last) return false; /* 只有一个元素 */
    i = last;                    /* i指向尾端 */
--i;
for(;;)
{
BidrectionalIterator ii = i;
--i;
/* 以上锁定一组(两个)相邻元素 */
if(*i < *ii) /* 如果前一个元素小于后一个元素 */
{
BidrectionalIterator j = last; /* 令j指向尾端 */
while(!(*i < *--j)); /* 由尾端往前找,直到遇到比*i大的元素 */
iter_swap(i,j); /* 交换i,j */
reverse(ii,last); /* 将ii之后的元素全部逆序重排 */
return true;
}
if(i == first) /* 进行至最前面了 */
{
reverse(first,last); /* 全部逆序重排 */
return false;
}
}
}

1.4版本二实现细节(纯STL规范)

 template<typename BidiIt>
bool next_permutation(BidiIt first,BidiIt last)
{
const auto rfirst=reverse_iterator<BidiIt>(last);+++
const auto rlast=reverse_iterator<BidiIt>(first); auto pivot=next(rfirst); while( pivot!= rlast && *pivot >= *prev(pivot))
++pivot;//直到找出第一个违反递增趋势的分区数,此时,pivot指向分区数; if(pivot == rlast)
{
reverse(rfirst,rlast);//如果此序列为递减系列,则下一个排序为颠倒整个序列;
return false;
} auto change=find_if(rfirst,rlast,bindlst(less<int>(),*pivot));//从右到左,找到第一个大于分区数的数,并赋给change; swep(*change,*pivot);//交换分区数与改变数; reverse(rfirst,pivot);//将分区数之后的序列颠倒; return true;
}

1.5 前一个排列(prev_permutation)

与next_permutation类似,STL也提供一个版本:

 int prev_permutation(int *begin, int *end)
{
    int *i=begin, *j, *k;
    if (i==end || ++i==end) return ;   // 0 or 1 element, no prev permutation
    for (i=end-; i!=begin;) {
        j = i--;    // find last decreasing pair (i,j)
        if (!(*i > *j)) continue;
        // find last k which less than i,
        for (k=end; !(*i > *(--k)););
        iter_swap(i,k);
        // now the range [j,end) is in ascending order
        reverse(j,end);
        return ;
    }
    // current is in ascending order
    reverse(begin,end);
    return ;
}

二、全排列

1.1 利用next_permutation求全排列

对初始序列依次求下一个排列,直到没有下一个序列为止。

举个实例,假设有序列{0,1,2,3,4},下图便是套用上述演算法则,一步一步获得“下一个”排列组合。图中只框出那符合“一元素为*i,第二元素为*ii,且满足*i<*ii ”的相邻两元素,至于寻找适当的j、对调、逆转等操作并未显示出。

代码如下:

    vector<vector<int>> permute(vector<int>& nums) {
vector<int>temp;
vector<vector<int>>result;
sort(nums.begin(),nums.end());
do
{
temp.clear();
for(int i=;i<nums.size();i++)
temp.push_back(nums[i]);
result.push_back(temp);
}while(next_permutation(nums.begin(),nums.end()));//do while循环最适合,因为先要打印出初始序列
return result;
}

1.2 利用深度优先搜索(DFS)求解,以后待更新。

三、第K个排列

简单的,可以用暴力枚举法,调用k-1次next_permutation()(注意一定是k-1次)

代码如下:

     string getPermutation(int n, int k) {
string str(n,'');
for(int i=;i<n;i++)
str[i]+=i+;
for(int i=;i<k-;i++)
next_permutation(str.begin(),str.end());
return str;
}

排列算法汇总(下一个排列,全排列,第K个排列)的更多相关文章

  1. C++ Primer 学习笔记_41_STL实践与分析(15)--先来看看算法【下一个】

    STL实践与分析 --初窥算法[下] 一.写容器元素的算法 一些算法写入元素值.在使用这些算法写元素时一定要当心.必须.写入输入序列的元素 写入到输入序列的算法本质上是安全的--仅仅会写入与指定输入范 ...

  2. 代码题(45)— 下一个排列、第k个排列

    1.31. 下一个排列 实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列. 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列). 必须原地修改,只 ...

  3. [Swift]LeetCode31. 下一个排列 | Next Permutation

    Implement next permutation, which rearranges numbers into the lexicographically next greater permuta ...

  4. LeetCode:下一个排列【31】

    LeetCode:下一个排列[31] 题目描述 实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列. 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排 ...

  5. Java实现 LeetCode 31下一个排列

    31. 下一个排列 实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列. 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列). 必须原地修改,只允许 ...

  6. 【LeetCode每天一题】Next Permutation(下一个排列)

    Implement next permutation, which rearranges numbers into the lexicographically next greater permuta ...

  7. ACM_下一个排列

    The Next Permutation Time Limit: 2000/1000ms (Java/Others) Problem Description: For this problem, yo ...

  8. 2.1.12 Next Permutation 下一个字典序数组

    对当前排列从后向前扫描,找到一对为升序的相邻元素,记为i和j(i < j).如果不存在这样一对为升序的相邻元素,则所有排列均已找到,算法结束:否则,重新对当前排列从后向前扫描,找到第一个大于i的 ...

  9. 31,Leetcode下一个排列 - C++ 原地算法

    题目描述 实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列. 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列). 必须原地修改,只允许使用额外常 ...

随机推荐

  1. cucumber的疑问解答

    在cucumber的自动化测试框架下面,在一个steps文件中定义的@page对象,可以在其他的不同的steps文件中调用,在整个的场景生命周期中都是有效的 原因:cucumber开始执行时,一次性把 ...

  2. C 碎片十 关键字&库函数

    一.关键字 1, sizeof sizeof关键字用于计算所占空间大小的 格式:sizeof(类型名/变量名); 2, typedef typedef关键字用于重命名数据类型的,相当于给原来的数据类型 ...

  3. JSPt的Base标签

    <base href="${pageContext.request.contextPath}/"/> 注意:base标签得到的内容是: /projectName/ 这种 ...

  4. rem媒体查询

    @media only screen and (min-width: 1080px), only screen and (min-device-width:1080px) { html,body { ...

  5. redis---安全设置

    redis的安全性是通过设置口令来实现的. 首先打开redis的配置文件,我的是在/etc/redis/redis.conf,个人的路径可能会有不同,可以自行查找. 打开redis.conf文件以后, ...

  6. 【MATLAB】设定坐标的轴的范围

    set(gca,'XLim',[0 1.5]);%X轴的数据显示范围set(gca,'XTick',[0:0.1:1.5]);%设置要显示坐标刻度set(gca,'XTickLabel',[0:0.1 ...

  7. 自己实现的简单的grid

    12年在第一家公司的时候,有过很长一段时间在前端的使用研究上.一开始的时候使用ExtJs4.0 MVC 来开发前端,觉得里面的风转的组件非常好用,Panel.window.tree等等,简化了对于前端 ...

  8. windows10下git报错warning: LF will be replaced by CRLF in readme.txt. The file will have its original line endings in your working directory.

    window10下使用git时 报错如下: $ git add readme.txtwarning: LF will be replaced by CRLF in readme.txt.The fil ...

  9. Mvc重写JsonResult

    用了mvc有一段时间了,慢慢的熟悉起来了,也渐渐的发现了mvc的一些缺点,比如当我们返回 Json(new{})的时候没办法做到将首字母转换成小写.日期再序列化过后是时间戳需要到前台重新处理或者提在在 ...

  10. hihoCoder 挑战赛10 #1144 : 01串

    思路:这只是逻辑测试题吧,考虑周全就行了.考虑n=m的情况,n>m的情况,m>n的情况. (1)n>m的情况,0比1多几个都是行的,一共有m个“01”,后面补足够多个零即可. (2) ...