代碼隨想錄-Day25

216.組合總和III

找出所有相加之和為 n 的 k 個數的組合,且滿足下列條件:

只使用數字1到9
每個數字 最多使用一次
返回 所有可能的有效組合的列表 。該列表不能包含相同的組合兩次,組合可以以任何順序返回。

示例 1:

輸入: k = 3, n = 7
輸出: [[1,2,4]]
解釋:
1 + 2 + 4 = 7
沒有其他符合的組合了。
示例 2:

輸入: k = 3, n = 9
輸出: [[1,2,6], [1,3,5], [2,3,4]]
解釋:
1 + 2 + 6 = 9
1 + 3 + 5 = 9
2 + 3 + 4 = 9
沒有其他符合的組合了。

方法一:二進制(子集)枚舉

class Solution {List<Integer> temp = new ArrayList<Integer>();List<List<Integer>> ans = new ArrayList<List<Integer>>();public List<List<Integer>> combinationSum3(int k, int n) {for (int mask = 0; mask < (1 << 9); ++mask) {if (check(mask, k, n)) {ans.add(new ArrayList<Integer>(temp));}}return ans;}public boolean check(int mask, int k, int n) {temp.clear();for (int i = 0; i < 9; ++i) {if (((1 << i) & mask) != 0) {temp.add(i + 1);}}if (temp.size() != k) {return false;}int sum = 0;for (int num : temp) {sum += num;}return sum == n;}
}

這段代碼也是定義了一個名為 Solution 的類,但這次是解決一個略有不同的組合問題——找出所有和為 n 且正好由 k 個數字組成的序列,這些數字取自 1 到 9 之間的整數,每個數字最多使用一次。這是一種使用位操作優化的組合求解方法。

成員變量

與之前一樣,定義了兩個成員變量:

  • temp:一個 List<Integer>,用于臨時存儲當前組合。
  • ans:一個 List<List<Integer>>,用于存儲所有滿足條件的組合。

方法

combinationSum3(int k, int n)
  • 功能:主方法,接收目標和 n 和組合長度 k 作為參數,返回所有符合條件的組合。
  • 過程:通過遍歷從 0(1 << 9)(即 2^9)之間所有可能的掩碼值(mask),利用 check 方法驗證每個掩碼是否代表一個有效的組合。如果是,則將該組合添加到答案列表 ans 中。
check(int mask, int k, int n)
  • 功能:輔助方法,檢查給定的掩碼 mask 是否代表一個有效的組合,即組合中的數字個數是否為 k 且這些數字之和為 n
  • 參數:除了掩碼 mask 外,還接收組合長度 k 和目標和 n
  • 過程
    • 首先清空 temp,然后遍歷從 0 到 8(代表數字 1 到 9),如果某位在 mask 中被設置(即該位為 1),則將對應的數字(i + 1)添加到 temp 中。
    • 檢查 temp 的大小是否等于 k,如果不等直接返回 false
    • 計算 temp 中所有數字的和,判斷這個和是否等于 n,如果相等返回 true,否則返回 false

這種方法利用位運算高效地枚舉了所有可能的選擇情況,相比于之前的遞歸解法,此方法在某些情況下可以減少遞歸調用的開銷,尤其是在處理較大范圍的組合問題時更為高效。

方法二:組合枚舉

class Solution {List<Integer> temp = new ArrayList<Integer>();List<List<Integer>> ans = new ArrayList<List<Integer>>();public List<List<Integer>> combinationSum3(int k, int n) {dfs(1, 9, k, n);return ans;}public void dfs(int cur, int n, int k, int sum) {if (temp.size() + (n - cur + 1) < k || temp.size() > k) {return;}if (temp.size() == k) {int tempSum = 0;for (int num : temp) {tempSum += num;}if (tempSum == sum) {ans.add(new ArrayList<Integer>(temp));return;}}temp.add(cur);dfs(cur + 1, n, k, sum);temp.remove(temp.size() - 1);dfs(cur + 1, n, k, sum);}
}

