首页 > 编程语言 >【华为OD-E卷 - 第k个排列 100分(python、java、c++、js、c)】

【华为OD-E卷 - 第k个排列 100分(python、java、c++、js、c)】

时间:2025-01-19 16:02:12浏览次数:3  
标签:排列 java 数字 nums python OD 列表 int 阶乘

【华为OD-E卷 - 第k个排列 100分(python、java、c++、js、c)】

题目

给定参数 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 位置的数字

用例

用例一:
输入:
3
3
输出:
213
用例二:
输入:
2
2
输出:
21

python解法

  • 解题思路:
  • 该代码的目标是解决排列组合中的第 k 个排列问题(即字典序第 k 小的排列)。问题描述是:给定正整数 n 和 k,返回从 [1, 2, …, n] 这些数字组成的所有排列中按字典序排列的第 k 个排列。

主要思路:

使用阶乘数组:通过预计算阶乘(factorial),快速确定某一位数字对应的索引范围。
按位置逐位构造排列:
确定第 i 位数字时,根据当前剩余排列数量可以计算该位应该选取的数字。
从剩余数字中取出对应的数字,并从候选数字列表中移除。
递归更新剩余的索引值 k:
计算余数,缩小问题规模,继续处理剩余的数字

n = int(input())  # 输入 n,表示排列的长度
k = int(input())  # 输入 k,表示需要找的第 k 个排列

# 初始化数字数组 [1, 2, ..., n]
numbers = [i + 1 for i in range(n)]

# 计算阶乘数组,用于快速确定当前数字的索引范围
factorial = [1] * (n + 1)
for i in range(2, n + 1):
    factorial[i] = factorial[i - 1] * i

# 初始化结果数组,用于存储最终的排列结果
result = []

# 因为索引从 0 开始,所以 k 减 1
k -= 1

# 遍历每一位,逐步确定每一位数字
for i in range(1, n + 1):
    # 计算当前位需要选择的数字索引
    index = k // factorial[n - i]
    
    # 将该数字添加到结果数组中
    result.append(str(numbers[index]))
    
    # 从候选数字中移除已选择的数字
    numbers.pop(index)
    
    # 更新 k 的值,缩小问题规模
    k %= factorial[n - i]

# 将结果数组拼接成字符串并输出
print("".join(result))

java解法

  • 解题思路
  • 目标是找到 [1, 2, …, n] 的所有排列中,按字典序排序后的第 k 个排列。解决方式与 Python 版本相似,采用递归的方法逐步构造结果。

主要步骤:

利用阶乘的性质确定排列范围:
对于长度为 n 的排列,前 n-1 位的排列总数为 (n-1)!。
根据 (k-1) / (n-1)! 可以计算出当前排列的起始数字的索引。
递归生成排列:
每次选定一个数字,将其从候选列表中移除。
根据剩余的 k 值,递归处理剩下的数字。
拼接结果:
每次递归选出的数字依次拼接,最终形成完整的排列。

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

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in); // 创建输入对象
        int n = sc.nextInt(); // 输入 n,表示排列的长度
        int k = sc.nextInt(); // 输入 k,表示需要找的第 k 个排列
        List<Integer> nums = new ArrayList<>(); // 初始化数字列表 [1, 2, ..., n]
        for (int i = 1; i <= n; i++) nums.add(i);
        // 调用函数获取第 k 个排列并输出
        System.out.println(getPermutation(nums, k));
    }

    /**
     * 获取第 k 个排列
     * @param nums 候选数字列表
     * @param k    第 k 个排列(从 1 开始)
     * @return     第 k 个排列的字符串
     */
    public static String getPermutation(List<Integer> nums, int k) {
        // 如果列表为空,返回空字符串(递归终止条件)
        if (nums.size() == 0) return "";
        int n = nums.size(); // 当前列表的长度
        int f = factorial(n - 1); // 计算 (n-1)!,用于确定当前数字的范围
        int index = (k - 1) / f; // 确定当前位数字的索引
        int chosen = nums.remove(index); // 从候选数字列表中移除选择的数字
        k = k - index * f; // 更新 k,处理剩余部分
        // 返回当前选择的数字和剩余数字的排列结果
        return chosen + getPermutation(nums, k);
    }

    /**
     * 计算 n 的阶乘
     * @param n 非负整数
     * @return  n 的阶乘
     */
    public static int factorial(int n) {
        int result = 1; // 初始化结果为 1
        for (int i = 2; i <= n; i++) result *= i; // 从 2 开始累乘到 n
        return result;
    }
}

C++解法

  • 解题思路
更新中

C解法

  • 解题思路

更新中

JS解法

  • 解题思路

  • 问题目标是找到从 [1, 2, …, n] 这些数字中生成的所有排列中,按字典序第 k 小的排列。代码使用了贪心算法结合数学分析来高效解决该问题。

核心思路:
使用阶乘的性质分割排列范围:
如果第一个数字固定为某值,那么剩下的排列数是 (n-1)!。
利用 k / (n-1)! 可以快速确定当前位的数字是哪一个。
动态更新数字列表:
每次确定一位数字后,将其从候选数字列表中移除。
逐步缩小问题规模:
更新 k 的值为当前范围内的余数,递归处理剩余的排列问题。
边界处理:
当数字列表为空时,递归终止

const readline = require('readline'); // 引入 readline 模块处理标准输入输出
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

