LeetCode 60:排列序列

LeetCode 60:排列序列

在這里插入圖片描述

問題定義與核心挑戰

給定整數 nk,返回集合 {1,2,...,n}k 個字典序排列。直接生成所有排列再遍歷到第 k 個的方法(時間復雜度 O(n!))會因 n≥10 時階乘爆炸而超時,因此需要 數學推導 + 貪心構造 的高效解法。

核心思路:階乘定位法

利用階乘的分組特性,逐位確定排列的每個數字:

  1. 階乘分組:對于 n 個數字,每個首位固定后,剩余 n-1 個數字的排列數為 (n-1)!。例如,n=3 時,首位為 1 的排列有 2! = 2 種(123132)。
  2. 逐位推導:通過計算 k-1(轉換為 0-based 索引)與階乘的商和余數,確定當前位的數字,并更新 k 為余數+1(保持后續推導的 1-based 邏輯)。

算法步驟詳解

步驟 1:預處理階乘數組

計算 0!(n-1)!,用于快速確定每組的排列數量:

// 階乘數組,fact[i] = i!
long[] fact = new long[n];
fact[0] = 1; // 0! = 1
for (int i = 1; i < n; i++) {fact[i] = fact[i-1] * i;
}
  • 例如,n=4 時,fact = [1, 1, 2, 6](對應 0!1!2!3!)。
步驟 2:初始化可用數字列表

維護一個動態列表,存儲當前未使用的數字(初始為 1~n):

List<Integer> nums = new ArrayList<>();
for (int i = 1; i <= n; i++) {nums.add(i);
}
步驟 3:逐位構造排列

從高位到低位(共 n 位),依次確定每個位置的數字:

StringBuilder res = new StringBuilder();
k--; // 轉換為 0-based 索引(核心!否則無法對齊階乘分組)for (int i = 0; i < n; i++) {// 當前剩余數字的數量:n - i// 當前階乘:(n-1-i)! → 對應剩余數字的排列數long currentFact = fact[n-1 - i];// 計算當前位的數字索引:k / currentFactint index = (int) (k / currentFact);// 取出數字,加入結果res.append(nums.get(index));// 從可用列表中移除該數字nums.remove(index);// 更新 k 為余數(下一輪的 k 是余數)k %= currentFact;
}

關鍵邏輯解析

  1. k-- 的必要性
    題目中 k1-based(如示例 1 中 k=3 對應第 3 個排列),但階乘分組的索引是 0-based。通過 k-- 轉換為 0-based 索引,確保計算時與階乘分組對齊。

  2. 階乘的作用
    currentFact = (n-1-i)! 表示剩余 n-i 個數字時,每個首位對應的排列數。例如,當確定第 1 位(i=0)時,currentFact = (n-1)!,即每個首位對應 (n-1)! 種排列。

  3. 索引計算與數字移除

    • index = k / currentFact:確定當前位應選可用列表中的第 index 個數字(因為前 index 組的排列數已被跳過)。
    • nums.remove(index):從可用列表中移除已選數字,避免重復使用。
    • k %= currentFact:更新 k 為當前組內的剩余索引,用于下一輪計算。

完整代碼(Java)

