【藍橋杯速成】| 9.回溯升級

題目一:組合綜合

問題描述

39. 組合總和 - 力扣(LeetCode)

給你一個?無重復元素?的整數數組?candidates?和一個目標整數?target?,找出?candidates?中可以使數字和為目標數?target?的 所有?不同組合?,并以列表形式返回。你可以按?任意順序?返回這些組合。

candidates?中的?同一個?數字可以?無限制重復被選取?。如果至少一個數字的被選數量不同,則兩種組合是不同的。?

對于給定的輸入,保證和為?target?的不同組合數少于?150?個。

示例?1:

輸入:candidates = [2,3,6,7], target = 7
輸出:[[2,2,3],[7]]
解釋:
2 和 3 可以形成一組候選,2 + 2 + 3 = 7 。注意 2 可以使用多次。
7 也是一個候選, 7 = 7 。
僅有這兩種組合。

解題步驟

這一題是在組合總和③上有了進一步的改進和要求

我們依舊可以用回溯三部曲模板解決

1.確定函數返回值及參數

這里我們需要從candidates數組中取值,所以這個數組應該一直陪伴我們,加入參數列表!

相當于我們之前從1~n中取值的n,都表示我們的取值范圍

同理,我們需要一直參考target數值,所以它也是參數的一員

為了記錄每個組合的總和,我們需要一個新變量用于存儲,隨之改變,所以加入新變量sum

最后仍然是我的開始索引,防止重復

void backtracking(vector<int>& candidates,int target,int sum,int startindex)

?2.確定終止條件

終止條件就是說我們找到答案會出現的情況,或者已知明確不可能出現答案就不要繼續的情況

所以分開判斷

if(sum>target){

? ? ? ? return;

}

if(sum==target){

? ? ? ? result.push_back(path);

? ? ? ? return;

}

3.單層搜索邏輯

使用for循環,遍歷candidates數組中的每一個數字,

在每一層中我們需要往path中加入該數字

同時計算sum值

然后遞歸的使用backtracking函數,獲得每一種可能情況

再進行回溯操作,sum值減去加入的數字值,數字也從path中pop_back

for(int i=startindex;i<candidates.size();i++){

? ? ? ? sum+=candidates[i];

? ? ? ? path.push_back(candidates[i]);

? ? ? ? backtracking(candidates,target,sum,startindex);//由于可以重復使用數字,所以此處startindex不需要+1

? ? ? ? sum-=candidates[i];

? ? ? ? path.pop_back();

}

最后只需要整合一下這個回溯函數,在主函數中正確傳參調用即可!

完整代碼如下!?

code

class Solution {
public:vector<int> path;vector<vector<int>> result;void backtracking(vector<int>& candidates,int target,int sum,int startindex){if(sum>target){return;}if(sum==target){result.push_back(path);return;}for(int i=startindex;i<candidates.size();i++){sum+=candidates[i];path.push_back(candidates[i]);backtracking(candidates,target,sum,i);sum-=candidates[i];path.pop_back();}}vector<vector<int>> combinationSum(vector<int>& candidates, int target) {backtracking(candidates,target,0,0);return result;}
};

題目二:電話號碼的字母組合

問題描述

17. 電話號碼的字母組合 - 力扣(LeetCode)

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

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

示例 1:

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

示例 2:

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

示例 3:

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

解題步驟

想必縮寫對應數字這事大家肯定很熟悉了

