排列的字典序问题(java版)

排列的字典序问题(java版)

排列的字典序问题(java版)_第1张图片
排列的字典序问题(java版)_第2张图片

import java.io.*;
import java.util.Scanner;
//字典序
/*
* 思路:
 ①如何得到2 6 4 5 8 1 7 3的下一个排列?
* 1 从尾部往前找第一个P(i-1) < P(i)的位置
* 2 6 4 4 5 8 1 <-- 7 <-- 3
* 最终找到1是第一个变小的数字,记录下1的位置i-1
* 2 从尾部往前找到第一个大于1的数
* 2 6 4 4 5 8 1 7 3 <--
* 最终找到3的位置,记录位置为m
* 3 交换位置i-1和m的值
* 2 6 4 4 5 8 3 7 1
* 4 倒序i位置后的所有数据
* 2 6 4 4 5 8 3 1 7
②如何得到2 6 4 5 8 1 7 3所对应的字典序值
* 比2小的数有1个,则 value+=1*7!;

* 比6小的数有4个,则 value+=4*6!;

* 比4小的数有2个,则 value+=2*5!;

* 比5小的数有2个,则 value+=2*4!;

* 比8小的数有3个,则 value+=3*3!;

* 比1小的数有0个,则 value+=0*2!;

* 比7小的数有1个,则 value+=1*1!;

* 比3小的数没有;

* */
class lab1_2_4 {
    public static void main(String[] args) throws IOException {
        Scanner input = new Scanner(System.in);
//        int n = input.nextInt();
//        int n = 8;
        File outFile = new File("F://input1.2.4.txt");//要现在F盘建文件
        BufferedReader br = new BufferedReader(new FileReader(outFile));
        String str1 = br.readLine();
        int n = Integer.parseInt(str1.trim());
        String str = br.readLine();//读取文件的数据
        String[] arrs = str.split(" ");
        int[] arr = new int[n];
        for(int i = 0;i < arrs.length;i++){
            arr[i] = Integer.parseInt(arrs[i]);
        }
        String data1 = "",data2 = "\n";
        System.out.println("orderValue:" + orderValue(arr,n));
        data1 += orderValue(arr,n);
        int[] b = nextNumber(arr,n);
//        System.out.print("nextNumber: ");
        for (int x:b
             ) {
//            System.out.print(x +" ");
            data2 += x + " ";
        }
        File inFile =new File("F://output1.2.4.txt");//算出的数据存在F盘
        Writer out =new FileWriter(inFile);
        out.write(data1);//把数据存进文件
        out.write(data2);//把数据存进文件
        out.close();

    }
    public static int fi(int n){//计算阶乘方法
        if(n == 0 || n == 1){
            return 1;
        }
        else
            return n * fi(n-1);
    }
    public static int orderValue(int[]a,int n){//用二重循环计算出数组中的数字所代表的值
        int value = 0;
        for( int i = 0;i < a.length;i++){
            int sum = 0;//记录每次比a[i]小的数的个数
            for(int j = i;j < a.length;j++){
                if(a[i]>a[j]){
                    sum ++;
                }
            }
            value += sum * fi(n - i -1);
        }
        return value;
    }
    public static int[] nextNumber(int[] a, int n){
        int index1 = 0;//从右端开始降序的索引
        int index2 = 0 ;
        for( int i = n-1;i >= 1;i --){
            if(a[i] > a[i - 1]){
                index1 = i - 1;
                break;
            }
        }
        for( int i = n-1;i >= index1;i --){
            if(a[i] > a[index1]){
                index2 = i;
                break;
            }
        }
        swap(a,index1,index2);
        arrayReverse(a,index1 + 1);
        return a;
    }
    public static void arrayReverse (int[] arr, int x){//逆序数组
        for(int start=x,end=arr.length-1; start<=end;start++,end--){
            int tmp = arr[start];
            arr[start] = arr[end];
            arr[end] = tmp;
    }
    }
    public static void swap(int[] arr,int index1,int index2){//把数组中的两个元素交换
        int tem ;
       tem = arr[index1] ;
       arr[index1] = arr[index2];
       arr[index2] = tem;
    }

}
/*
* 心得:
* 我觉这个题,尤其是求解字典序值的时候有点像是冒泡排序那种感觉,
* 两重循环,上一层循环的起点 看作是下一层的起点
* 之前总是编译不通过是因为没有用break语句,经过调试发现是那里出现了问题
* */

你可能感兴趣的:(java)