一、下一个排列

首先,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. pat1059. Prime Factors (25)

    1059. Prime Factors (25) 时间限制 50 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 HE, Qinming Given ...

  2. JS for循环删除数组元素

    $(function(){ var aa = [1,1,2,3,3,4,4,5]; alert(aa); for (var i = aa.length-1;i >= 0 ;i--) { if ( ...

  3. Unity C# 调用SaveFileDialog保存Excel文件

    本文原创,转载请注明出处:http://www.cnblogs.com/AdvancePikachu/p/6893934.html 本文学习如何把数据转存为Excel文件并调用SaveFileDial ...

  4. js清除缓存以及jsp缓存[部分常用]

    参考: http://bbs.csdn.net/topics/330028896  浏览器缓存机制 http://www.docin.com/p-591569918.html  浏览器缓存的一些问题的 ...

  5. linux修改系统时间为北京时间(CentOS)

    删除本地时间 rm -rf /etc/localtime 设置时区为上海 ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 利用date查看 ...

  6. Spring Boot概要

    1.Spring Boot使用“习惯优于配置”(项目中存在大量的配置,此外还内置了一个习惯性的配置)的理念,使用户的项目实现快速运行.通过学习Spring Boot中的配置文件application. ...

  7. /pentest/cisco/cisco-auditing-tool

    /pentest/cisco/cisco-auditing-tool ./CAT    -h host 扫描单个主机 -w  wordlist 猜测团体名称列表 -a passlist   猜测密码列 ...

  8. 数据字典的设计--4.DOM对象的ajax应用

    需求:点击下拉选项框,选择一个数据类型,在表单中自动显示该类型下所有的数据项的名称,即数据库中同一keyword对应的所有不重复的ddlName.      1.在dictionaryIndex.js ...

  9. VMware下Centos6.4安装

    VMware(Virtual Machine ware)是一个“虚拟PC”软件公司,提供服务器.桌面虚拟化的解决方案. 小伙伴们网上下载VMware11,一路下一步自己安装吧!!! 打开 VMware ...

  10. shell脚本调试技巧

    shell脚本调试之工具——bashdb http://www.cnblogs.com/itcomputer/p/5011845.html