一、下一个排列

首先,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. 《大话设计模式》num03-04-05---单一职责原则、开放封闭原则、依赖倒转原则

    2018年03月03日 21:19:19 独行侠的守望 阅读数个人分类: 设计模式 版权声明:本文为博主原创文章,转载请注明文章链接. https://blog.csdn.net/xiaoanzi12 ...

  2. 1074 食物链 2001年NOI全国竞赛

    1074 食物链 2001年NOI全国竞赛 时间限制: 3 s 空间限制: 64000 KB 题目等级 : 钻石 Diamond         题目描述 Description 动物王国中有三类动物 ...

  3. The sixth day

    bound to 铁定You are bound to be fired  你会被铁定开除的 A:Dan forgot his map? Dan忘了带地图了吗? B:Yep!And he's boun ...

  4. Struts2笔记1

    一.简介 1.作用于web层:Struts2是一种基于MVC模式的轻量级Web框架; 2.各文件夹简介:     apps:该文件夹存用于存放官方提供的Struts2示例程序,这些程序可以作为学习者 ...

  5. vue-cli建立的项目如何在手机端运行以及如何用charles来抓包

    刚开始自己在config文件夹下的index.js中的dev下的host写成的是localhost,但是发现自己不能在手机端访问,并且也不可以在charles进行抓包处理,后来把localhost改成 ...

  6. <Android 基础(二)> BroadcastReceiver

    介绍 BroadcastReceiver:广播接收者,很形象,广播发送,类比生活中的广播,有能力听得到的都可以介绍到这个信息,然后在大脑中反映.对应到Android中就是SendBroadcast和o ...

  7. pandas error记录随笔

    1.sys:1: DtypeWarning: Columns (0,1) have mixed types. Specify dtype option on import or 解决办法:PANDAS ...

  8. Wince 6.0获取设备的分辨率 自动设置窗体位置

    调用微软提供给wince的API  “coredll.dll” [DllImport("coredll.dll")] public static extern int GetSys ...

  9. Localroast使用总结

    全手打原创,转载请标明出处: https://www.cnblogs.com/dreamsqin/p/10883248.html,多谢~=.= 什么是Localroast 一个根据 JSON 文件快速 ...

  10. StackOverflow之旅<2>------{HashMap和Hashtable的区别}

    问题 在Java中HashMap和Hashtable的区别? 哪一个对于多线程应用程序更好? 回答 Hashtable是同步的,加了synchronized锁,而HashMap不是.没有加synchr ...