一、下一个排列

首先,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. php安装错误 (node.c:1953:error) 解决办法

    CentOs安装PHP在make时报错: root@---- [/opt/php-5.2.17]# make /bin/sh /opt/php-5.2.17/libtool --silent --pr ...

  2. JDK 7 API 下载

    JDK 7 API 官方下载地址: http://www.oracle.com/technetwork/java/javase/documentation/java-se-7-doc-download ...

  3. RxJava2 中多种取消订阅 dispose 的方法梳理( 源码分析 )

    Github 相关代码: Github地址 一直感觉 RxJava2 的取消订阅有点混乱, 这样也能取消, 那样也能取消, 没能系统起来的感觉就像掉进了盘丝洞, 迷乱… 下面说说这几种情况 几种取消的 ...

  4. SpringBoot的优缺点

    优点: 1.快速构建项目 2.对主流开发框架的无配置继承 3.项目可独立运行,无须外部依赖Servlet容器 4.提高运行时的应用监控 5.极大地提高了开发.部署效率 6.与云计算的天然集成 缺点: ...

  5. Android 常用RGB值及名称

    Android   常用RGB值及名称 颜  色 RGB值 英文名 中文名 #FFB6C1 LightPink 浅粉红 #FFC0CB Pink 粉红 #DC143C Crimson 深红/猩红 #F ...

  6. python3爬虫03(find_all用法等)

    #read1.html文件# <html><head><title>The Dormouse's story</title></head># ...

  7. 博客系统-后台页面搭建:eazy

    业务分析:布局为四个模块上边是系统描述,左边是导航菜单,中间是每个窗口的内容,下边是版权信息 点击左边的导航按钮,在右边窗口显示 代码: <%@ page language="java ...

  8. cms-详细页面-1

    cms-详细信息页面设计思路:点击主页面然后查询详细信信,把查询出来的数据放大modelandvie里面,然后返回前台,然后在跳转页面取出来显示:代码:mapper: <?xml version ...

  9. php使用GD库实现图片水印和缩略图——生成图片缩略图

    今天呢,就来学习一下在php中使用PD库来实现对图片水印的文字水印方法,不需要PS哦! 首先,准备素材 (1)准备一张图片 (2)准备一张水印(最好是透明的,即背景是白色底) (3)准备一中字体(在电 ...

  10. HDU5124 lines

    离散化 + 树状数组. 这些东西自己都是刚接触不久的,所以需要多写点题练练手. 题目描述: 一维坐标中有N条线段,其中有一个点上面覆盖的线段数是最多的,求该点上面的线段数目. 这道题和HDU1556特 ...