华为OD E卷(100分)24-第K个排列

前言

        工作了十几年,从普通的研发工程师一路成长为研发经理、研发总监。临近40岁,本想辞职后换一个相对稳定的工作环境一直干到老, 没想到离职后三个多月了还没找到工作,愁肠百结。为了让自己有点事情做,也算提高一下自己的编程能力,无聊之余打算用一些大厂的编程题练练手。希望通过这些分享能够帮到一些人,也希望能和看到此文的大神们沟通交流,提升自己,更希望在此期间能够找到一份理想的工作。

题目描述

        给定参数n,从1到n会有n个整数:1,2,3,.,n,这n个数字共有 n!种排列。
        按大小顺序升序列出所有排列情况,并-一标记,当n=3时,所有排列如下:

"123"

"132"

"213"

"231"

"312"

"321"

        给定n 和 k,返回第k个排列。

输入

        输入两行,第一行为n,第二行为k,给定n的范国是[1,9],给定k的范围是[1,n!]。

输出 

        输出排在第k位置的数字。

示例

示例1

输入:
3
3

输出:
213

说明:
3的排列有123 132 213...,那么第3位置的为213

示例2

输入:
2
2

输出:
21

说明:
2的排列有12 21,那么第2位置的为21

解题思路

         这道题属于排列组合问题,需要找到第 k 个排列。给定数字 n,有 n! 种排列。
通过 数学方法 来求解,我们可以避免生成所有排列,直接通过数学推理一步步缩小范围,找到目标排列。

当n=4,k=15时

确定第一位:
            k = 14(从0开始计数)
            index = k / (n-1)! = 2, 说明第15个数的第一位是3
            更新k
            k = k - index*(n-1)! = 2
确定第二位:
            k = 2
            index = k / (n-2)! = 1, 说明第15个数的第二位是2
            更新k
            k = k - index*(n-2)! = 0
确定第三位:
            k = 0
            index = k / (n-3)! = 0, 说明第15个数的第三位是1
            更新k
            k = k - index*(n-3)! = 0
确定第四位:
            k = 0
            index = k / (n-4)! = 0, 说明第15个数的第四位是4
最终确定n=4时第15个数为3214

题解

Java实现

package huawei.e100;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
* @author arnold
* @date 2024年12月16日
* 

*/
public class T24 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		while(sc.hasNext()) {
			int n = sc.nextInt();
			int k = sc.nextInt();
			System.out.println(run(n,k));
		}
	}
	
	static String run(int n, int k) {
		// 待选择的数
		List<Integer> nums = new ArrayList<Integer>();
		// 1-N个数字组合的数,1个数的组合为 1*1,2个数的组合为2*1, 3个数的组合为3*2*1
		int[] factorials = new int[n+1];
		int f = 1;
		for (int i = 1; i <= n; i++) {
			nums.add(i);
			f *= i;
			factorials[i] = f;
		}
		
		k--;
		
		StringBuilder sb = new StringBuilder();
		
        for(int i=n-1; i>=0; i--){
            int index = k / factorials[i];
            sb.append(nums.remove(index));
            k -= index*factorials[i];
        }
		
		return sb.toString();
	}
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

arnold66

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值