這段代碼是用Java編寫的,它定義了一個名為Solution的類,該類包含方法來找出所有組合之和等于特定目標值n的k個不同正整數的組合,且這些整數都在1到n之間(這里限制為1到9,因為題目隱含了這個范圍,如dfs函數的第二個參數所示)。這是一個經典的回溯算法應用實例。

方法說明

  • combinationSum3(int k, int n): 這是主要的方法,接收兩個整數參數kn,分別代表需要找到的組合的元素個數以及這些元素的和。它初始化調用深度優先搜索(dfs)方法來尋找所有符合條件的組合,并返回存儲這些組合的二維列表ans

  • dfs(int cur, int n, int k, int sum): 這是一個遞歸輔助函數,用于執行深度優先搜索。

    • cur表示當前考慮加入組合的起始數字(遞增的基礎)。
    • n是可選數字的最大值,在這個上下文中固定為9。
    • ksum與主方法接收的參數相同,分別代表需要的組合長度和目標和。

    該函數的工作原理如下:

    • 剪枝:首先判斷當前路徑是否有可能達到解。如果當前臨時組合的長度加上剩余數字的數量小于k,或者已經超過k,直接返回,無需繼續搜索。
    • 結束條件:當臨時組合的長度等于k時,檢查這些數字的和是否等于目標sum。如果是,則將當前組合添加到答案列表中,并返回。
    • 遞歸搜索:嘗試選擇當前數字cur,將其加入臨時組合temp,然后遞歸調用dfs函數嘗試下一個數字。之后通過temp.remove(temp.size() - 1)撤銷選擇(回溯),再嘗試不包含當前數字的情況。

示例解析

假設調用combinationSum3(3, 7),該函數將尋找所有和為7且包含3個數字的組合,這些數字來自1到9。可能的結果包括[1, 2, 4]。此過程通過深度優先搜索逐層嘗試每一種可能的組合,并通過剪枝策略減少無效的搜索路徑,從而高效地找到所有解。

方法三:回溯


// 上面剪枝 i <= 9 - (k - path.size()) + 1; 如果還是不清楚
// 也可以改為 if (path.size() > k) return; 執行效率上是一樣的
class Solution {LinkedList<Integer> path = new LinkedList<>();List<List<Integer>> ans = new ArrayList<>();public List<List<Integer>> combinationSum3(int k, int n) {build(k, n, 1, 0);return ans;}private void build(int k, int n, int startIndex, int sum) {if (sum > n) return;if (path.size() > k) return;if (sum == n && path.size() == k) {ans.add(new ArrayList<>(path));return;}for(int i = startIndex; i <= 9; i++) {path.add(i);sum += i;build(k, n, i + 1, sum);sum -= i;path.removeLast();}}
}

這段代碼同樣定義了一個名為 Solution 的類,用于解決找出所有和為 n 且包含恰好 k 個不同數字的組合的問題,其中數字選擇范圍限定在 1 到 9 之間。與之前版本相比,這段代碼采用了一些小的改動和優化,使用了 LinkedList 作為路徑的存儲結構,以更直觀地展示組合構建過程,并在剪枝策略上做了調整。下面是詳細的解析:

類成員變量

  • LinkedList<Integer> path:用于保存當前搜索路徑上的數字組合。
  • List<List<Integer>> ans:用于存儲所有滿足條件的組合。

主方法 combinationSum3(int k, int n)

  • 功能:接收目標和 n 和組合長度 k 作為參數,調用 build 方法生成所有符合條件的組合,最后返回所有組合的列表 ans

輔助方法 build(int k, int n, int startIndex, int sum)

  • 功能:遞歸構建組合。接收當前需要的組合長度 k、目標和 n、搜索起始數字 startIndex 以及當前路徑和 sum 作為參數。
  • 剪枝條件
    • 如果 sum > n,說明當前路徑的和已經超過了目標和,直接返回。
    • 如果 path.size() > k,說明已經選擇了超過 k 個數字,違反了組合長度的限制,同樣直接返回。
  • 終止條件:當當前路徑的和等于 n 且已選擇的數字個數等于 k 時,將當前路徑添加到結果列表 ans 中。
  • 遞歸構建:從 startIndex 開始遍歷至 9,將當前數字 i 加入路徑,然后遞歸調用 build 方法進行下一層搜索,之后通過 path.removeLast() 回溯,移除剛剛加入的數字,嘗試下一個數字。

