成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一篇解讀組合總和III

開發 前端
找出所有相加之和為 n 的 k 個數的組合。組合中只允許含有 1 - 9 的正整數,并且每種組合中不存在重復的數字。

[[424324]]

組合總和III

力扣題目鏈接:https://leetcode-cn.com/problems/combination-sum-iii/

找出所有相加之和為 n 的 k 個數的組合。組合中只允許含有 1 - 9 的正整數,并且每種組合中不存在重復的數字。

說明:

  • 所有數字都是正整數。
  • 解集不能包含重復的組合。

示例 1: 輸入: k = 3, n = 7 輸出: [[1,2,4]]

示例 2: 輸入: k = 3, n = 9 輸出: [[1,2,6], [1,3,5], [2,3,4]]

思路

本題就是在[1,2,3,4,5,6,7,8,9]這個集合中找到和為n的k個數的組合。

相對于77. 組合,無非就是多了一個限制,本題是要找到和為n的k個數的組合,而整個集合已經是固定的了[1,...,9]。

想到這一點了,做過77. 組合之后,本題是簡單一些了。

本題k相當于了樹的深度,9(因為整個集合就是9個數)就是樹的寬度。

例如 k = 2,n = 4的話,就是在集合[1,2,3,4,5,6,7,8,9]中求 k(個數) = 2, n(和) = 4的組合。

選取過程如圖:

組合總和III

圖中,可以看出,只有最后取到集合(1,3)和為4 符合條件。

回溯三部曲

確定遞歸函數參數

和77. 組合一樣,依然需要一維數組path來存放符合條件的結果,二維數組result來存放結果集。

這里我依然定義path 和 result為全局變量。

至于為什么取名為path?從上面樹形結構中,可以看出,結果其實就是一條根節點到葉子節點的路徑。

  1. vector<vector<int>> result; // 存放結果集 
  2. vector<int> path; // 符合條件的結果 

接下來還需要如下參數:

  • targetSum(int)目標和,也就是題目中的n。
  • k(int)就是題目中要求k個數的集合。
  • sum(int)為已經收集的元素的總和,也就是path里元素的總和。
  • startIndex(int)為下一層for循環搜索的起始位置。

所以代碼如下:

  1. vector<vector<int>> result; 
  2. vector<int> path; 
  3. void backtracking(int targetSum, int k, int sumint startIndex) 

其實這里sum這個參數也可以省略,每次targetSum減去選取的元素數值,然后判斷如果targetSum為0了,說明收集到符合條件的結果了,我這里為了直觀便于理解,還是加一個sum參數。

還要強調一下,回溯法中遞歸函數參數很難一次性確定下來,一般先寫邏輯,需要啥參數了,填什么參數。

  • 確定終止條件

什么時候終止呢?

在上面已經說了,k其實就已經限制樹的深度,因為就取k個元素,樹再往下深了沒有意義。

所以如果path.size() 和 k相等了,就終止。

如果此時path里收集到的元素和(sum) 和targetSum(就是題目描述的n)相同了,就用result收集當前的結果。

