效果
根据排列计算不同生成算法的下一排列
分两种模式,输入排列和输入序数,由于中介数并不能保证三者中同时存在,所以懒得做了.....
目前也只做了常见的9位,懒得支持任意位。。。。(主要作业中大多是九位的)
对于速度而言,由于是在运行期间计算所有排列所以在初始加载时比较慢,可以先持久化为json文件,直接加载,查找排列时可以用高效的二分查找,缩短查找时间
数据结构方面,对于表格格式的输出,应该设置一个转换函数,将对象转为需要的格式
工具函数可以集成到一个对象中,直接调用 静态方法
工具
// 获取长度为len的所有排列,按照字典序
function getAllRange(len) {
let a = []
let MAX = len
let used = new Set()
let ALL = []
dfs(0)
function dfs(n) {
if (n == MAX) {
// console.log(a)
ALL.push(Array.from(a))
used.delete(a.pop())
return
}
for (let i = 1; i <= MAX; i++) {
if (!used.has(i)) {
a.push(i)
used.add(i)
dfs(n + 1)
}
}
used.delete(a.pop())
}
return ALL
}
// 阶乘
function fac(n) {
return n < 2 ? 1 : n * fac(n - 1)
}
// 字典序中介数计算
function f1(arr) {
let ret = []
for (let i = 0; i < arr.length; i++) {
let c = 0
for (let j = i + 1; j < arr.length; j++)
arr[j] < arr[i] ? c++ : c
ret[i] = c
}
return ret.slice(0, arr.length - 1)
}
// 字典序中介数求序数
function getM1(arr) {
return arr.reduce(
(pre, cur, index) => pre + cur * fac(arr.length - index),
0
)
}
// 递增排列转中介数
function f2(arr) {
let ret = []
for (let i = 0; i < arr.length; i++) {
let c = 0
for (let j = i + 1; j < arr.length; j++)
arr[j] < arr[i] ? c++ : c
ret[arr[i] - 1] = c
}
return ret.reverse().slice(0, arr.length - 1)
}
// 递增中介数求序数
function getM2(a) {
return a.reduce(
(pre, cur, index) => pre + cur * fac(a.length - index),
0
)
}
// 递减中介数求序数
function getM3(a, len) {
let pre = a[0]
for (let i = 1; i < a.length; i++) {
pre = pre * (len - a.length + 1 + i) + a[i]
}
return pre
}
function getData(len) {
let data = {
inc: {},
dec: {},
dic: {}
}
let range = getAllRange(len)
for (let i of range) {
// 递增的中介数和序数
data['inc'][i.join('')] = {}
data['inc'][i.join('')]['mid'] = parseInt(f2(i).join(''))
data['inc'][i.join('')]['num'] = getM2(f2(i))
data['inc'][i.join('')]['range'] = i.join('')
// 递减
data['dec'][i.join('')] = {}
data['dec'][i.join('')]['mid'] = parseInt(f2(i).reverse().join(''))
data['dec'][i.join('')]['num'] = getM3(f2(i).reverse(), len)
data['dec'][i.join('')]['range'] = i.join('')
// 字典
data['dic'][i.join('')] = {}
data['dic'][i.join('')]['mid'] = parseInt(f1(i).join(''))
data['dic'][i.join('')]['num'] = getM1(f1(i))
data['dic'][i.join('')]['range'] = i.join('')
}
return data
}
// 字典序下一个排列
function next1(arr) {
let num = d['dic'][arr]['num']
console.log(num + 1)
for (let i in d['dic']) {
if (d['dic'][i]['num'] == num + 1) {
console.log(i)
return {
key: i,
num: d['dic'][i]['num'] + 1,
mid: d['dic'][i]['mid']
}
}
}
}
let d = getData(9)
// 递增序下一个排列
function next2(arr) {
console.log(d['inc'][arr])
let num = 1 + d['inc'][arr]['num']
console.log(num)
for (let i in d['inc']) {
if (d['inc'][i]['num'] == num) {
console.log(i)
return {
key: i,
num: d['inc'][i]['num'],
mid: d['inc'][i]['mid']
}
}
}
}
// 递减序下一个排列
function next3(arr) {
console.log(d['dec'][arr])
let num = 1 + d['dec'][arr]['num']
console.log(num)
for (let i in d['dec']) {
if (d['dec'][i]['num'] == num) {
console.log(i)
return {
key: i,
num: d['dec'][i]['num'],
mid: d['dec'][i]['mid']
}
}
}
}
// 递增进制的加法,低位逢二进一,依次递增
function inc1(num) {
let a = Array.from('' + num).map(cur => cur - '').reverse()
// console.log(a);
let c = 1
for (let i = 0; i < a.length; i++) {
let s = (a[i] + c)
a[i] = s % (i + 2)
c = Math.floor(s / (i + 2))
}
if (c == 1) {
a[a.length] = 1
}
console.log(a);
return parseInt(a.reverse().join(''))
}
// 递减进制的加法,低位逢九进一,依次递减
function inc2(num, len = 9) {
let a = Array.from('' + num).map(cur => cur - '').reverse()
// console.log(a);
let c = 1
for (let i = 0; i < a.length; i++) {
let s = (a[i] + c)
a[i] = s % (len - i)
c = Math.floor(s / (len - i))
}
if (c == 1) {
a[a.length] = 1
}
console.log(a);
return parseInt(a.reverse().join(''))
}
export {
d,
next1,
next2,
next3,
}
ui
<template>
<div class="main">
<el-form ref="form" :model="form" label-width="80px" style="width: 300px">
<el-form-item label="位数">
<el-select v-model="form.len">
<el-option v-for="i in 9" :label="i" :value="i" :key="i"></el-option>
</el-select>
</el-form-item>
<el-form-item label="类型">
<el-select v-model="form.type">
<el-option label="序数" :value="0"></el-option>
<!--<el-option label="中介数" :value="1"></el-option>-->
<el-option label="排列" :value="2"></el-option>
</el-select>
</el-form-item>
<el-form-item label="数据">
<el-input v-model="form.input" placeholder="请输入数据" @keyup.enter.native="onSubmit"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">submit</el-button>
</el-form-item>
</el-form>
<table class="table table-bordered table-striped " style="width: 800px;text-align: center">
<thead>
<tr>
<th></th>
<th>增序</th>
<th>逆序</th>
<th>字典序</th>
</tr>
</thead>
<tbody>
<tr v-for="i,index in tableData">
<th scope="row">{{cols[index]}}</th>
<td>{{tableData[index][0]}}</td>
<td>{{tableData[index][1]}}</td>
<td>{{tableData[index][2]}}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import {next1, next2, next3, d} from '../util'
import 'bootstrap/dist/css/bootstrap.css'
export default {
name: "main-view",
methods: {
// 对应不同类型的处理函数,返回一个对象
f0() {
// 输入的是序数 232450
let cur_inc, cur_dec, cur_dic
let next_inc, next_dec, next_dic
for (let i in d['inc']) {
if (d['inc'][i]['num'] == this.form.input) {
cur_inc = d['inc'][i]
break
}
}
for (let i in d['dec']) {
if (d['dec'][i]['num'] == this.form.input) {
cur_dec = d['dec'][i]
break
}
}
for (let i in d['dic']) {
if (d['inc'][i]['num'] == this.form.input) {
cur_dic = d['dic'][i]
break
}
}
for (let i in d['inc']) {
if (d['inc'][i]['num'] == cur_inc['num'] + 1) {
next_inc = d['inc'][i]
break
}
}
for (let i in d['dec']) {
if (d['dec'][i]['num'] == cur_dec['num'] + 1) {
next_dec = d['dec'][i]
break
}
}
for (let i in d['dic']) {
if (d['dic'][i]['num'] == cur_dic['num'] + 1) {
next_dic = d['dic'][i]
break
}
}
return [
[cur_inc['num'], cur_dec['num'], cur_dic['num']],
[cur_inc['mid'], cur_dec['mid'], cur_dic['mid']],
[cur_inc.range, cur_dec.range, cur_dic.range],
[next_inc['num'], next_dec.num, next_dic.num],
[next_inc.mid, next_dec.mid, next_dic.mid],
[next_inc.range, next_dec.range, next_dic.range],
]
},
f1() {
// 输入的是中介数
},
f2() {
// 输入的是排列 //632589714
let cur_inc = d['inc'][this.form.input]
let cur_dec = d['dec'][this.form.input]
let cur_dic = d['dic'][this.form.input]
let next_inc, next_dec, next_dic
for (let i in d['inc']) {
if (d['inc'][i]['num'] == cur_inc['num'] + 1) {
next_inc = d['inc'][i]
break
}
}
for (let i in d['dec']) {
if (d['dec'][i]['num'] == cur_dec['num'] + 1) {
next_dec = d['dec'][i]
break
}
}
for (let i in d['dic']) {
if (d['dic'][i]['num'] == cur_dic['num'] + 1) {
next_dic = d['dic'][i]
break
}
}
return [
[cur_inc['num'], cur_dec['num'], cur_dic['num']],
[cur_inc['mid'], cur_dec['mid'], cur_dic['mid']],
[cur_inc.range, cur_dec.range, cur_dic.range],
[next_inc['num'], next_dec.num, next_dic.num],
[next_inc.mid, next_dec.mid, next_dic.mid],
[next_inc.range, next_dec.range, next_dic.range],
]
},
// 执行查询显示结果
onSubmit() {
this.tableData = [this.f0, this.f1, this.f2][this.form.type]()
}
},
data() {
return {
cols: ['当前序数', '当前中介数', '当前排序', '下一序数', '下一中介数', '下一排序'],
form: {
len: 9,
type: 2,
input: ''
},
tableData: Array(6).fill([]),
}
}
}
</script>
<style scoped>
.main {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
</style>