剪枝策略說明

原注釋中提到的剪枝條件 i <= 9 - (k - path.size()) + 1; 與代碼中采用的剪枝條件 if (path.size() > k) return; 實現了相同的功能,但后者更直觀易懂。它確保了在任何時候路徑中的數字數量都不會超過所需組合的長度 k,從而避免了無效的搜索,保證了算法效率。兩種剪枝策略在執行效率上基本一致,但后者在代碼可讀性上更優。

17. 電話號碼的字母組合

給定一個僅包含數字 2-9 的字符串,返回所有它能表示的字母組合。答案可以按 任意順序 返回。

給出數字到字母的映射如下(與電話按鍵相同)。注意 1 不對應任何字母。
在這里插入圖片描述

方法一:回溯

class Solution {public List<String> letterCombinations(String digits) {List<String> combinations = new ArrayList<String>();if (digits.length() == 0) {return combinations;}Map<Character, String> phoneMap = new HashMap<Character, String>() {{put('2', "abc");put('3', "def");put('4', "ghi");put('5', "jkl");put('6', "mno");put('7', "pqrs");put('8', "tuv");put('9', "wxyz");}};backtrack(combinations, phoneMap, digits, 0, new StringBuffer());return combinations;}public void backtrack(List<String> combinations, Map<Character, String> phoneMap, String digits, int index, StringBuffer combination) {if (index == digits.length()) {combinations.add(combination.toString());} else {char digit = digits.charAt(index);String letters = phoneMap.get(digit);int lettersCount = letters.length();for (int i = 0; i < lettersCount; i++) {combination.append(letters.charAt(i));backtrack(combinations, phoneMap, digits, index + 1, combination);combination.deleteCharAt(index);}}}
}

這段代碼是一個 Java 程序,實現了一個名為 Solution 的類,該類包含兩個方法:letterCombinationsbacktrack。這個程序的目的是根據給定的電話號碼數字字符串(比如 “23”)生成所有可能的字母組合(“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”)。這里,每個數字映射到多個字母(比如 ‘2’ 映射到 “abc”),這些映射關系已經預定義在 phoneMap 中。

方法說明

  1. letterCombinations(String digits)

    • 功能:這是主要的接口方法,接收一個字符串 digits 作為輸入,返回一個包含所有可能字母組合的列表。
    • 邏輯:首先檢查輸入字符串是否為空,若為空則直接返回一個空列表。接著,定義了一個哈希映射 phoneMap,將數字字符映射到對應的字母字符串。然后,調用 backtrack 方法進行回溯操作生成所有組合,并將結果收集到 combinations 列表中。
  2. backtrack(List combinations, Map<Character, String> phoneMap, String digits, int index, StringBuffer combination)

    • 功能:遞歸回溯方法,用于生成所有可能的字母組合。
    • 參數
      • combinations: 存儲所有組合的列表。
      • phoneMap: 數字到字母的映射。
      • digits: 輸入的數字字符串。
      • index: 當前處理的 digits 中字符的索引。
      • combination: 當前正在構建的組合的緩沖區。
    • 邏輯
      • 基準情況:如果 index 等于 digits 的長度,說明已經完成一個組合,將其添加到 combinations 列表中。
      • 遞歸情況:根據當前 index 所對應的數字從 phoneMap 獲取對應字母串,遍歷這個字母串中的每個字母,將其添加到 combination 中,然后遞歸調用自身處理下一個數字。在遞歸返回后,通過 deleteCharAt 方法回溯,移除剛添加的字母,嘗試下一個字母。

示例解析

例如,當輸入 “23” 時,首先映射 ‘2’ 到 “abc”,然后 ‘3’ 到 “def”。程序會從 “2” 開始,對 “abc” 中的每個字母與 “def” 中的每個字母進行組合,最終生成所有可能的字母組合并返回。

這種方法利用回溯算法有效地減少了重復計算,保證了所有組合都被遍歷且只被生成一次,適合解決此類組合問題。

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

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

相關文章

Python OCR 圖片轉文字進階:讀光OCR之行檢測模型+行識別模型