所以 ,終止代碼如下:

  1. if (path.size() == k) { 
  2.     if (sum == targetSum) result.push_back(path); 
  3.     return; // 如果path.size() == k 但sum != targetSum 直接返回 
  • 單層搜索過程

本題和77. 組合區別之一就是集合固定的就是9個數[1,...,9],所以for循環固定i<=9

如圖:

處理過程就是 path收集每次選取的元素,相當于樹型結構里的邊,sum來統計path里元素的總和。

代碼如下:

  1. for (int i = startIndex; i <= 9; i++) { 
  2.     sum += i; 
  3.     path.push_back(i); 
  4.     backtracking(targetSum, k, sum, i + 1); // 注意i+1調整startIndex 
  5.     sum -= i; // 回溯 
  6.     path.pop_back(); // 回溯 

別忘了處理過程 和 回溯過程是一一對應的,處理有加,回溯就要有減!

參照關于回溯算法,你該了解這些!中的模板,不難寫出如下C++代碼:

  1. class Solution { 
  2. private: 
  3.     vector<vector<int>> result; // 存放結果集 
  4.     vector<int> path; // 符合條件的結果 
  5.     // targetSum:目標和,也就是題目中的n。 
  6.     // k:題目中要求k個數的集合。 
  7.     // sum:已經收集的元素的總和,也就是path里元素的總和。 
  8.     // startIndex:下一層for循環搜索的起始位置。 
  9.     void backtracking(int targetSum, int k, int sumint startIndex) { 
  10.         if (path.size() == k) { 
  11.             if (sum == targetSum) result.push_back(path); 
  12.             return; // 如果path.size() == k 但sum != targetSum 直接返回 
  13.         } 
  14.         for (int i = startIndex; i <= 9; i++) { 
  15.             sum += i; // 處理 
  16.             path.push_back(i); // 處理 
  17.             backtracking(targetSum, k, sum, i + 1); // 注意i+1調整startIndex 
  18.             sum -= i; // 回溯 
  19.             path.pop_back(); // 回溯 
  20.         } 
  21.     } 
  22.  
  23. public
  24.     vector<vector<int>> combinationSum3(int k, int n) { 
  25.         result.clear(); // 可以不加 
  26.         path.clear();   // 可以不加 
  27.         backtracking(n, k, 0, 1); 
  28.         return result; 
  29.     } 
  30. }; 

剪枝

這道題目,剪枝操作其實是很容易想到了,想必大家看上面的樹形圖的時候已經想到了。

如圖:

已選元素總和如果已經大于n(圖中數值為4)了,那么往后遍歷就沒有意義了,直接剪掉。

那么剪枝的地方一定是在遞歸終止的地方剪,剪枝代碼如下:

  1. if (sum > targetSum) { // 剪枝操作 
  2.     return

和77.組合 一樣,for循環的范圍也可以剪枝,i <= 9 - (k - path.size()) + 1就可以了。

最后C++代碼如下:

  1. class Solution { 
  2. private: 
  3.     vector<vector<int>> result; // 存放結果集 
  4.     vector<int> path; // 符合條件的結果 
  5.     void backtracking(int targetSum, int k, int sumint startIndex) { 
  6.         if (sum > targetSum) { // 剪枝操作 
  7.             return; // 如果path.size() == k 但sum != targetSum 直接返回 
  8.         } 
  9.         if (path.size() == k) { 
  10.             if (sum == targetSum) result.push_back(path); 
  11.             return
  12.         } 
  13.         for (int i = startIndex; i <= 9 - (k - path.size()) + 1; i++) { // 剪枝 
  14.             sum += i; // 處理 
  15.             path.push_back(i); // 處理 
  16.             backtracking(targetSum, k, sum, i + 1); // 注意i+1調整startIndex 
  17.             sum -= i; // 回溯 
  18.             path.pop_back(); // 回溯 
  19.         } 
  20.     } 
  21.  
  22. public
  23.     vector<vector<int>> combinationSum3(int k, int n) { 
  24.         result.clear(); // 可以不加 
  25.         path.clear();   // 可以不加 
  26.         backtracking(n, k, 0, 1); 
  27.         return result; 
  28.     } 
  29. }; 

總結

開篇就介紹了本題與77.組合的區別,相對來說加了元素總和的限制,如果做完77.組合再做本題在合適不過。

分析完區別,依然把問題抽象為樹形結構,按照回溯三部曲進行講解,最后給出剪枝的優化。 

相信做完本題,大家對組合問題應該有初步了解了。

 

責任編輯:武曉燕 來源: 代碼隨想錄
相關推薦

2021-09-14 07:26:26

組合問題循環

2022-06-15 08:17:13

OA系統數據

2020-11-22 08:32:29

人工智能AI

2015-08-13 11:25:51

大數據

2021-07-12 06:11:14

SkyWalking 儀表板UI篇

2022-02-07 11:01:23

ZooKeeper

2021-05-20 06:57:16

RabbitMQ開源消息

2023-04-20 08:00:00

ES搜索引擎MySQL

2022-10-26 07:39:36

MVCC數據庫RR

2022-12-19 08:14:30

注解開發配置

2022-01-02 08:43:46

Python

2020-03-20 08:30:56

手機移動端適配

2021-07-02 08:51:29

源碼參數Thread

2021-09-28 08:59:30

復原IP地址

2023-07-31 07:48:43

Java內存虛擬機

2021-10-14 10:22:19

逃逸JVM性能

2022-04-12 08:30:52

回調函數代碼調試

2021-07-16 22:43:10

Go并發Golang

2021-09-15 19:05:16

數據開源項目

2021-05-27 05:24:21

云計算數據網絡
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美大片黄 | 欧美精品一区二区三区在线 | av黄色免费在线观看 | 看真人视频一级毛片 | 亚洲欧美一区在线 | 国产精品久久 | 国产精品久久久久久婷婷天堂 | 一区二区三区国产 | 自拍偷拍第一页 | 在线成人 | 91久久精品国产91久久性色tv | 久久精品小视频 | caoporn国产 | 久久久免费| 欧洲一级黄 | 午夜精品久久久久久久99黑人 | 亚洲精品一区二区三区蜜桃久 | 日韩无| 国产一区二区av | 成人在线小视频 | 超碰av人人| 草久免费视频 | 亚洲精品日韩一区二区电影 | 久久久久国色av免费观看性色 | 色综合久久久 | 国产激情视频在线 | 成人在线免费视频 | 欧美精品福利视频 | 欧美日韩视频 | 99爱在线视频 | 国产亚洲精品综合一区 | 视频一二三区 | 鸳鸯谱在线观看高清 | 午夜爽爽男女免费观看hd | 99热国产精品 | av黄色网| 激情小说综合网 | 91精品国产一区二区三区 | 91精品国产91久久综合桃花 | 精精精精xxxx免费视频 | 日本一二三区高清 |