一、下一个排列

首先,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;
}

最新文章

  1. javascript曲线图和面积图Line &amp; Area chart控件功能及下载
  2. Strong name signature not valid for this assembly Microsoft.mshtml.dll
  3. JavaScript由单价、数量计算总价
  4. http://www.blogjava.net/xzclog/archive/2011/09/29/359789.html
  5. 联想电脑win7旗舰版环境下的如何成功配置AppServ
  6. epoll分析
  7. Rstudio设置永久工作路径
  8. CPU使用率
  9. BYTE、WORD与DWORD类型
  10. LNMP1.2一键安装教程
  11. 初识EL表达式
  12. iOS菜鸟之FMDB的二次封装简单易用
  13. [置顶] 【Git入门之十五】Github操作指南
  14. 用标准Struts2+mvc写的用户管理
  15. 如何给js动态创建的dom添加事件
  16. curl学习之curl_setopt参数设置大总结
  17. Java 浮点型与双精度数值比较
  18. 【BZOJ 2395】Time is money
  19. SNF软件开发机器人-子系统-功能-启用大按钮样式如何配置
  20. linux基本介绍和使用

热门文章

  1. elasticsearch远程代码执行漏洞告警
  2. 【转】sql server数据库操作大全——常用语句/技巧集锦/经典语句
  3. IO字节流。
  4. mysql 批量修改 表字段/表/数据库 字符集和排序规则
  5. JavaScript初识(二)
  6. vue封装storage案例
  7. ArcGIS中Features与JSON的互相转化
  8. python基础-数据运算
  9. bt5 r3下metasploit连接postgresql数据库
  10. Visual Studio 更改护眼颜色