import java.util.ArrayList;
import java.util.List;class Solution {public String getPermutation(int n, int k) {// 1. 預處理階乘數組:fact[i] = i!long[] fact = new long[n];fact[0] = 1; // 0! = 1for (int i = 1; i < n; i++) {fact[i] = fact[i-1] * i;}// 2. 初始化可用數字列表:[1, 2, ..., n]List<Integer> nums = new ArrayList<>();for (int i = 1; i <= n; i++) {nums.add(i);}// 3. 逐位構造結果StringBuilder res = new StringBuilder();k--; // 轉換為 0-based 索引,方便計算for (int i = 0; i < n; i++) {// 當前剩余數字的排列數:(n-1-i)!long currentFact = fact[n-1 - i];// 計算當前位的數字索引int index = (int) (k / currentFact);// 取出數字,加入結果res.append(nums.get(index));// 移除已選數字nums.remove(index);// 更新 k 為余數k %= currentFact;}return res.toString();}
}

示例驗證(以示例 2 為例)

輸入n=4, k=9
預期輸出"2314"

推導過程:
  1. 階乘數組fact = [1, 1, 2, 6](對應 0!~3!)。
  2. 初始化nums = [1,2,3,4]k=9→k-1=8(轉換為 0-based)。
步驟 i剩余數字currentFactindex = 8 / currentFact選中數字nums 變為k = 8 % currentFact
0[1,2,3,4]6 (3!)8 / 6 = 12[1,3,4]8 % 6 = 2
1[1,3,4]2 (2!)2 / 2 = 13[1,4]2 % 2 = 0
2[1,4]1 (1!)0 / 1 = 01[4]0 % 1 = 0
3[4]1 (0!)0 / 1 = 04[]0 % 1 = 0

最終結果:"2314",與示例一致。

復雜度分析

  • 時間復雜度O(n2)
    • 階乘預處理:O(n)
    • 逐位構造:共 n 次循環,每次 nums.remove(index)O(n) 操作(數組拷貝)。
  • 空間復雜度O(n)
    • 階乘數組和可用列表均占用 O(n) 空間。

該方法通過階乘分組貪心構造,將時間復雜度從 O(n!) 降至 O(n2),高效解決了大 n 場景下的排列定位問題,是處理“有序排列定位”類問題的經典思路。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/916549.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/916549.shtml
英文地址,請注明出處:http://en.pswp.cn/news/916549.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

亞遠景-傳統功能安全VS AI安全:ISO 8800填補的標準空白與實施難點

一、為什么需要ISO 8800&#xff1a;傳統安全標準的“盲區”傳統功能安全&#xff08;ISO 26262&#xff09;? 假設&#xff1a;系統行為可被完整規格化&#xff0c;失效模式可枚舉&#xff0c;風險可用概率-危害矩陣量化。? 盲區&#xff1a;對“設計意圖正確&#xff0c;但…

菜鳥教程 R語言基礎運算 注釋 和數據類型

菜鳥教程 R語言基礎運算 注釋 和數據類型 1.注釋 注釋主要用于一段代碼的解析&#xff0c;可以讓閱讀者更易理解&#xff0c;編程語言的注釋會被編譯器忽略掉&#xff0c;且不會影響代碼的執行。 一般編程語言的注釋分為單行注釋與多行注釋&#xff0c;但是 R 語言只支持單行注…

華為云ELB(彈性負載均衡)持續報異常

華為云ELB&#xff08;彈性負載均衡&#xff09;持續報異常&#xff0c;需結合實例類型&#xff08;共享型/獨享型&#xff09;和異常代碼進行針對性排查。以下是分步排查建議&#xff1a;一、根據實例類型排查網絡配置共享型實例 安全組規則&#xff1a;檢查后端服務器安全組是…

《R for Data Science (2e)》免費中文翻譯 (第2章) --- Workflow: basics

寫在前面 本系列推文為《R for Data Science (2)》的中文翻譯版本。所有內容都通過開源免費的方式上傳至Github&#xff0c;歡迎大家參與貢獻&#xff0c;詳細信息見&#xff1a; Books-zh-cn 項目介紹&#xff1a; Books-zh-cn&#xff1a;開源免費的中文書籍社區 r4ds-zh-cn …

開源深度學習新寵:Burn框架助您無憂高效建模

在日新月異的人工智能世界里&#xff0c;各類深度學習框架如雨后春筍般涌現&#xff0c;而Burn&#xff0c;作為新一代的深度學習框架&#xff0c;以其不妥協的靈活性、高效性和可移植性嶄露頭角。本文將深入探討Burn的核心功能、應用場景及具體使用方法&#xff0c;幫助您更好…

基于深度學習的圖像分割:使用DeepLabv3實現高效分割

前言 圖像分割是計算機視覺領域中的一個重要任務&#xff0c;其目標是將圖像中的每個像素分配到不同的類別中。近年來&#xff0c;深度學習技術&#xff0c;尤其是卷積神經網絡&#xff08;CNN&#xff09;&#xff0c;在圖像分割任務中取得了顯著的進展。DeepLabv3是一種高效的…

如何高效合并音視頻文件(時間短消耗資源少)(二)

英語字幕 1 00:00:06,480 --> 00:00:08,400 Good morning. We have a banger for you2 00:00:08,400 --> 00:00:09,840 today. We&amp;#39;re going to launch chatbt3 00:00:09,840 --> 00:00:11,519 agent. But before jumping into that, I&amp;#39;d4 00…

內網后滲透攻擊過程(實驗環境)--4、權限維持(2)

用途限制聲明&#xff0c;本文僅用于網絡安全技術研究、教育與知識分享。文中涉及的滲透測試方法與工具&#xff0c;嚴禁用于未經授權的網絡攻擊、數據竊取或任何違法活動。任何因不當使用本文內容導致的法律后果&#xff0c;作者及發布平臺不承擔任何責任。滲透測試涉及復雜技…

CentOS 9 配置國內 YUM 源

1.備份 sudo mv /etc/yum.repos.d/centos.repo /etc/yum.repos.d/centos.repo.backup sudo mv /etc/yum.repos.d/centos-addons.repo /etc/yum.repos.d/centos-addons.repo.backup2.創建新文件 vi /etc/yum.repos.d/centos.repo[baseos] nameCentOS Stream $releasever - BaseO…

【算法】遞歸、搜索與回溯算法入門

文章目錄遞歸什么是遞歸為什么會用到遞歸如何理解遞歸如何寫好一個遞歸搜索 vs 深度優先遍歷 vs 深度優先搜索 vs 寬度&#xff08;廣度&#xff09;優先遍歷 vs 寬度&#xff08;廣度&#xff09;優先搜索 vs 暴搜深度優先遍歷 vs 深度優先搜索&#xff08;dfs&#xff09;寬度…

借助Aspose.HTML控件,在 Python 中將 SVG 轉換為 PDF

您可能會發現許多解決方案都提供以編程方式將SVG轉換為PDF 的功能。但這篇博文將介紹一個功能強大的 SDK&#xff0c;供 Python 開發人員自動化文件轉換和操作。本指南將重點介紹通過 .NET 實現 Python 的 Aspose.HTML。此外&#xff0c;我們將逐步講解相關步驟和代碼片段&…

高級06-Java網絡編程:從Socket到HTTP

引言&#xff1a;Java 網絡編程的重要性 隨著互聯網技術的飛速發展&#xff0c;網絡編程已成為現代軟件開發中不可或缺的一部分。Java 作為一種廣泛應用于企業級開發和分布式系統的編程語言&#xff0c;提供了強大的網絡通信支持。從底層的 Socket 編程到高層的 HTTP 協議處理&…

STM32的藍牙通訊(HAL庫)

藍牙基礎知識&#xff08;了解即可&#xff09;&#xff1a;1.是一種利用低功率無線電&#xff0c;支持設備短距離通信的無線電技術&#xff0c;能在包括移動電話、PDAQ、無線耳機、筆記本電腦、相關外設等眾多設備之間進行無線信息交換&#xff0c;藍牙工作在全球通用的2.4 GH…

方案B,version1

我們重新設計起步階段的步驟,目標是:通過運行PowerShell腳本和配置GitHub Actions工作流(deploy.yml)來實現自動化部署。 要求: 用私有倉庫(my-website-source-SSH)存儲源碼。 通過GitHub Actions自動構建(這里只是簡單的Hello World,所以構建步驟可以簡化為復制文件…

Linux --- 進程

一、進程概念 在 Linux 系統中&#xff0c;??進程&#xff08;Process&#xff09;?? 是程序執行的動態實例&#xff0c;是操作系統進行資源分配和調度的基本單位。 ??1. 程序 vs 進程?? ??程序&#xff08;Program&#xff09;??&#xff1a;是靜態的代碼集合&…

Cgroup 控制組學習(三)在容器中使用 CGroups

一、CGroups 關于mememory的限制操作 cgroup關于cpu操作 關于memeory cgroup的幾個要點 ① memeory限額類 1、memory.limit_bytes&#xff1a;硬限制--> 限制最大內存使用量&#xff0c;單位有k、m、g三種&#xff0c;填-1則代表無限制,默認是字節2、memory.soft_limi…

SpringBoot面試基礎知識

SpringBoot 是面試中后端開發崗位的高頻考點&#xff0c;以下是核心考點整理&#xff1a;1. SpringBoot 基礎概念- 定義&#xff1a;SpringBoot 是 Spring 框架的簡化版&#xff0c;通過“自動配置”“起步依賴”等特性&#xff0c;簡化 Spring 應用的搭建和開發&#xff0c;減…

Java面試全方位解析:從基礎到AI的技術交鋒

Java面試全方位解析&#xff1a;從基礎到AI的技術交鋒 面試場景&#xff1a;互聯網大廠Java工程師崗位面試 面試官&#xff1a;您好&#xff0c;我是今天的面試官&#xff0c;接下來我們將進行三輪技術面試。 謝飛機&#xff1a;您好您好&#xff01;我是謝飛機&#xff0c;特別…

Web Worker:解鎖瀏覽器多線程,提升前端性能與體驗

目錄 一、Web Worker 是什么&#xff1f; 核心特性 類型 二、為什么需要 Web Worker&#xff1f;(單線程的痛點) 三、Web Worker 的典型使用場景 四、一個簡單的代碼示例 (專用 Worker) 五、使用 Web Worker 的注意事項 六、總結 一、Web Worker 是什么&#xff1f; 簡…

LabVIEW命令行調用與傳參功能

該功能一方面借助 Formatinto String 構建命令行字符串&#xff0c;實現LabVIEW 環境下命令行調用 VI 并傳參&#xff1b;另一方面&#xff0c;針對 Mac 平臺&#xff0c;通過解析應用 Info.plist 文件&#xff0c;處理 LabVIEW 可執行文件路徑&#xff0c;完善跨平臺命令行調用…