【LeetCode 熱題 100】46. 全排列——回溯

Problem: 46. 全排列

文章目錄

  • 整體思路
  • 完整代碼
  • 時空復雜度
    • 時間復雜度:O(N * N!)
    • 空間復雜度:O(N)

整體思路

這段代碼旨在解決一個經典的組合數學問題:全排列 (Permutations)。給定一個不含重復數字的數組 nums,它需要找出其所有可能的全排列,并返回一個包含這些排列的列表。

該算法采用的核心方法是 回溯法(Backtracking),這是一種通過 深度優先搜索(DFS) 來系統地探索所有可能解的搜索策略。

算法的整體思路可以分解為以下步驟:

  1. 逐位構建排列

    • 算法將生成一個排列的過程看作是逐個“填空”的過程。它定義了一個 dfs(i, ...) 函數,其核心任務是確定排列中第 i 個位置應該填入哪個數字。
  2. 狀態維護

    • 為了輔助構建過程,算法使用了兩個關鍵的數據結構:
      • List<Integer> path:用于存儲當前正在構建的排列。
      • boolean[] onPath:一個與原數組 nums 等長的布爾數組,用作“訪問標記”。onPath[j] = true 表示 nums[j] 這個數字已經被放入了當前的 path 中,不能再被使用。
  3. 遞歸與回溯的核心邏輯

    • dfs 函數從第 0 位開始 (i=0)。在為第 i 位選擇數字時,它會遍歷整個原始數組 nums
    • 對于 nums 中的每一個數字 nums[j],它會檢查該數字是否已被使用(if (!onPath[j]))。
    • 選擇 (Choose):如果 nums[j] 未被使用,就做出選擇:
      a. 將 nums[j] 放入當前排列的第 i 位:path.set(i, nums[j])
      b. 將 nums[j] 標記為已使用:onPath[j] = true
    • 探索 (Explore):做出選擇后,遞歸地調用 dfs(i + 1, ...),去解決下一個子問題——填充第 i+1 位。
    • 撤銷選擇 (Unchoose / Backtrack):當對 i+1 位的探索(即 dfs(i + 1, ...) 調用)返回后,必須撤銷剛才的選擇。這是回溯法的精髓。
      a. 將 nums[j] 標記為未使用:onPath[j] = false
      b. 這樣,在下一次循環中,nums[j] 就可以被用來填充其他位置,從而形成不同的排列。
  4. 遞歸終止條件

    • i 的值等于數組長度 n 時(if (i == n)),意味著排列的所有 n 個位置都已經被成功填滿。
    • 此時,一個完整的排列就構建好了(存儲在 path 中)。
    • path 的一個深拷貝new ArrayList<>(path))添加到最終的結果列表 ans 中。必須使用拷貝,因為 path 本身會在回溯過程中被不斷修改。

通過這個“選擇-探索-撤銷”的循環,算法能夠不重不漏地遍歷所有可能的排列組合。

完整代碼

class Solution {/*** 計算給定數組的全排列。* @param nums 不含重復數字的整數數組* @return 包含所有全排列的列表*/public List<List<Integer>> permute(int[] nums) {int n = nums.length;// ans: 最終的結果列表List<List<Integer>> ans = new ArrayList<>();// path: 用于存儲當前正在構建的單個排列路徑// Arrays.asList(new Integer[n]) 創建一個固定大小的、由null填充的List,便于后續使用 set 方法List<Integer> path = Arrays.asList(new Integer[n]);// onPath: 標記數組,onPath[j]為true表示nums[j]已在當前path中boolean[] onPath = new boolean[n];// 從第 0 個位置開始進行深度優先搜索dfs(0, nums, ans, path, onPath);return ans;}/*** 深度優先搜索(回溯)輔助函數。* @param i 當前需要填充的排列位置的索引* @param nums 原始輸入數組* @param ans 結果列表* @param path 當前構建的排列* @param onPath 標記數組*/private void dfs(int i, int[] nums, List<List<Integer>> ans, List<Integer> path, boolean[] onPath) {int n = nums.length;// 遞歸終止條件:當 i 等于 n 時,說明所有位置都已填滿,一個完整的排列已生成if (i == n) {// 將當前路徑的一個深拷貝加入到結果列表中// 必須是深拷貝,因為 path 會在回溯過程中被修改ans.add(new ArrayList<>(path));return; // 結束當前遞歸分支}// 遍歷所有可用的數字,嘗試將其放入第 i 個位置for (int j = 0; j < n; j++) {// 如果 nums[j] 還未在當前路徑中使用過if (!onPath[j]) {// 選擇:將 nums[j] 放入第 i 個位置path.set(i, nums[j]);// 標記 nums[j] 為已使用onPath[j] = true;// 探索:遞歸地去填充下一個位置 (i + 1)dfs(i + 1, nums, ans, path, onPath);// 撤銷選擇(回溯):將 nums[j] 標記為未使用,// 這樣它就可以在其他分支中被用于其他位置。這是回溯法的核心。onPath[j] = false;}}}
}

時空復雜度

時間復雜度:O(N * N!)

