<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      代碼隨想錄第二十二天 | Leecode 77. 組合、216. 組合總和 III、17. 電話號碼的字母組合

      Leecode 77. 組合

      題目描述

      給定兩個整數(shù) nk,返回范圍 [1, n] 中所有可能的 k個數(shù)的組合。

      你可以按 任何順序 返回答案。

      • 示例 1:

      輸入:n = 4, k = 2
      輸出:

      [
        [2,4],
        [3,4],
        [2,3],
        [1,2],
        [1,3],
        [1,4],
      ]
      
      • 示例 2:

      輸入:n = 1, k = 1
      輸出:[[1]]

      解題思路與代碼展示

      本題要求給出所有滿足組合情況,使用窮舉法逐個嘗試,如果滿足則存入結(jié)果數(shù)組中。但直接寫的過程中會遇到兩個比較難處理的點:

      • 如果每次要求的數(shù)的個數(shù)固定,比如滿足條件的3個數(shù)存入數(shù)組中,那么就只需使用3層for循環(huán)即可,即需要幾個數(shù)就使用幾層for循環(huán)。但題目所給的數(shù)的個數(shù)并不固定,故此時需要使用回溯(遞歸)的方式來進行處理。
      • 此外,還需要確保輸出的數(shù)組沒有重復(fù),即每次搜索過的數(shù)不會進行二次搜索。為了避免重復(fù)查找,可以設(shè)置一個查找的初始值,每次遞歸的時候傳入該值并從這個值開始往后遞歸搜索。

      綜合上面思路,可以寫出代碼如下:

      class Solution {
      public:
          vector<vector<int>> result; // 使用兩個全局變量來存儲結(jié)果值和過程中每一次搜索的結(jié)果
          vector<int> curVec;
      
          void combineHelper(int n, int k, int startindex){ // 遞歸函數(shù)
              if(curVec.size() == k) { // 如果vector當前大小為k,則說明已經(jīng)符合條件,直接push存放入結(jié)果中
                  result.push_back(curVec); 
                  return;
              }
              for(int i = startindex; i <= n-(k-curVec.size()) + 1; i++){ // 使用for循環(huán)遍歷,相當于每次遞歸調(diào)用都有一層for循環(huán);并從startindex開始搜索。其中終止條件中i的上界是剪枝后的結(jié)果,排除了一些不可能的情況,可以加速搜索。
                  curVec.push_back(i);  // 將當前數(shù)存入當前vector中
                  combineHelper(n, k, i+1); // 遞歸調(diào)用
                  curVec.pop_back(); // 回溯退回
              }
          }
      
          vector<vector<int>> combine(int n, int k) {
              combineHelper(n,k,1); // 遞歸調(diào)用輔助函數(shù)
              return result; // 返回結(jié)果
          }
      };
      

      Leecode 216. 組合總和 III

      題目描述

      找出所有相加之和為 nk 個數(shù)的組合,且滿足下列條件:

      • 只使用數(shù)字19
      • 每個數(shù)字 最多使用一次

      返回 所有可能的有效組合的列表 。該列表不能包含相同的組合兩次,組合可以以任何順序返回。

      • 示例 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
      沒有其他符合的組合了。

      • 示例 3:

      輸入: k = 4, n = 1
      輸出: []
      解釋: 不存在有效的組合。
      [1,9]范圍內(nèi)使用4個不同的數(shù)字,我們可以得到的最小和是 1 + 2 + 3 + 4 = 10,因為10 > 1,沒有有效的組合。

      解題思路與代碼展示

      本題和上面一題比較類似,使用相似的方法即可,區(qū)別在于遞歸終止條件中要多考慮如果求和值大于目標的情況,此時不滿足條件,直接退回即可。

      class Solution {
      public:
          vector<int> curVec; // 使用vector和curSum來記錄當前狀態(tài),用于判斷是否滿足條件
          int curSum;
          vector<vector<int>> result; // result用于存放最終結(jié)果
      
          void combHelper(int k, int n, int startNum){
              if(curSum == n && curVec.size() == k){ // 如果數(shù)求和與數(shù)的個數(shù)都恰好滿足條件,則說明此時已經(jīng)滿足
                  result.push_back(curVec); // 將滿足條件的vector存入結(jié)果中
              }
              else if(curSum > n) return; // 如果求和大于目標值,則一定不滿足,此時直接返回即可
              
              for(int i = startNum; i < 10 ; i++){ // 每一位數(shù)都從startNum開始遞歸求解
                  curSum += i; // 更新當前總和,更新存儲的vec向量
                  curVec.push_back(i);
                  combHelper(k,n,i+1); // 遞歸搜索下一個數(shù)
                  curSum -= i; // 回溯,此時要返回上一次的狀態(tài),故需要同時恢復(fù)curSum和curVec
                  curVec.pop_back(); 
              }
          }
      
          vector<vector<int>> combinationSum3(int k, int n) {
              combHelper(k, n, 1);
              return result;
          }
      };
      

      上面代碼關(guān)鍵在于遞歸返回進行回溯時,需要恢復(fù)所有遞歸過程中被修改的變量,在本題中需要同時回復(fù)curSum和curVec。

      Leecode 17. 電話號碼的字母組合

      題目描述

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

      給出數(shù)字到字母的映射如下(與電話按鍵相同)。注意 1 不對應(yīng)任何字母。

      • 示例 1:

      輸入:digits = "23"
      輸出:["ad","ae","af","bd","be","bf","cd","ce","cf"]

      • 示例 2:

      輸入:digits = ""
      輸出:[]

      • 示例 3:

      輸入:digits = "2"
      輸出:["a","b","c"]

      解題思路與代碼展示

      本題思路上不算難,在確定了使用回溯的方法后,只需要根據(jù)每次數(shù)字的不同從相應(yīng)可能得字母字符中依次選取進行回溯遞歸即可。但困難的點在于,總共有字母的按鍵包括2-9總共8個鍵,如果每一個鍵用一個if,同時內(nèi)部使用一個for循環(huán)進行回溯,會導(dǎo)致寫很多沒必要的重復(fù)代碼。為了避免這種情況需要使用一些方法來進行處理。我首先想到的第一種方法是合并前邊2-6個數(shù)字,因為前5個數(shù)每個數(shù)都剛好對應(yīng)3個字母,因此可以使用乘除法和取余運算來進行計算當前字母對應(yīng)哪些字母。但需要注意的是,這個計算過程中需要非常小心int類型與char類型之間的轉(zhuǎn)換,1的ASCII碼并不等于1,中間需要加減一個'0'才能進行轉(zhuǎn)換。

      使用這種方法可以寫出代碼如下:

      class Solution {
      public:
          vector<string> result; // 同樣是使用全局變量來存儲結(jié)果和當前狀態(tài)的字符串
          string curStr;
      
          void combinationHelper(string digits, int curIndex){
              if(curIndex == digits.size()) { // 如果所有數(shù)字已經(jīng)遍歷結(jié)束,則將當前字符串存入結(jié)果中,并返回
                  result.push_back(curStr);
                  return;
              }
              if(digits[curIndex] < '7'){ // 對于前2-6的數(shù),每個數(shù)都對應(yīng)三個字母,故可以放在一起處理
                  for(int i = 0; i < 3; i++){ // for循環(huán)遍歷每個數(shù)對應(yīng)的三個字母
                      curStr += ('a' + (digits[curIndex]-'0'-2)*3 ) + i%3; // 存入一個字母,此時要注意字符與int之間轉(zhuǎn)換需要減去一個值
                      combinationHelper(digits, curIndex+1); // 遞歸調(diào)用存入下一個數(shù)字對應(yīng)的字母
                      curStr.pop_back(); // 回溯
                  }
              }
              else if(digits[curIndex] == '7' ){ // 處理完前2-6之后,采用同樣的方式處理7,8,9,區(qū)別在于7和9對應(yīng)4個字母,其余都一樣
                  for(int i = 0 ; i < 4; i++){
                      curStr += 'p' + i;
                      combinationHelper(digits, curIndex+1);
                      curStr.pop_back();
                  }
              }
              else if(digits[curIndex] == '8'){
                  for(int i = 0; i < 3; i++){
                      curStr += 't' + i;
                      combinationHelper(digits, curIndex+1);
                      curStr.pop_back();
                  }
              }
              else if(digits[curIndex] == '9'){
                  for(int i = 0 ; i < 4; i++){
                      curStr += 'w' + i;
                      combinationHelper(digits, curIndex+1);
                      curStr.pop_back();
                  }
              }
          }
      
          vector<string> letterCombinations(string digits) {
              if(!digits.size()) return result;  // 如果輸入的字符串為空,則直接返回
              combinationHelper(digits, 0); // 使用回溯遞歸調(diào)用,將所有可能結(jié)果都存入result
              return result; // 返回result結(jié)果
          }
      };
      

      可以看到,上面代碼雖然確實在合并了一些情況的同時也能夠處理本題中的所有情況,但是對于數(shù)字取到7-9時,還是有大量重復(fù)代碼。為了簡化這部分內(nèi)容,考慮使用一個string類型的數(shù)組來存放每個數(shù)字對應(yīng)的字母。即:

      string numLetterMap[10]{
           "",
           "",
           "abc",
          "def",
          "ghi",
          "jkl",
          "mno",
          "pqrs",
          "tuv",
          "wxyz"
      };
      

      這樣每次使用將按鍵數(shù)字轉(zhuǎn)換為字母字符的時候,直接去數(shù)組中查找即可,這樣我們可以修改得到下面的代碼:

      class Solution {
      public:
          string numLetterMap[10]{ // 存放每個按鍵對應(yīng)的字母字符
          "",
          "",
          "abc",
          "def",
          "ghi",
          "jkl",
          "mno",
          "pqrs",
          "tuv",
          "wxyz"
          };
      
          void combHelper(vector<string>& result, string digits, string curStr){
              if(curStr.size() == digits.size()){ // 如果已經(jīng)長度相等,說明已經(jīng)完成,此時需要存入結(jié)果中
                  result.push_back(curStr);
                  return;
              }
              int num = digits[curStr.size()] - '0'; // 首先將char類型的數(shù)字轉(zhuǎn)換為int類型
              for(int i = 0; i < numLetterMap[num].size(); i++){ // for循環(huán)下遍歷所有取值,注意此時循環(huán)次數(shù)取決于字符串數(shù)組中對應(yīng)位置的長度
                  curStr += numLetterMap[num][i]; // 當前字符串上加一個字母
                  combHelper(result, digits, curStr); // 遞歸
                  curStr.pop_back(); // 回溯
              }
          }
      
          vector<string> letterCombinations(string digits) {
              vector<string> result;
              if(!digits.size()) return result;
              string curStr = "";
              combHelper(result, digits ,curStr);
              return result;
          }
      };
      

      通過上面代碼可以學(xué)到,之后再遇到討論情況比較多的時候,為了避免使用多個if或是switch等造成討論情況過多,可以考慮使用一些數(shù)據(jù)類型來存儲一部分信息,從而簡便討論。

      今日總結(jié)

      今天學(xué)習(xí)到了回溯算法,了解到回溯和遞歸的密不可分。回溯過程中會有一個或多個變量用于存放“當前狀態(tài)”,每一次使當前狀態(tài)變?yōu)橄乱粻顟B(tài)之后調(diào)用遞歸函數(shù)進行處理,遞歸結(jié)束之后還需要將當前進行恢復(fù)。同時回溯可以考慮使用一個全局變量來存放結(jié)果和當前狀態(tài),或者是用引用傳遞的方式來確保可以進行修改。

      此外,當遇到需要討論的情況比較多的時候,考慮能否使用一個數(shù)組來存儲不同情況下的一些取值,從而減少if討論分支,減少代碼量。

      力扣當前刷到82題了,繼續(xù)堅持

      posted on 2025-04-16 21:11  JQ_Luke  閱讀(454)  評論(0)    收藏  舉報

      主站蜘蛛池模板: 熟妇人妻中文a∨无码| 国产蜜臀在线一区二区三区| 国产三级精品三级在线观看| 亚洲精品无码久久千人斩| 性视频一区| 免费人成视频网站在线观看18| 美腿丝袜亚洲综合第一页| 韩国三级网一区二区三区| 国产自在自线午夜精品| 一本之道高清乱码少妇| 天堂www在线中文| 无码日韩做暖暖大全免费不卡| 色94色欧美sute亚洲线路二| 深夜av在线免费观看| 国产一精品一av一免费| 国产高清自产拍AV在线| 丝袜国产一区av在线观看| 日韩加勒比一本无码精品| 成人啪啪高潮不断观看| 午夜精品福利亚洲国产| 免费无码va一区二区三区 | 午夜福利理论片高清在线| 亚洲国产成人精品无色码| 国产精品一区二区传媒蜜臀| 欧美成人免费一区二区三区视频 | 欧美高清freexxxx性| 天堂在线最新版av观看| 日韩不卡无码精品一区高清视频| 丰满无码人妻热妇无码区| 国产毛片基地| 9丨精品国产高清自在线看| 亚洲偷自拍国综合| 国产成人自拍小视频在线| 在线高清理伦片a| 在线观看精品日本一区二| 福利视频在线一区二区| 久久永久视频| 日本中文字幕亚洲乱码| 亚洲男人AV天堂午夜在| 色av专区无码影音先锋| 亚洲精品理论电影在线观看|