(在背后說人家壞話或者講機密時就用數字代號的事沒少干ψ(`?′)ψ

那么這一題相較于之前的組合題區別就在于,它的選值對象不再是同一個范圍內的數字了

而是存在數字對應字符串,在字符串中選取對應值,

并且這一題的組合長度也是固定的,給定dights有幾位,我們的組合長度就是幾位

簡單分析就是這樣,那當務之急就是解決數字對應字符串

這樣才可以確定之后的取值范圍

關于映射關系,我們可以選用數組和map

這里選擇二維數組

const string lettermap[10]{

? ? ? ? "","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"

? ? };

?0號和1號位為空,雖然看似一維數組,但由于string可以按照數組使用,所以是二維滴!

同樣,我們需要一個存儲過程量和一個存儲最后結果集的變量,

根據題目所求的數據類型,定義為👇

string s;//過程量,存儲每一種可能

vector<string> result;//結果集,存放所有正確結果

ok,準備完畢,開始走回溯三部曲

1.確定函數返回值及參數

這里我們不能一味的拿來之前的參數列表使用,一定要明確參數的意義

當然返回值依然是void

要把數字轉化為對應字母,那我們就需要該數字,和取到哪一位數字的一個標識

可以這么想,我們的函數需要遞歸調用的,每次都需要看取哪一位元素,

所以digits用來看,index用來指并且是要動態改變的

void backtracking(const string& digits,int index)?

?2.終止條件

既然我們已經派出index指向我們所挑選的數字

那么只要index的數值等于digits的大小,那就意味著指到最后一位了,完成我們的任務了!

所以滿足終止條件,我們需要加入這個s到結果集中并返回

if(index==digits.size()){

? ? ? ? result.push_back(s);

? ? ? ? return;

}

?3.單層遍歷邏輯

我們需要遍歷的是當前數字所對應的字符串(或者說字符數組)

所以在執行遍歷之前,我們應該取出這個字符數組

取出字符數組又分為兩步

1).確認當前數字

2).找數字對應字符數組

int digit=digits[index]-'0';//digits為字符串類型,取出類型需要通過-'0'轉為int型

string letters=lettermap[digit];//在我們的對應二維數組中找到對應string

?ok萬事大吉,開始進入單層遍歷邏輯

為方便理解我們用digits = "23"來舉例,最開始肯定是拿到2對應的字符串“abc”嘛

那就遍歷這個字符串for(int i=0;i<letters.size();i++)

在這個循環里,把單個字符串加入到s中,第一個加入的是"a"

然后遞歸調用backtracking函數,我們就可以拿到3對應的字符串“def”

然后再遍歷“def”,分別與a進行組合,得到三個組合,a這個結點就組合完畢

最外層就可以再指向下一個b,再與def進行同樣的組合

過程類似下圖,只舉例了第一個a的情況

?那么我們的單層遍歷代碼如下:

for(int i=0;i<letters.size();i++){

? ? ? ? s.push_back(letters[i]);

? ? ? ? backtracking(digits,index+1);

? ? ? ? s.pop_back();

}

整合所有代碼, 在主函數中調用即可

這里呢我們可以做一個剪枝操作,

如果給我們的數字序列為空,那么直接返回result(初始為空)即可

if(digits.size()==0){

? ? ? ? return result;

}

code

class Solution {
public:string s;vector<string> result;const string lettermap[10]{"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};void backtracking(const string& digits,int index){if(index==digits.size()){result.push_back(s);return;}int dight=digits[index]-'0';string letters=lettermap[dight];for(int i=0;i<letters.size();i++){s.push_back(letters[i]);backtracking(digits,index+1);s.pop_back();}}vector<string> letterCombinations(string digits) {if(digits.size()==0){return result;}backtracking(digits,0);return result;}
};

補充:

const 是 constant 的縮寫,本意是不變的,不易改變的意思。在 C++ 中是用來修飾內置類型變量,自定義對象,成員函數,返回值,函數參數。

C++ const 允許指定一個語義約束,編譯器會強制實施這個約束,允許程序員告訴編譯器某值是保持不變的。如果在編程中確實有某個值保持不變,就應該明確使用const,這樣可以獲得編譯器的幫助。


題目三:組合總和②

問題描述

40. 組合總和 II - 力扣(LeetCode)

給定一個候選人編號的集合?candidates?和一個目標數?target?,找出?candidates?中所有可以使數字和為?target?的組合。

candidates?中的每個數字在每個組合中只能使用?一次?。

注意:解集不能包含重復的組合。?

示例?1:

輸入: candidates =?[10,1,2,7,6,1,5], target =?8,
輸出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]

示例?2:

輸入: candidates =?[2,5,2,1,2], target =?5,
輸出:
[
[1,2,2],
[5]
]

解題步驟

不知道有沒有和我一樣的小蠢蛋,看到這一題沒仔細審題還以為是之前做過沒有提交

嘎嘎寫完代碼運行完才發現不對勁

這一題的特殊之處在于它所給的candidates是可能重復的,但最后要求解集中不能包含重復的

那么按照之前的邏輯,我們只能滿足它在各不相同的情況下不重復,

但不能解決同一個取值空間中有相同元素的重復可能

所以這里我們要加入一個新的操作——去重

其它代碼都大致相同就不多解釋,重點來理一下去重的邏輯

我們需要在每一層去確認當前元素之前是否被使用過,

那么為了方便對比前后,可以先將整個candidates數組進行排序,

那相同值肯定就出現在旁邊,不需要考慮是多久之前出現

sort(candidates.begin(), candidates.end());

同時需要留下記錄,所以需要一個新的數組來存儲這些記錄

vector<bool> used(candidates.size(), false);//初始化為false全部沒用過

那么這個used數組應該要伴隨這組結果一直遞歸才能查看情況

所以把他加入參數列表

? ? void backtracking(vector<int>& candidates,int target,int sum,int index,vector<bool>& used){

那么在單層遍歷中需要同時改變這個結點的使用狀態

????????????sum+=candidates[i];

? ? ? ? ? ? path.push_back(candidates[i]);

? ? ? ? ? ? used[i]=true;

? ? ? ? ? ? backtracking(candidates,target,sum,i+1,used);

? ? ? ? ? ? used[i]=false;

? ? ? ? ? ? sum-=candidates[i];

? ? ? ? ? ? path.pop_back();

簡單的已經鋪墊完了,接下來捋一下去重方法

重復那就是candidates[i] == candidates[i - 1],但是只加這一個條件會使我們失去確實用到兩個相同元素的結果,而不是僅去掉重復的結果(細品這個差別)

所以還需要加上used[i - 1] == false代表對于同一樹層candidates[i - 1]使用過(因為回溯所以false)

在滿足這兩個條件下我們就需要continue跳過這個組合結果

if (i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false) {

? ? ? ? ? ? ? ? continue;

? ? ? ? ? ? }

完整代碼如下!?

code

class Solution {
public:vector<int> path;vector<vector<int>> result;int sum;void backtracking(vector<int>& candidates,int target,int sum,int index,vector<bool>& used){if(sum>target){return;}if(sum==target){result.push_back(path);return;}for(int i=index;i<candidates.size();i++){if (i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false) {continue;}sum+=candidates[i];path.push_back(candidates[i]);used[i]=true;backtracking(candidates,target,sum,i+1,used);used[i]=false;sum-=candidates[i];path.pop_back();}}vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {vector<bool> used(candidates.size(), false);path.clear();result.clear();sort(candidates.begin(), candidates.end());backtracking(candidates,target,0,0,used);return result;}
};

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

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

相關文章

【C++進階】深入探索類型轉換

目錄 一、C語言中的類型轉換 1.1 隱式類型轉換 1.2. 顯式類型轉換 1.3.C語言類型轉換的局限性 二、C 類型轉換四劍客 2.1 static_cast&#xff1a;靜態類型轉換&#xff08;編譯期檢查&#xff09; 2.2 dynamic_cast&#xff1a;動態類型轉換&#xff08;運行時檢查&…

代碼隨想錄_動態規劃

代碼隨想錄 動態規劃 509.斐波那契數 509. 斐波那契數 斐波那契數 &#xff08;通常用 F(n) 表示&#xff09;形成的序列稱為 斐波那契數列 。該數列由 0 和 1 開始&#xff0c;后面的每一項數字都是前面兩項數字的和。也就是&#xff1a; F(0) 0&#xff0c;F(1) 1 F(n…

計算機基礎:編碼03,根據十進制數,求其原碼

專欄導航 本節文章分別屬于《Win32 學習筆記》和《MFC 學習筆記》兩個專欄&#xff0c;故劃分為兩個專欄導航。讀者可以自行選擇前往哪個專欄。 &#xff08;一&#xff09;WIn32 專欄導航 上一篇&#xff1a;計算機基礎&#xff1a;編碼02&#xff0c;有符號數編碼&#xf…

設計模式(創建型)-單例模式

摘要 在軟件開發的世界里&#xff0c;設計模式是開發者們智慧的結晶&#xff0c;它們為解決常見問題提供了經過驗證的通用方案。單例模式作為一種基礎且常用的設計模式&#xff0c;在許多場景中發揮著關鍵作用。本文將深入探討單例模式的定義、實現方式、應用場景以及可…

基于FPGA頻率、幅度、相位可調的任意函數發生器(DDS)實現

基于FPGA實現頻率、幅度、相位可調的DDS 1 摘要 直接數字合成器( DDS ) 是一種通過生成數字形式的時變信號并進行數模轉換來產生模擬波形(通常為正弦波)的方法,它通過數字方式直接合成信號,而不是通過模擬信號生成技術。DDS主要被應用于信號生成、通信系統中的本振、函…

本地JAR批量傳私服

在有網絡隔離的環境下&#xff0c;Maven項目如果沒有搭建私服就得把用到的通用組件通過U盤在每個組員間拷貝來拷貝去。非常的麻煩跟低效。搭建私服&#xff0c;如果通用組件很多的時候手工一個一個上傳更是非常的麻煩跟低效&#xff1b; 我就遇上這問題&#xff0c;跟A公司合作…

【ROS實戰】02-ROS架構介紹

1. 簡介 你是否曾有過這樣的疑問&#xff1a;我按照文檔安裝了ROS&#xff0c;依照要求寫了一些示例節點&#xff08;node&#xff09;、消息&#xff08;msg&#xff09;和話題&#xff08;topic&#xff09;&#xff0c;但覺得過程既麻煩又繁瑣。也許你開始懷疑&#xff1a;…

LeetCode算法題(Go語言實現)_07

題目 給你一個整數數組 nums&#xff0c;返回 數組 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘積 。 題目數據 保證 數組 nums之中任意元素的全部前綴元素和后綴的乘積都在 32 位 整數范圍內。 請 不要使用除法&#xff0c;且在 O(n) 時間復…

網絡華為HCIA+HCIP 網絡編程自動化

telnetlib介紹 telnetlib是Python標準庫中的模塊。它提供了實現Telnet功能的類telnetlib.Telnet。這里通過調用telnetlib.Telnet類里的不同方法實現不同功能。 配置云

查看GPU型號、大小;CPU型號、個數、核數、內存

GPU型號、大小 nvidia-smiCPU型號 cat /proc/cpuinfo | grep model name | uniqCPU個數 cat /proc/cpuinfo | grep "physical id" | uniq | wc -lCPU核數 cat /proc/cpuinfo | grep "cpu cores" | uniqCPU內存 cat /proc/meminfo | grep MemTotal參考…

Docker與K8S是什么該怎么選?

用了很久的容器化&#xff0c;最近突然看到一個問題問&#xff1a; docker和K8S究竟有什么區別&#xff0c;到底該怎么選&#xff1f;我認真思考了一會&#xff0c;發現一時間還真說不明白&#xff0c;于是就研究了一段時間發布今天的博文&#xff01; Docker vs Kubernetes&a…

Android Handler 通過線程安全的 MessageQueue 和底層喚醒機制實現跨線程通信

目錄 一、MessageQueue 的線程安全實現 1. 消息隊列的同步鎖&#xff08;synchronized&#xff09; 2. 消息順序與延時處理 二、底層喚醒機制&#xff1a;從 Java 到 Linux 內核 1. 消息插入后的喚醒邏輯 2. Native 層實現&#xff08;基于 Linux 的 eventfd 和 epoll&am…

關于 2>/dev/null 的作用以及機理

每個進程都有三個標準文件描述符&#xff1a;stdin&#xff08;標準輸入&#xff09;、stdout&#xff08;標準輸出&#xff09;和stderr&#xff08;標準錯誤&#xff09;。默認情況下&#xff0c;stderr會輸出到終端。使用2>可以將stderr重定向到其他地方&#xff0c;比如…

MySQL中的鎖機制:從全局鎖到行級鎖

目錄 1. 鎖的基本概念 2. 全局鎖 2.1 全局鎖的定義 2.2 全局鎖的類型 2.3 全局鎖的使用場景 2.4 全局鎖的實現方式 2.5 全局鎖的優缺點 2.6 全局鎖的優化 3. 表級鎖 3.1 表級鎖的類型 3.2 表級鎖的使用場景 3.3 表級鎖的優缺點 4. 意向鎖&#xff08;Intention Lo…

編程語言選擇分析:C#、Rust、Go 與 TypeScript 編譯器優化

編程語言選擇分析&#xff1a;C#、Rust、Go 與 TypeScript 編譯器優化 在討論編程語言的選擇時&#xff0c;特別是針對微軟的 C# 和 Rust&#xff0c;以及谷歌的 Go 語言&#xff0c;以及微軟試圖通過 Go 來拯救 TypeScript 編譯器的問題&#xff0c;我們可以從多個角度來分析和…

基于WebRTC的嵌入式音視頻通話SDK:EasyRTC跨平臺兼容性技術架構實時通信的底層實現

EasyRTC的核心架構圍繞WebRTC技術構建&#xff0c;同時通過擴展信令服務、媒體服務器和NAT穿透機制&#xff0c;解決了WebRTC在實際部署中的痛點。其架構可以分為以下幾個核心模塊&#xff1a; 1&#xff09;WebRTC基礎層 媒體捕獲與處理&#xff1a;通過getUserMediaAPI獲取…

【Rust】包和模塊管理,以及作用域等問題——Rust語言基礎15

文章目錄 1. 前言2. 包和 Crate3. 定義模塊以及模塊之間的關系4. 作用域問題4.1. 作用域問題初現4.2. 解決問題一4.3. 解決問題二4.4. super 關鍵字4.5. 將路徑引入作用域4.6. as 關鍵字4.7. pub use 重導出 5. 引入的問題5.1. 引入一個外部包5.2. 嵌套路徑來消除大量的 use 行…

微服務架構中的API網關:Spring Cloud與Kong/Traefik等方案對比

微服務架構中的API網關&#xff1a;Spring Cloud與Kong/Traefik等方案對比 一、API 網關的概念二、API 網關的主要功能2.1 統一入口與路由轉發2.2 安全與權限控制2.3 流量管理與容錯2.4 API 管理與聚合2.5 監控與日志2.5 協議轉換與適配2.6 控制平面與配置管理 三、API 網關選型…

NewStar CTF web wp

文章目錄 week1headach3會贏嗎智械危機謝謝皮蛋PangBai 過家家&#xff08;1&#xff09; week3include meblindsql1臭皮的計算機臭皮踩踩背這照片是你嗎 week4Pangbai過家家四blindsql2chocolateezcmsssezpollute隱藏的密碼 weeek5pangbai過家家(5)redissqlshell臭皮吹泡泡臭皮…

Linux驅動開發-①中斷②阻塞、非阻塞IO和異步通知

Linux驅動開發-①中斷②阻塞、非阻塞IO和異步通知 一&#xff0c;中斷1.中斷的流程2.上半部和下半部2.1上半部2.2下半部2.2.1 tasklet2.2.2 工作隊列 3.按鍵延時消抖中斷程序 二&#xff0c;阻塞和非阻塞IO和異步通知1.阻塞IO1.1 常見結構11.2 常見結構2 2.非阻塞IO2.1 驅動結構…