按字典顺序生成所有的排列

  因为最近在做[url=http://eastsun.iteye.com/category/34059]Project Euler[/url]上的题,里面涉及到的都是和数学有关问题,有一些数学概念会反复出现。比如判断一个数是否为素数,求一些元素的全排列之类。为了方便起见,我把一些功能写成函数,以便以后重复使用。这个帖子介绍的是将一些元素所有的全排列按[url=http://en.wikipedia.org/wiki/Lexicographical_order]字典顺序[/url]依次生成的函数。

[b][size=medium][color=red]☆[/color] Scala代码[/size][/b]
/**
&#Util.scala
utils for mathematical algorithm,include:
# generate all permutations in lexicographical order

@author Eastsun
*/
package eastsun.math

object Util {
/**
Rearranges the elements in the Array[T] src into the lexicographically next smaller permutation of elements.
The comparisons of individual elements are performed using operators <= and >= in Ordered[T]
@return true if the function rearranged the array as a lexicographicaly smaller permutation.
*/
def prevPermutation[T](src:Array[T])
(implicit view:(T) => Ordered[T]):Boolean = {
var i = src.length - 2
while(i >= 0 && src(i) <= src(i+1)) i -= 1
if(i < 0) return false
var j = src.length - 1
while(src(j) >= src(i)) j -= 1
adjustArray(src,i,j)
true
}

/**
Rearranges the elements in the Array[T] src into the lexicographically next greater permutation of elements.
The comparisons of individual elements are performed using operators <= and >= Ordered[T]
@return true if the function rearrange the array as a lexicographicaly greater permutation.
*/
def nextPermutation[T](src:Array[T])
(implicit view:(T) => Ordered[T]):Boolean = {
var i = src.length - 2
while(i >= 0 && src(i) >= src(i+1)) i -= 1
if(i < 0) return false
var j = src.length - 1
while(src(j) <= src(i)) j -= 1
adjustArray(src,i,j)
true
}

private def adjustArray[T](src:Array[T],i:Int,j:Int){
var tmp = src(i)
src(i) = src(j)
src(j) = tmp
var len = (src.length - i)/2
for(k <- 1 to len){
tmp = src(src.length - k)
src(src.length - k) = src(i + k)
src(i + k) = tmp
}
}
}

  算法没什么特别的,如果不清楚google一下即可,这儿就简单说明一下代码。Util中含两个public方法:
def prevPermutation[T](src:Array[T])(implicit view:(T) => Ordered[T]):Boolean
def nextPermutation[T](src:Array[T])(implicit view:(T) => Ordered[T]):Boolean

  顾名思义,第一个[color=orange]prevPermutation[/color]方法是将数组src重排成比当前字典顺序小的上一个排列。注意该方法的返回值为Boolean:如果存在比当前字典顺序小的排列,则重排src,并返回true;否则不影响src并返回false。还算有两点需要注意的地方:
  1.该方法第二个参数view是implicit的,所以调用该方法的时候可以省略。只需要保证类型T有一个到Ordered[T]类型的隐式转换就可以了。
  2.该方法第一个参数src中允许有重复的元素。
   [color=olive]比如对于1,2,3,3,其所有排列按字典顺序排列为:
    1233
    1323
    1332
    2133
    2313
    2331
    3123
    3132
    3213
    3231
    3312
    3321[/color]

[b][size=medium][color=red]☆[/color] 应用[/size][/b]
  下面就通过解决[url=http://eastsun.iteye.com/category/34059]Project Euler[/url]中的两个题来示范一下如何使用这两个API。

[url=http://projecteuler.net/index.php?section=problems&id=24]题目24[/url]:What is the millionth lexicographic permutation of the digits 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9?
[color=darkred]题目简介[/color]:将数字0, 1, 2, 3, 4, 5, 6, 7, 8 ,9的所有排列按字典顺序排序,求排在第1,000,000位的那个数字。(注意:从第一位记起)
  当然这个题有更高效的解决方法,可以参看[url=http://eastsun.iteye.com/blog/204837]Euler Project解题汇总 023 ~ 030[/url]。这里就使用nextPermutation方法暴力解决:
import eastsun.math.Util._

object Euler024 extends Application {
var src = Array(0,1,2,3,4,5,6,7,8,9)
for(idx <- 1 until 1000000) nextPermutation(src)
println(src.mkString(""))
}


[url=http://projecteuler.net/index.php?section=problems&id=41]问题41[/url]:What is the largest n-digit pandigital prime that exists?
[color=darkred]题目简介[/color]:一个数称为pandigital,如果它是数字1,2,……,n的一个排列。比如2143就是一个4位的pandigital。
  现在求所有pandigital中最大的那个素数。
[color=red]解题思路[/color]:我们先不对这个问题进行进一步数学上的分析,直接想怎么用蛮力法去解决它。显然,我们可以先从9位的pandigital从大大小进行尝试,如果找到了一个素数,那么这个数就是所求;否则,再对8位的pandigital从大到小进行尝试……如此直到找到一个素数为止,这个素数就是问题的答案。
  下面就是依照这个思路写的代码:
import eastsun.math.Util._

object Euler041 extends Application {


def isPrime(n:Int) = 2.to(math.sqrt(n).toInt).forall{ n%_ != 0}

var buf = Array(9,8,7,6,5,4,3,2,1)
var idx = 0
var res = 0
while(res == 0){
var src = buf.slice(idx,buf.length)//subArray(idx,buf.length)
do{
var num = src.foldLeft(0){ _*10 + _ }
if(isPrime(num)) res = num
}while(res == 0&&prevPermutation(src))
idx += 1
}
println(res)
}

  虽然是很野蛮的方法,但这段代码已经够用了,只需要2秒左右就能得到答案。不过只要再简单思考一下,就可以瞬时找到答案。如果你高中数学还学得马马虎虎,应该不难验证:[color=green]一个数能被3整除当且仅当这个数的各位数字之和能被3整除[/color]。这样就可以知道9位的pandigital里面不可能有素数,因为1+2+3+..+9 = 45能被三整除,同样可以知道8位的pandigital里面也没有素数。所以事实上我们从7位的pandigital试起就可以。
CTF实战:Wireshark数据包分析从入门到精通(附经典题型解析) 本文详细介绍了Wireshark在CTF比赛中的数据包分析技巧,从基础抓包到高级协议解析,涵盖HTTP流量分析、USB键盘数据还原等实战案例。通过经典题型解析,帮助读者掌握精准过滤、文件提取等核心技能,提升CTF竞赛中的网络流量分析能力。 阅读详情

相关推荐

CSI Tools 工具的安装 Intel 5300 + Ubuntu14.04

在 ubuntu14 系统上面安装 CSI Tools,2020最新教程,亲测可用,只要保证和我做法一致绝对可以安装好。

WS的小屋 1万+

生成字典序全排列

最近用到了C++ STL里的next_permutation函数,刚好又在复习算法,于是想到了生成全排列的算法。       有好几种算法可以生成全排列,比如自底向上插入生成全排列、Johnson-Trotter算法生成、字典序生成等等。       我想到用字典序生成全排列的一个算法。       字典序排列就是按照字典a-z,1-9的顺序给出字符串的顺序全排列,例如abc的全排列就是从a

Logan's 3522

crowdcountingp2p代码复现

前面学习了一下论文:Improved Field-Based Soybean Seed Counting and Localization with Feature Level Considered该论文的模型原型由CrowdCounting-P2PNet改进而来这里先复现一下CrowdCounting-P2PNet模型,然后再学习P2PNet-Soy模型。

m0_73832962的博客 2329

生成全排列

全排列的生成算法就是对于给定的字符集,用有效的方法将所有可能的全排列无重复无遗漏地枚举出来。任何n个字符集的排列都可以与1~n的n个数字的排列一一对应,因此在此就以n个数字的排列为例说明排列的生成法。          n个字符的全体排列之间存在一个确定的线性顺序关系。所有

天道酬勤! 2616

某手sig3-ios算法 Chomper黑盒调用

本文主要是介绍Chomper的算法模拟执行,Chomper目前已经已经是能比较完整的模拟ios可执行文件执行的模拟器,在这块有非常大的优势。以前安卓端有强势的unidbg,现在iOS也有Chomper了,后续等待作者持续更新,完善Chomper。强势推荐一波-> Chomper地址: https://github.com/sledgeh4w/chomper。我这块也已经使用Chomper完成雅迪系列、某手的算法调用。后续也会有更多扩展。

成小新的博客 2158

AI测试实战:用文心一言5分钟生成登录功能测试用例(附Excel模板)

本文详细介绍了如何利用AI工具(如文心一言)在5分钟内高效生成登录功能测试用例,并提供了可直接应用的Excel模板。通过对比传统手工编写与AI生成的效率差异,展示了AI在软件测试领域的巨大优势,包括减少重复劳动、避免边界条件遗漏和提升格式标准化。文章还包含实战技巧、高级应用方案和行业最佳实践,助力测试人员快速提升工作效率。

weixin_30379531的博客 411

用字典顺序得到所有的排列

RT :为了得到字典顺序的所有排列,我查了一些资料,发现有些说法好像有些问题,现在总结一下;【字典序法生成全排列】字典序列算法是一种非递归算法。而它正是STL中Next_permutation的实现算法。我们来看看他的思路吧:它的整体思想是让排列成为可递推的数列,也就是说从前一状态的排列,可以推出一种新的状态,直到最终状态。比如说,最初状态是12345,最终状态是54321。其实我觉得这跟我们手动做全排列是一样的。首先是12345,然后12354,然后12435,12453....逐渐地从后往前递增。看看算

xum2008的专栏 2473

应急响应之windows日志分析工具logparser使用

windows日志分析工具logparser使用介绍

u013930899的博客 8127

排列的生成(一) —— 字典序法

1.定义   在数学中,字典或词典顺序(也称为词汇顺序,字典顺序,字母顺序或词典顺序)是基于字母顺序排列的单词按字母顺序排列的方法。 这种泛化主要在于定义有序完全有序集合(通常称为字母表)的元素的序列(通常称为计算机科学中的单词)的总顺序。   对于数字1、2、3…n的排列,不同排列的先后关系是从左到右逐个比较对应的数字的先后来决定的。例如对于5个数字的排列 12354和12345,排列12345...

HachiLin的博客 6305

告别F5失灵!手把手教你为Cursor配置.Net Core控制台项目专属调试环境

本文详细指导如何在Cursor编辑器中为.Net Core控制台项目配置专属调试环境,解决F5失灵等常见问题。从调试器选择到launch.json配置,再到高级调试技巧,帮助开发者高效搭建完整的调试工具链,提升开发效率。

weixin_28834765的博客 288

R语言实战:非正态数据下的Scheirer–Ray–Hare检验全流程解析

本文详细解析了在R语言中执行Scheirer–Ray–Hare检验的全流程。当实验数据不符合正态分布时,该非参数检验是分析两因素设计(包括主效应和交互效应)的有效工具。文章从原理、环境配置、数据导入、核心代码到结果解读与报告撰写,提供了完整的实战指南,并附有常见的避坑建议。

weixin_29061465的博客 398

字典序法生成排列

/** 顾名思义,这种方法的思想就是将所有n元排列按“字典顺序”排成队, 以12…n为第一个排列,排序的规则,也就是由一个排列(p)=(p1p2…pn) 直接生成下一个排列的算法可归结为 (1) 求满足关系式P[k-1]<P[k]的k的最大值,设为i,即 i = max{k|P[k-1] < P[k]}; (2) 求满足关系式P[i-1]<P[k]的k的最大值,设为

星辰风 1189

吊打原版YOLOv8!ASF-YOLO多尺度融合+注意力机制实战解析(遥感/医疗/质检均适用)

ASF-YOLO融合YOLOv8的创新目标检测框架摘要 ASF-YOLO是针对小目标检测优化的先进框架,采用三重特征编码器和尺度序列融合技术增强多尺度特征提取能力。核心创新包括: 三重特征编码器(TPE)融合跨层级信息 尺度序列特征融合(SSFF)模块通过3D卷积处理多尺度信息 通道-位置注意力机制(CPAM)聚焦关键特征区域 Zoom_cat模块实现自适应多尺度特征融合 该框架特别适用于医学影像、遥感检测等小目标密集场景,通过动态特征权重调整显著提升检测精度。关键技术实现包含多尺度特征统一、3D卷积序列处

FJN110的博客 529

算法设计与分析-字典顺序生成排列【一看就会】

字典生成排序例题,一看就会

m0_57482322的博客 834

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

产生所有排列---字典顺序-----2013年1月23日

问题描述:以字典顺序产生所有排列。假定集合set是连续的并且按从小到大顺序排列好了的,并且有n个元素。 思路:算法的思路分成两个部分:A是递归产生以某个数字开头的排列,B是调用A来依次生成 1为第一位的所有排列,2为第一位的所有排列,....n为第一位的所有排列。 下面是A部分的详细思路: 1.以1234为例子。从右到左来寻...

weixin_33743703的博客 109

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

c++ 字典顺序生成全排列,蛮力算法时间复杂度 Θ(n*n!)

1. 我们先看下(按照字典顺序下一个最大排列是什么?)    {1,2,3} 全排列 {1,2,3}     {1,3,2}     {2,1,3}     {2,3,1}     {3,1,2}     {3,2,1}            例1:从上面随机选择一个排列 {2,1,3}    字典顺序下一个最大排列    {2,3,1}            例2:从上面随机选择一个排列 {3,...

qq_21286289的博客 2324

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

全排列生成算法(一)

对于给定的集合A{a1,a2,...,an},其中的n个元素互不相同,如何输出这n个元素的所有排列(全排列)。 递归算法 这里以A{a,b,c}为例,来说明全排列的生成方法,对于这个集合,其包含3个元素,所有的排列情况有3!=6种,对于每一种排列,其第一个元素有3种选择a,b,c,对于第一个元素为a的排列,其第二个元素有2种选择b,c;第一个元素为b的排列,第二个元素也有2种选择a,c,……,

joylnwang的专栏 5万+

递归算法之全排列生成(Permutations)详细解读

全排列(Permutations)是指从给定的 𝑛个元素中,按照某种顺序进行排列,生成所有可能的顺序组合。全排列是排列组合中的一个重要问题,在算法、数学、以及计算机科学中有着广泛的应用。

欢迎来到我的博客!这里是一个专注于计算机技术的分享平台,涵盖编程开发、算法研究、系统架构、软件工程等多个领域。无论你是初学者还是资深开发者,都能在这里找到有价值的内容。 3139

生成1~n的全排列,按字典序输出

这个题按照书上的解法,输出顺序并不是字典序,所以在网上找到了一个很棒的解法,先写到这里记录下来。 #include<iostream> using namespace std; int a[100]; void dfs(int cur,int n)//cur表示目前正在填的数,n表示总共要填的数 { if(cur==n)//递归边界,说明填完了 {...

weixin_30598225的博客 3040

C++递归与非递归实现全排列

#include "quicksort.h" void swap(int *p1,int *p2) { int temp=*p1; *p1=*p2; *p2=temp; } void reverse(int *a,int *b)//反转 { while(a swap(a++,b--);//因为在进行全排列时进行了判断,所以肯定在a到b这段范围内的值都是满足从大到小的顺序,反转后

坚持 751

生成组合对象

组合对象,即排列、组合和给定集合的子集等。 数学中我们也学过排列组合,对于给定的一个集合,给出其对应的排列组合,以及对应的子集。 生成排列 排列问题指的是对于给定的多个元素求其中各种可能的序列。为了简单起见,这里仅仅考虑1到n之间的整数的排列问题。 生成排列的方法有三种:插入法、Johnson-Trotter法、字典顺序法 插入法 方法便是依次从集合中取元素,并将其插入到之前生成的排列中。 如: 求n=3的排列 则首先在n=1的排列中插入2,然后在n=2的排列中插入3。 过程便是: 在 1 中从右到左插入

学习永无止境 571

每日一小练——按字典顺序列出所有排列

上得厅堂,下得厨房,写得代码,翻得围墙,欢迎来到睿不可挡的每日一小练!

睿不可挡的专栏 2940

N个字符全排列的非递归实现

(二)非递归全排列算法,即按字典序排列算法。 基本思想是:     1.对初始队列进行排序,找到所有排列中最小的一个排列Pmin。     2.找到刚刚好比Pmin大比其它都小的排列P(min+1)。     3.循环执行第二步,直到找到一个最大的排列,算法结束。 如排列ABCDE,这是所有排列中最小的一个排列,刚好比ABCDE大的排列是:ABCED。 算法如下: 给定已知序列P =

lin200753的专栏 1562

字典序生成排列

比较粗暴,根据《离散数学及其应用》的伪代码直接写的。public class GeneratingPermutation { public static void main(String[] args) { System.out.println(genPerm("123")); System.out.println(genPerm("243541"));

薛定谔的猫窝 1037
上一篇: Project Euler解题汇总 023 ~ 030
下一篇: Euler Project解题汇总 031 ~ 040
JavaSxy
博客等级 码龄21年 1粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值