Python OCR 圖片轉文字進階&#xff1a;讀光OCR之行檢測模型行識別模型 介紹阿里云文字識別OCR&#xff08;讀光OCR&#xff09;前置條件模型1&#xff1a;行檢測模型模型1&#xff1a;行識別模型 代碼&#xff1a;main.py 介紹 什么是OCR&#xff1f; OCR是“Optical Charac…

Leetcode:字符串轉換整數 (atoi)

題目鏈接&#xff1a;8. 字符串轉換整數 (atoi) - 力扣&#xff08;LeetCode&#xff09; 普通版本&#xff08;條件限制&#xff09; class Solution { public:int myAtoi(string s) {int res 0;int i 0;int flag 1;//假設整數為正while(s[i] )//跳過空格{i;}if(s[i] …

德人合科技——@天銳綠盾 | -文檔透明加密系統

天銳綠盾文檔透明加密系統是一種先進的數據安全解決方案&#xff0c;旨在保護企業和組織的敏感信息&#xff0c;防止未經授權的訪問和泄漏。 PC地址&#xff1a; https://isite.baidu.com/site/wjz012xr/2eae091d-1b97-4276-90bc-6757c5dfedee 以下是該系統的一些關鍵特點和功…

[C++11/14新特性] tuple元組介紹

C11 標準新引入了一種類模板&#xff0c;命名為 tuple&#xff08;中文可直譯為元組&#xff09;。tuple 最大的特點是&#xff1a;實例化的對象可以存儲任意數量、任意類型的數據。tuple 的應用場景很廣泛&#xff0c;例如當需要存儲多個不同類型的元素時&#xff0c;可以使用…

3D目標檢測入門:探索OpenPCDet框架

前言 在自動駕駛和機器人視覺這兩個飛速發展的領域中&#xff0c;3D目標檢測技術扮演著核心角色。隨著深度學習技術的突破性進展&#xff0c;3D目標檢測算法的研究和應用正日益深入。OpenPCDet&#xff0c;這個由香港中文大學OpenMMLab實驗室精心打造的開源工具箱&#xff0c;…

加密算法簡述

目錄 1 加密算法的分類 2 對稱加密 3 非對稱加密 4 哈希算法 1 加密算法的分類 數據加密的基本過程是將原本的明文數據依照某種算法進行一定的處理&#xff0c;使之成為一段不可讀的密文&#xff0c;只有通過相應的密鑰與算法進行計算后才可顯示出原文。而這個過程中的算法…

【用Python畫畫】六一兒童節畫愛心

本文收錄于 《Python編程入門》專欄&#xff0c;從零基礎開始&#xff0c;分享一些Python編程基礎知識&#xff0c;歡迎關注&#xff0c;謝謝&#xff01; 文章目錄 一、前言二、代碼示例三、知識點梳理四、總結 一、前言 本文介紹如何使用Python的海龜畫圖工具turtle&#xf…

linux中如和查找端口是否被占用

在Linux系統中&#xff0c;可以使用以下命令來查找特定端口是否被占用&#xff1a; 使用netstat命令&#xff1a; netstat -tuln | grep <port_number>其中&#xff0c;-t表示TCP協議&#xff0c;-u表示UDP協議&#xff0c;-l表示監聽狀態&#xff0c;-n表示顯示端口號…

Docker從安裝開始精通

從虛擬機到容器 1.環境配置的難題 軟件開發最大的麻煩事之一&#xff0c;就是環境配置。用戶計算機的環境都不相同&#xff0c;你怎么知道自家的軟件&#xff0c;能在那些機器跑起來&#xff1f; 用戶必須保證兩件事&#xff1a;操作系統的設置&#xff0c;各種庫和組件的安裝…

堆排序的實現

在上一篇博客中&#xff0c;介紹了堆的實現&#xff0c;現在來介紹一下堆排序。 一.打印有序&#xff1a; 現在先給一個無序的數組&#xff0c;現在我們利用我們實現的堆的功能先完成一下打印排序&#xff1a; 在for循環里是一個建堆的過程&#xff0c;每來一個數據就放入堆中…