rl.on('line', (input) => {
    // 处理输入,第一行为 n,第二行为 k
    if (!global.n) {
        global.n = parseInt(input.trim()); // 读取 n
    } else {
        global.k = parseInt(input.trim()); // 读取 k
        console.log(getKthPermutation(global.n, global.k)); // 输出第 k 个排列
        rl.close(); // 关闭输入流
    }
});

/**
 * 获取第 k 个排列
 * @param {number} n - 数字范围 1 到 n
 * @param {number} k - 第 k 个排列(从 1 开始)
 * @return {string} 返回第 k 个排列的字符串
 */
function getKthPermutation(n, k) {
    let factorials = [1]; // 用于存储阶乘值
    let nums = []; // 候选数字列表

    // 初始化阶乘数组和候选数字列表
    for (let i = 1; i <= n; i++) {
        factorials[i] = factorials[i - 1] * i; // 计算并存储 i 的阶乘
        nums.push(i); // 将数字 i 加入候选数字列表
    }

    k--; // 将 k 转换为从 0 开始的索引
    let result = ''; // 存储最终结果的字符串

    // 从高位到低位依次确定每一位数字
    for (let i = n; i > 0; i--) {
        // 确定当前位数字的索引
        let idx = Math.floor(k / factorials[i - 1]);
        result += nums[idx]; // 将选定的数字添加到结果字符串中
        nums.splice(idx, 1); // 从候选数字列表中移除该数字
        k %= factorials[i - 1]; // 更新 k 的值为余数
    }

    return result; // 返回最终结果
}

注意:

如果发现代码有用例覆盖不到的情况,欢迎反馈!会在第一时间修正,更新。
解题不易,如对您有帮助,欢迎点赞/收藏

标签:排列,java,数字,nums,python,OD,列表,int,阶乘
From: https://blog.csdn.net/CodeClimb/article/details/145184950

相关文章

  • 咱们继续学Java——高级篇 第一百八十三篇:之Java高级Swing编程之JEditorPane组件与进
    咱们继续学Java——高级篇第一百八十三篇:之Java高级Swing编程之JEditorPane组件与进度指示器在Java编程的学习旅程中,我们始终保持着积极探索、共同成长的态度。今天,我们将深入学习Java高级Swing编程中关于JEditorPane组件与进度指示器的部分,包括JEditorPane组件的功能特性......
  • python图书管理系统
    效果展示概述本教程将引导你构建一个基于Python的图书管理系统,该系统使用Tkinter作为图形用户界面(GUI),并利用SQLite数据库存储和管理图书信息。通过本教程,你将学习如何实现添加、编辑、删除以及查询图书的功能。准备工作确保你的计算机上安装了Python3.x版本。由于我们......
  • Java学习,删除集合指定元素
    Java删除集合中指定元素,通常依赖于集合具体类型。不同的集合类型(如ArrayList,HashSet,LinkedList等)提供了不同的方法来执行此操作。使用ArrayList:importjava.util.ArrayList;importjava.util.List; publicclassMain{  publicstaticvoidmain(String[]ar......
  • 小志的Java学习计划
    小志的Java学习计划自身情况分析及目标​普通二本计算机软件工程专业,大学期间未参加比赛,绩点和个人技术水平也不高只能说可以保证毕业。一战考研数学发挥失利。受到网络上学历贬值的信息的影响,考虑到本身报考院校也不是出色的双非院校三年以后就业也许也不容易,于是并不打......
  • [2025.1.19 JavaSE学习]网络编程-2(netstat指令 && TCP补充)
    netstatnetstat-an:可以查看当前主机网络情况,包括端口监听情况和网络连接情况netstat-an|more:可以分页显示在dos控制台执行Listening表示某个端口在监听如果有一个外部程序(客户端)连接到该端口,就会显示一条连接信息PS:netstat-anb,可以发现,8888端口号在上一节程序运行......
  • 【NodeJS渗透】提取和分析.asar文件的案例研究
    免责声明⽂中所涉及的技术、思路和⼯具仅供以安全为⽬的的学习交流使⽤,任何⼈不得将其⽤于⾮法⽤途以及盈利等⽬的,否则后果⾃⾏承担。所有渗透都需获取授权!硬编码密钥(在SQLite中)和加密算法(在AesFormula.js文件中)信息泄露导致真实凭据被泄露一、案例研究本节案例研究将讨论我......
  • node.js经典电影共享系统的设计与实现程序+论文 可用于毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容一、选题背景关于电影共享系统的研究,现有研究主要以商业电影推荐与播放平台为主,专门针对经典电影共享的研究较少。在国内外,电影相关系统多侧重于热门电影的推广、盈......
  • node.js基于的图书书目推荐系统程序+论文 可用于毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容选题背景关于图书书目推荐系统的研究,现有研究主要以传统推荐算法在图书推荐中的应用为主,例如基于内容的推荐、基于协同过滤的推荐等。这些研究成果在一定程度上提高......
  • 【开源】一款基于JAVA的国产化自主可控的人工智能开源平台
    一、项目简介人工智能开源平台是由联合国内顶尖科研力量共同打造的国产化自主可控的人工智能开源平台。平台面向人工智能研究中的数据处理、算法开发、模型训练、算力管理和推理应用等各个流程的技术难点,研发了包括一站式算法开发平台、高性能分布式深度学习框架、先进算法模型库......
  • node.js基于的儿童手工创意店管理系统程序+论文 可用于毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容一、选题背景关于店铺管理系统的研究,现有研究主要以传统零售店铺或大型商业机构为主,专门针对儿童手工创意店的研究较少。在国内外,大多数店铺管理系统侧重于通用功能......