算法訓練營day29

一、組合

參考鏈接77. 組合 - 力扣(LeetCode)

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;public class Solution {public List<List<Integer>> combine  (int n, int k) {List<List<Integer>> res = new ArrayList<>();if (k <= 0 || n < k) {return res;}Deque<Integer> path = new ArrayDeque<>();dfs(n, k, 1, path, res);return res;}private void dfs(int n, int k, int index, Deque<Integer> path, List<List<Integer>> res) {//如果當前path的大小和 k相等,則將結果保存到ArrayList當中if (path.size() == k) {res.add(new ArrayList<>(path));return;}// 剪枝優化 i <= n - (k - path.size()) + 1 背吧,歸納法for (int i = index; i <= n - (k - path.size()) + 1; i++) {path.addLast(i);dfs(n, k, i + 1, path, res);path.removeLast();}}
}
二、遞增子序列

核心理解:set去重

set在dfs的實現的方式是 new HashSet<>(),而不是在函數外定義的set,每一次遞歸都會生成新的Set,

class Solution {// 定義全局變量保存結果List<List<Integer>> res = new ArrayList<>();public List<List<Integer>> findSubsequences(int[] nums) {// idx 初始化為 -1,開始 dfs 搜索。dfs(nums, -1, new ArrayList<>());return res;}private void dfs(int[] nums, int idx, List<Integer> curList) {// 只要當前的遞增序列長度大于 1,就加入到結果 res 中,然后繼續搜索遞增序列的下一個值。if (curList.size() > 1) {res.add(new ArrayList<>(curList));}// 在 [idx + 1, nums.length - 1] 范圍內遍歷搜索遞增序列的下一個值。// 借助 set 對 [idx + 1, nums.length - 1] 范圍內的數去重。
//注意 set是 數中每一層的 變量,到達下一層時又new了HashSetSet<Integer> set = new HashSet<>();for (int i = idx + 1; i < nums.length; i++) {// 1. 如果 set 中已經有與 nums[i] 相同的值了,說明加上 nums[i] 后的所有可能的遞增序列之前已經被搜過一遍了,因此停止繼續搜索。if (set.contains(nums[i])) { continue;}set.add(nums[i]);// 2. 如果 nums[i] >= nums[idx] 的話,說明出現了新的遞增序列,因此繼續 dfs 搜索(因為 curList 在這里是復用的,因此別忘了 remove 哦)if (idx == -1 || nums[i] >= nums[idx]) {curList.add(nums[i]);dfs(nums, i, curList);curList.remove(curList.size() - 1);}}}
}
  1. 比如 4 7 3 2 1 7 … 這個數組,當curList遍歷到 4 7 的時候,進入遞歸,一直遍歷直到 出現 第二個7,這時候出現了 4 7 7 序列添加到結果中
  2. 回溯到 4 7 ,在當前層的for循環進行遍歷,再次遍歷到 第二個 7,判斷set中有7,通過1我們知道 4 7 7 開頭的數組組合我們在遞歸中已經將其實現,所以這一枝我們進行剪枝
  3. 回歸set的作用,處理數組中出現相同值時 出現重復結果(也就是去重)

參考鏈接46. 全排列 - 力扣(LeetCode)

三、全排列
import java.util.ArrayList;
import java.util.List;public class Solution {public List<List<Integer>> permute(int[] nums) {int len = nums.length;// 使用一個動態數組保存所有可能的全排列List<List<Integer>> res = new ArrayList<>();if (len == 0) {return res;}//使用一個數組表示某個數是否已經被選過,選過為true,否則為falseboolean[] used = new boolean[len];List<Integer> path = new ArrayList<>();dfs(nums, len, 0, path, used, res);return res;}
//nums 當前數組,len 數組長度,depth表示深度,path 當前走過的路徑,used 某個數字是否被選中, res 結果數組private void dfs(int[] nums, int len, int depth,List<Integer> path, boolean[] used,List<List<Integer>> res) {
// 如果遍歷到 深度 和 長度 相等表示所有數字都已經被選擇過了if (depth == len) {res.add(path);return;}// 在非葉子結點處,產生不同的分支,這一操作的語義是:在還未選擇的數中依次選擇一個元素作為下一個位置的元素,這顯然得通過一個循環實現。 ****這段是重點核心代碼,需要背for (int i = 0; i < len; i++) {if (!used[i]) {path.add(nums[i]);used[i] = true;dfs(nums, len, depth + 1, path, used, res);// 注意:下面這兩行代碼發生 「回溯」,回溯發生在從 深層結點 回到 淺層結點 的過程,代碼在形式上和遞歸之前是對稱的used[i] = false;path.remove(path.size() - 1);}}}public static void main(String[] args) {int[] nums = {1, 2, 3};Solution solution = new Solution();List<List<Integer>> lists = solution.permute(nums);System.out.println(lists);}
}
四、全排列2

使用存在重復數字的數組來生成新的全排列數組,要求去重

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.List;public class Solution {public List<List<Integer>> permuteUnique(int[] nums) {int len = nums.length;List<List<Integer>> res = new ArrayList<>();if (len == 0) {return res;}// 排序(升序或者降序都可以),排序是剪枝的前提Arrays.sort(nums);boolean[] used = new boolean[len];// 使用 Deque 是 Java 官方 Stack 類的建議Deque<Integer> path = new ArrayDeque<>(len);dfs(nums, len, 0, used, path, res);return res;}private void dfs(int[] nums, int len, int depth, boolean[] used, Deque<Integer> path, List<List<Integer>> res) {if (depth == len) {res.add(new ArrayList<>(path));return;}for (int i = 0; i < len; ++i) {if (used[i]) {continue;}// 剪枝條件:i > 0 是為了保證 nums[i - 1] 有意義// 寫 !used[i - 1] 是因為 nums[i - 1] 在深度優先遍歷的過程中剛剛被撤銷選擇,被撤銷選擇為falseif (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {continue;}path.addLast(nums[i]);used[i] = true;dfs(nums, len, depth + 1, used, path, res);// 回溯部分的代碼,和 dfs 之前的代碼是對稱的used[i] = false;path.removeLast();}}
}

A 1分24秒到2分00秒:講了為什么要先排序 因為結果是要去重的,而結果都是列表形式的,那列表怎么判重呢?就是排序之后一個一個的比較,所以那還不如先排序之后再計算,在計算的過程中判斷是否有重復,免得對每個結果再做一次排序去重操作。再一個,排序之后相同的元素一定重復嗎?不一定,不同結果經過排序之后也可能相同

B 為什么" nums[i-1] 的used狀態是被選擇的,那么說明當前的nums[i] 是 nums[i-1]的下一層路徑。"

原因:因為往下層遞歸的話,一直再往下層走,dfs還未return,也就是說used還沒有被回溯為未選擇狀態,所以同一條分支上,nums[i-1] 的used狀態一定是被選擇的。

為什么“ 如果 nums[i-1] 的狀態是沒被選擇的,那么說明當前 的nums[i] 是nums[i-1] 同層路徑。”

原因:遞歸到葉節點,開始往上回溯了,回溯到某一層時把used[i-1]回溯為未選擇狀態,然后for循環i++橫向移動,自然這時再判斷used[i-1]就一定是未選擇狀態。

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

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

相關文章

C語言----斐波那契數列

各位看官們好&#xff0c;當我寫了上一篇博客楊輝三角后&#xff0c;有一些看官叫我講一下斐波那契數列。對于這個大家應該是有了解的。最簡單的規律就是f(n)f(n-2)f(n-1)。就是當前是前兩項之和&#xff0c;然后下標1和0都是1.從第三項開始計算的。那么我們知道規律&#xff0…

選購洗地機有哪些技巧?2024洗地機全面解析,618洗地機綜合對比

洗地機作為人們生活中智能清潔工具的代表&#xff0c;它自帶清/污水箱&#xff0c;不用手洗滾刷&#xff0c;既可以吸塵也可以自動識別并清洗地板上的干濕垃圾和頑固污漬&#xff0c;它以多功能一體化的設計改善了家務清潔的效率和體驗。那么如何在眾多洗地機品牌中&#xff0c…

C#實現簡單音樂文件解析播放——Windows程序設計作業2

1. 作業內容 編寫一個C#程序&#xff0c;要求實現常見音樂文件的播放功能&#xff0c;具體要求如下&#xff1a; ????1). 播放MP3文件&#xff1a; 程序應能夠讀取MP3文件&#xff0c;并播放其中的音頻。 ????2). 播放OGG文件&#xff1a; 應能夠播放ogg文件。 ????…

阿里云Redis創建使用

說明&#xff1a;本文介紹如何使用阿里云Redis&#xff0c;包括開通、連接、使用&#xff1b; 開通 進入官網Redis產品頁&#xff0c;點擊免費試用&#xff08;白嫖&#xff09;&#xff1b; 選擇中間這個&#xff0c;云數據庫Redis版&#xff1b; 開通完成后&#xff0c;可在…

如何在Java項目中使用Spring Boot快速連接達夢數據庫(DM)

前言 在Java開發領域&#xff0c;Spring Boot憑借其簡潔快速的特性成為現代應用開發的首選框架。本文將詳細介紹如何在Spring Boot項目中整合JDBC以快速連接達夢數據庫(DM)&#xff0c;并提供一個簡單的示例來驗證連接是否成功。 一、環境準備與依賴配置 在開始之前&#xf…

零代碼平臺助力中國石化江蘇油田實現高效評價體系

概述&#xff1a; 中國石化集團江蘇石油勘探局有限公司面臨著評價體系依賴人工處理數據、計算繁瑣且容易出錯的挑戰。為解決這一問題&#xff0c;他們決定借助零代碼平臺明道云開發江蘇油田高質量發展經濟指標評價系統。該系統旨在實現原始數據批量導入與在線管理、權重及評分…

QT設計模式:建造者模式

基本概念 建造者模式是一種創建型設計模式&#xff0c;它允許你創建復雜對象的過程獨立于該對象的組成部分以及它們的組裝方式。這樣可以構造出不同的對象表示。 在建造者模式中&#xff0c;將創建對象的過程和對象的表示分離&#xff0c;通過一步步的構建&#xff0c;可以得…

FFmpeg常用API與示例(四)——過濾器實戰

1.filter 在多媒體處理中&#xff0c;filter 的意思是被編碼到輸出文件之前用來修改輸入文件內容的一個軟件工具。如&#xff1a;視頻翻轉&#xff0c;旋轉&#xff0c;縮放等。 語法&#xff1a;[input_link_label1]… filter_nameparameters [output_link_label1]… 1、視…

C++中調用python函數(VS2017+WIN10+Anaconda虛擬環境)

1.利用VS創建C空項目 step1 文件——新建——項目 step2 Visual C—— Windows桌面——Windows桌面向導 step3 選擇空項目 step4 源文件——新建項——添加 step5 Visual C——C文件&#xff08;.cpp&#xff09; 2.配置環境 Step1. 更換成Release與X64 Step2. 打開項目屬性&…

文本提取新技能:學會按行數批量提取,輕松應對各種需求

在數字化時代&#xff0c;文本處理成為我們日常生活和工作中不可或缺的一部分。無論是從網頁、文檔還是數據庫中提取信息&#xff0c;文本提取技能都顯得尤為重要。而按行數批量提取文本內容&#xff0c;更是文本處理中的一項高效且實用的技能。本文將介紹辦公提效工具如何按行…

在Spring Boot應用安裝SSL證書

目錄 前提條件 步驟一&#xff1a;下載SSL證書 步驟二&#xff1a;在Spring Boot安裝SSL證書 步驟三&#xff1a;驗證SSL證書是否安裝成功 前提條件 已通過數字證書管理服務控制臺簽發證書SSL證書綁定的域名已完成DNS解析&#xff0c;即您的域名與主機IP地址相互映射已在W…

ASP.NET學生信息管理系統

摘 要 本文介紹了在ASP.net環境下采用“自上而下地總體規劃&#xff0c;自下而上地應用開發”的策略開發一個管理信息系統的過程。通過分析某一學校學生管理的不足&#xff0c;創建了一套行之有效的計算機管理學生的方案。文章介紹了學生管理信息系統的系統分析部分&#xff0c…

微信投票源碼系統至尊版 吸粉變現功能二合一

源碼簡介 微信投票系統在營銷和社交互動中發揮著多方面的作用&#xff0c;它能夠提升用戶的參與度和品牌曝光度&#xff0c;還是一種有效的數據收集、營銷推廣和民主決策工具。 分享一款微信投票源碼系統至尊版&#xff0c;集吸粉變現功能二合一&#xff0c;全網獨家支持禮物…

已經安裝tensorflow,仍報錯No module named ‘tensorflow‘

在安裝某些python虛擬環境的教程文章中&#xff0c;經常看到有評論區說安裝了但是調用顯示無模塊&#xff0c;例如pytorch和tensorflow等等。 其實跟之前我寫過的一篇文章解決方法類似&#xff0c;就是python項目中需要應用哪個虛擬環境&#xff0c;這個項目的python解釋器就選…

企業網絡需求及適合的解決方案

近年來&#xff0c;企業網絡通信需求可謂五花八門&#xff0c;變幻莫測。它不僅為企業的生產、辦公、研發、銷售提供全面賦能&#xff0c;同時也讓企業業務規模變大成為了可能。 在當前的技術格局下&#xff0c;中大型企業常見的技術方案有很多&#xff0c;而同時也有各自不可替…

商務英語口語成人考級外語培訓之BECkao考級口語篇

在口語考試中&#xff0c;不管實際內容你能說出多少&#xff0c;但準備一些套話&#xff0c;至少還能撐撐場子你們說是不是&#xff1f; 內容闡述 描述事實 1.Im going to describe/present/explain/give you some information about... 2.Id like to say a few words about...…

德國儲能項目鋰電池儲能集裝箱突發火災:安全挑戰再引關注

2024年4月27日&#xff0c;德國尼爾莫爾商業區的一起鋰電池儲能集裝箱火災事件引起了全球關注。這起事故不僅導致兩名消防員在救援過程中受傷&#xff0c;更暴露了儲能系統在安全領域亟待解決的重要問題。 根據德國消防隊的出警記錄&#xff0c;火災發生在晚上9點前不久。消防人…

機器學習算法應用——神經網絡回歸任務、神經網絡分類任務

神經網絡回歸任務&#xff08;4-3&#xff09; 神經網絡回歸任務&#xff0c;通常指的是使用神經網絡模型進行回歸分析。回歸分析是一種統計學方法&#xff0c;用于研究一個或多個自變量&#xff08;預測變量&#xff09;與一個因變量&#xff08;響應變量&#xff09;之間的關…

漲薪技術 —— 搞定Appium工作中常見應用操作!

前言 Appium 是一個開源、跨平臺的自動化測試工具&#xff0c;用于測試原生和輕量移動應用&#xff0c;支持 iOS, Android 和 FirefoxOS 平臺。此工具在測試工作中也較長用到&#xff0c;接下來給大家介紹日常中的操作。 1、應用操作 1.1獲取應用的包名和界面名 當我們從一…

日報表定時任務優化歷程

報表需求背景 報表是一個很常見的需求&#xff0c;在項目中后期往往會需要加多種維度的一些統計信息&#xff0c;今天就來談談上線近10個月后的一次報表優化優化之路&#xff08;從一天報表跑需要五分鐘&#xff0c;優化至秒級&#xff09; 需求&#xff1a;對代理商進行日統計…