  1. 排列數量:對于一個包含 N 個不同元素的集合,其全排列的數量是 N! (N的階乘)。
  2. 構建每個排列的成本
    • 算法的搜索過程可以看作是在一棵“排列樹”上進行DFS。這棵樹有 N! 個葉子節點,每個葉子節點代表一個完整的排列。
    • 從根節點到任意一個葉子節點的路徑長度為 N
    • 當到達一個葉子節點時(即 i == n),需要執行 new ArrayList<>(path) 操作,這是一個 O(N) 的操作,用于復制當前排列。
  3. 綜合分析
    • 總的時間復雜度約等于 (葉子節點數量 * 到達葉子節點的成本) + (非葉子節點的計算成本)。
    • 非葉子節點的總數也與 N! 相關。
    • 一個更精確的視角是,總共有 N! 個排列,每個排列的生成和復制都需要 O(N) 的時間。因此,總時間復雜度為 O(N * N!)

空間復雜度:O(N)

  1. 主要存儲開銷:我們分析的是額外輔助空間,不包括存儲最終結果的 ans 列表(否則空間將是 O(N * N!))。
    • List<Integer> path: 用于存儲當前路徑,其大小為 N。空間復雜度為 O(N)
    • boolean[] onPath: 標記數組,其大小為 N。空間復雜度為 O(N)
    • 遞歸調用棧dfs 函數的最大遞歸深度為 N(從 i=0i=n)。因此,遞歸棧所占用的空間為 O(N)

綜合分析
算法所需的額外輔助空間由 pathonPath 和遞歸棧深度共同決定。它們都是 O(N) 級別的。因此,總的輔助空間復雜度為 O(N)

參考靈神

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

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

相關文章

AXI接口學習

amba總線的發展axi協議是兩個接口之間的點對點的協議&#xff0c;主要是有5個通道。主機在寫地址&#xff08;AW&#xff09;通道上發送地址&#xff0c;并在寫數據&#xff08;W&#xff09;通道上將數據傳輸到從機。從機將接收到的數據寫入指定地址空間。從機完成寫操作&…

Validation - Spring Boot項目中參數檢驗的利器

Validation - Spring Boot項目中參數檢驗的利器 什么是Validation Sping Boot官方原文&#xff1a;When it comes to validating user input, Spring Boot provides strong support for this common, yet critical, task straight out of the box.Although Spring Boot support…

云服務器VS虛擬主機:如何抉擇?

開篇引入在當今數字化浪潮中&#xff0c;無論是個人站長想要搭建獨具風格的博客&#xff0c;展示自己的生活感悟與專業見解&#xff1b;還是中小企業期望構建官方網站&#xff0c;拓展線上業務版圖&#xff0c;提升品牌知名度&#xff1b;亦或是大型互聯網企業籌備高并發的電商…

不同相機CMOS噪點對熒光計算的影響

摘要&#xff1a;熒光成像是生物醫學、材料科學等領域的重要研究手段&#xff0c;其成像質量高度依賴傳感器噪聲特性。本文系統分析CMOS傳感器噪聲類型及其對熒光信號計算的影響機制&#xff0c;結合實驗數據探討不同CMOS架構的噪聲表現差異&#xff0c;提出針對性優化策略。研…

docker 常見命令使用記錄

1. swarm 集群 1. 集群創建 # 創建集群管理節點&#xff0c; --advertise-addr 指定節點管理通信地址&#xff0c;--data-path-addr 指定容器通信地址 docker swarm init --advertise-addr 1.14.138.35 --data-path-addr 1.14.138.35# --advertise-addr 指明當前work節點的…

KRaft 角色狀態設計模式:從狀態理解 Raft

這些狀態類是 Raft 協議行為的核心載體。它們包含轉移邏輯 和 節點在特定狀態下的所有行為和數據。QuorumState它是 KRaft 客戶端實現中狀態管理的核心&#xff0c;扮演著“狀態機上下文&#xff08;Context&#xff09;”和“狀態轉換協調者”的關鍵角色。QuorumState 是整個 …

Linux的磁盤存儲管理實操——(上)

一、Linux的設備文件分類 Linux的設備文件分類1、在Linux系統中設備文件是用來與外接交互的接口&#xff0c;它將內核中的硬件設備與文件系統關聯起來&#xff0c;讓用戶可以像操作普通文件一樣來操作硬件設備&#xff0c;同時也為開發者提供了方便而強大的應用程序接口。 2、L…

內核bpf的實現原理

bpftrace能幫我們干什么&#xff1f;1、統計 tcp連接的生命時長、2、統計mysql執行一條sql語句的時間3、統計redis執行命令的時間、 4、對文件進行一次讀或者寫的時間。 常用命令&#xff1a; bpftrace -e Begin { printf("hello\n"); } bpftrace -l *enter_accep…

前端npm配置Nexus為基礎倉庫

步驟&#xff1a; 一、Nexus倉庫配置 新增npm倉庫,具體詳解見 Nexus私有倉庫配置&#xff0c;解釋 注&#xff1a;Nexus的版本需要至少3.38以上&#xff0c;不然會出現npm install 時npm的審計功能報錯&#xff0c;導致install失敗。雖然在3.38以后不會報400錯誤&#xff0c…

數據結構 之 【排序】(直接插入排序、希爾排序)

目錄 1.直接插入排序 1.1直接插入排序的思想 1.2直接插入排序的代碼邏輯&#xff1a; 1.3 直接插入排序圖解 1.4單趟排序代碼(單個元素的排序邏輯) 1.5完整排序代碼 1.6直接插入排序的時間復雜度與空間復雜度 1.7直接插入排序的優勢 2.希爾排序(縮小增量排序) 2.1…

Laravel 后臺登錄 403 Forbidden 錯誤深度解決方案-優雅草卓伊凡|泡泡龍

Laravel 后臺登錄 403 Forbidden 錯誤深度解決方案-優雅草卓伊凡|泡泡龍一頓操作猛如虎&#xff0c;一看結果250&#xff0c;必須記錄&#xff0c;必須記錄&#xff0c;&#xff01;今天弄了很久關于我們2023年的產品系統蜻蜓T會議系統專業版&#xff0c;然后終于搞好了密碼也重…

Newline全場景方案閃耀2025中國智慧生活大會

7月15日 — 16日&#xff0c;由中國電子視像行業協會等權威機構指導的2025 CIC中國智慧生活大會在京召開。Newline作為視像協會PID分會副會長單位攜全場景智慧辦公解決方案亮相&#xff0c;首席營銷官李宇鵬受邀出席領袖圓桌環節&#xff0c;與騰訊云、京東方、創維、TCL、小猿…

Edge瀏覽器地址欄默認搜索引擎設置指南

前言 Microsoft Edge 瀏覽器允許用戶自定義地址欄默認搜索引擎&#xff0c;只是設置入口隱藏比較深&#xff0c;以版本 137.0.3296.83 (正式版本) (64 位)為例詳細記錄設置地址欄默認搜索引擎步驟&#xff1a; Edge 設置默認搜索引擎步驟 通過設置界面修改 打開Edge設置&#x…

Python eval函數詳解 - 用法、風險與安全替代方案

Python eval函數詳解 - 用法、風險與安全替代方案在Python中&#xff0c;eval() 是一個內置函數&#xff0c;用于解析并執行傳入的字符串形式的表達式。它能夠將字符串動態地轉換為有效的Python代碼并運行。雖然 eval() 功能強大&#xff0c;但其使用也伴隨著潛在的安全風險。本…

Webpack5 新特性與詳細配置指南

一、Webpack5 新特性 內置 Asset Modules&#xff08;資源模塊&#xff09; 替代 file-loader、url-loader、raw-loader 等&#xff0c;統一資源處理方式。四種類型&#xff1a;asset/resource&#xff1a;導出文件 URL&#xff08;等同 file-loader&#xff09;。asset/inli…

籠子在尋找一只鳥:解讀生活的隱形陷阱

想象一個閃閃發光的籠子&#xff0c;敞開著門&#xff0c;在世界中游蕩&#xff0c;尋找一只鳥兒。這畫面是不是有點奇怪&#xff1f;這是卡夫卡的格言“一個籠子在尋找一只鳥”帶給我們的奇思妙想。通常&#xff0c;鳥兒自由翱翔&#xff0c;籠子靜靜等待&#xff0c;但卡夫卡…

低空經濟展 | 約克科技攜小型化測試設備亮相2025深圳eVTOL展

全球低空經濟與eVTOL產業盛會——2025深圳eVTOL展&#xff0c;將于2025年9月23日至25日在深圳坪山燕子湖國際會展中心盛大啟幕&#xff01; 本屆展會以“低空經濟eVTOL航空應急救援商載大型無人運輸機”為核心&#xff0c;預計匯聚200位發言嘉賓、500家頂尖展商及15,000位專業觀…

數學專業轉行做大數據容易嗎?需要補什么?

高考志愿選擇數學專業是一個面向未來的決定。數學作為基礎學科&#xff0c;其嚴謹的邏輯訓練和抽象思維能力培養&#xff0c;為后續專業發展提供了廣泛的可能性。在數字化時代背景下&#xff0c;數學專業畢業生在數據科學、人工智能等領域的競爭優勢明顯。大學期間推薦考CDA數據…

物聯網系統中-設備管理定義方法

物聯網系統中的設備管理是指對聯網物理設備進行全生命周期監控、配置、維護和優化的系統性過程。它涵蓋了從設備接入到退役的各個環節&#xff0c;是物聯網平臺的核心能力&#xff0c;確保設備安全、穩定、高效地運行并產生價值。 以下是設備管理的詳細定義與核心組成部分&…

java和ptyhon對比

&#x1f4dd; ?1. 語言特性對比??維度??Java??Python??語法風格?靜態類型&#xff0c;需顯式聲明變量類型&#xff1b;代碼冗長&#xff08;需分號、大括號&#xff09;動態類型&#xff0c;變量類型自動推斷&#xff1b;簡潔&#xff08;縮進代替大括號&#xff0c…