c++ map/multimap容器

在C中&#xff0c;std::map 和 std::multimap 是兩種關聯容器&#xff0c;它們包含了可重復的&#xff08;對于 multimap&#xff09;或唯一的&#xff08;對于 map&#xff09;鍵值對。這些容器都根據它們的鍵自動排序&#xff0c;并允許非常快速地根據鍵查找、插入和刪除元素…

監控易監測對象及指標之:深入監測Exchange 2013郵件服務器的關鍵指標

在當今的信息化時代&#xff0c;Exchange 2013郵件服務器因其高效、穩定的特點被廣泛應用于企業通信中。為了確保郵件服務器的持續穩定運行&#xff0c;及時發現并解決潛在問題至關重要。監控易作為一款功能強大的監控工具&#xff0c;為Exchange 2013郵件服務器提供了一系列細…

linux進程的加載和啟動過程分析

我們的源代碼通過預處理,編譯,匯編,鏈接后形成可執行文件,那么當我們在終端敲下指令$ ./a.out argv1 argv2 后,操作系統是怎么將我們的可執行文件加載并運行的呢? 首先知道,計算機的操作系統的啟動程序是寫死在硬件上的,每次計算機上電時,都將自動加載啟動程序,之后…

python第五次作業

1.請實現一個裝飾器&#xff0c;每次調用函數時&#xff0c;將函數名字以及調用此函數的時間點寫入文件中 # 導入datetime模塊&#xff0c;用于獲取當前時間并格式化輸出 import datetime# 定義一個裝飾器工廠函數log_funcName_time&#xff0c;它接受一個參數time def log_fu…

紅外聽力教學考試系統-紅外語音聽力廣播在大學英語四六級聽力考試中應用

紅外聽力教學考試系統-紅外語音聽力廣播在大學英語四六級聽力考試中的應用 由北京海特偉業科技有限公司任洪卓發布于2024年6月1日 紅外語音聽力廣播&#xff08;即紅外聽力教學考試系統&#xff09;在英語四六級聽力考試的應用正日益凸顯出其重要性和優越性。在當前的高等教育…

xcode刪除依賴包package,刪除不必要的依賴項

點擊項目&#xff0c;然后點擊PROJECT項里面的Package DepenDependencies&#xff1a; 選中一個依賴項&#xff0c;然后點擊減號&#xff0c;就可以把依賴項刪除掉了&#xff0c;左側項目下面的Package已經沒有了這個依賴項 TARGET下面的package也要刪除&#xff1a;在這里刪除…

【C++】【Windows】程序加載DLL庫時依次查找哪些目錄

搜索的順序通常如下&#xff1a; 應用程序目錄&#xff1a;首先&#xff0c;系統會在包含可執行文件&#xff08;EXE&#xff09;的目錄中查找DLL。系統目錄&#xff1a;接下來&#xff0c;系統會在Windows系統目錄中查找&#xff0c;比如 C:\Windows\System32。16位系統目錄&…

人工智能與未來工作:未來已來,你準備好了嗎?

1. 引言 隨著人工智能技術的飛速發展&#xff0c;它正在逐漸滲透到我們生活的方方面面&#xff0c;尤其是工作領域。本文將探討人工智能的基本概念&#xff0c;它在不同行業的應用&#xff0c;以及它對未來就業市場和教育體系可能帶來的影響。 2. 人工智能的基本概念 2.1 定…

ESP32S3外設學習筆記

GPIO ESP32的GPIO&#xff08;通用輸入輸出&#xff09;引腳非常靈活&#xff0c;支持多種工作模式。這些模式可以通過編程來配置&#xff0c;以適應不同的應用需求。以下是ESP32 GPIO引腳的主要工作模式&#xff1a; 1. 輸入模式 普通輸入模式&#xff1a;在這種模式下&…

dubbo復習:(14)通過上下文傳遞附加數據

服務調用和響應時&#xff0c;除了請求的方法和返回的響應&#xff0c;還可以通過上下文(Context)傳遞更多的數據(附加數據&#xff09; 一、接口定義 package cn.edu.tju.service;public interface ContextService {String invoke(String param); }二、服務端接口實現&#x…