算法刷題記錄——LeetCode篇(4) [第301~400題](持續更新)

(優先整理熱門100及面試150,不定期持續更新,歡迎關注)


322. 零錢兌換

給你一個整數數組 coins ,表示不同面額的硬幣;以及一個整數 amount ,表示總金額。
計算并返回可以湊成總金額所需的最少的硬幣個數。如果沒有任何一種硬幣組合能組成總金額,返回 -1
你可以認為每種硬幣的數量是無限的。

示例 1:

輸入:coins = [1, 2, 5], amount = 11
輸出:3 

解釋:11 = 5 + 5 + 1

示例 2:

輸入:coins = [2], amount = 3
輸出:-1

示例 3:

輸入:coins = [1], amount = 0
輸出:0

提示:

  • 1 <= coins.length <= 12
  • 1 <= coins[i] <= 2^31 - 1
  • 0 <= amount <= 10^4

方法一:動態規劃

使用動態規劃數組 dp,其中 dp[i] 表示湊成金額 i 所需的最少硬幣個數。通過逐步填充 dp 數組,最終得到 dp[amount] 的結果。

  1. 初始化

    • dp[0] = 0:金額為0時不需要任何硬幣。
    • 其他金額初始化為 amount + 1,因為最多需要 amount 個硬幣(全用面額1的硬幣),初始值設為更大的數表示暫時不可達。
  2. 狀態轉移

    • 對于每個金額 i,遍歷所有硬幣面額 coin
    • coin ≤ i,則可以通過 i - coin 的金額加上當前硬幣組成 i,即 dp[i] = min(dp[i], dp[i - coin] + 1)
  3. 結果判斷

    • 如果最終 dp[amount] 仍大于 amount,說明無法湊出目標金額,返回 -1
    • 否則返回 dp[amount],即最少硬幣數。

代碼實現(Java)

import java.util.Arrays;class Solution {public int coinChange(int[] coins, int amount) {if (amount == 0) {return 0;}int[] dp = new int[amount + 1];Arrays.fill(dp, amount + 1); // 初始化為一個較大的值(超過最大可能硬幣數)dp[0] = 0; // 金額0需要0個硬幣// 遍歷所有金額,從1到amountfor (int i = 1; i <= amount; i++) {// 遍歷所有硬幣面額for (int coin : coins) {if (coin <= i) { // 硬幣面額不超過當前金額時,才可能使用dp[i] = Math.min(dp[i], dp[i - coin] + 1);}}}// 判斷結果是否有效return dp[amount] > amount ? -1 : dp[amount];}
}

方法二:BFS解法

將問題轉化為圖的最短路徑問題,其中每個節點表示當前剩余金額,邊表示使用一枚硬幣。BFS按層遍歷,首次到達金額0時的層數即為最少硬幣數。

  1. 初始化

    • 隊列存放待處理的金額,初始為 amount
    • 已訪問集合 visited 防止重復處理相同金額。
    • steps 記錄當前層數(即已用硬幣數)。
  2. 層序遍歷

    • 每層開始前記錄隊列大小,處理完該層所有節點后步數+1。
    • 對每個金額嘗試所有硬幣:
      • current - coin == 0,直接返回當前步數。
      • 若新金額合法且未訪問過,加入隊列并標記,避免重復處理相同金額。
  3. 終止條件

    • 隊列清空時仍未找到解,返回 -1

代碼實現(Java)

import java.util.*;class Solution {public int coinChange(int[] coins, int amount) {if (amount == 0) return 0;Queue<Integer> queue = new LinkedList<>();Set<Integer> visited = new HashSet<>();queue.offer(amount);visited.add(amount);int steps = 0;while (!queue.isEmpty()) {int size = queue.size();steps++;for (int i = 0; i < size; i++) {int current = queue.poll();for (int coin : coins) {int next = current - coin;if (next == 0) {return steps; // 找到解,直接返回}if (next > 0 && !visited.contains(next)) {visited.add(next);queue.offer(next);}}}}return -1; // 隊列清空仍未找到解}
}

復雜度分析

  • 動態規劃時間復雜度:外層循環:O(amount),內層循環:O(coins.length),總復雜度:O(amount * coins.length)
  • BFS時間復雜度:最壞情況:O(amount * coins.length),實際效率取決于硬幣面額分布,大額硬幣可能加速收斂。

對比總結

方法優勢劣勢
BFS無需預計算所有狀態,快速收斂空間復雜度高(隊列膨脹)
動態規劃適合多次查詢,空間可控需遍歷全部狀態

347. 前 K 個高頻元素

給你一個整數數組 nums 和一個整數 k ,請你返回其中出現頻率前 k 高的元素。你可以按任意順序返回答案。

示例 1:

輸入: nums = [1,1,1,2,2,3], k = 2
輸出: [1,2]

示例 2:

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

提示:

  • 1 <= nums.length <= 105
  • k 的取值范圍是 [1, 數組中不相同的元素的個數]
  • 題目數據保證答案唯一,換句話說,數組中前 k 個高頻元素的集合是唯一的

進階: 你所設計算法的時間復雜度必須優于 O(n log n) ,其中 n 是數組大小。

方法一:最小堆(優先隊列)

使用最小堆維護當前頻率最高的k個元素,遍歷時保持堆的大小不超過k,時間復雜度為O(n log k)

  1. 統計頻率:使用哈希表記錄每個元素的出現次數。
  2. 維護最小堆:將元素按頻率加入堆,堆大小超過k時移除堆頂(最小頻率元素)。
  3. 提取結果:堆中剩余的元素即為前k高的頻率元素。

代碼實現(Java)

class Solution {public int[] topKFrequent(int[] nums, int k) {// 統計頻率Map<Integer, Integer> freqMap = new HashMap<>();for (int num : nums) {freqMap.put(num, freqMap.getOrDefault(num, 0) + 1);}// 創建最小堆,按頻率升序排序PriorityQueue<Map.Entry<Integer, Integer>> heap = new PriorityQueue<>((a, b) -> a.getValue() - b.getValue());// 維護堆的大小為kfor (Map.Entry<Integer, Integer> entry : freqMap.entrySet()) {heap.offer(entry);if (heap.size() > k) {heap.poll();}}// 提取結果int[] res = new int[k];int idx = 0;while (!heap.isEmpty()) {res[idx++] = heap.poll().getKey();}return res;}
}

方法二:桶排序

基于頻率的桶排序,時間復雜度為O(n),適合處理大數據量。

  1. 統計頻率:記錄每個元素出現的次數及最大頻率。
  2. 構建頻率桶:將元素按頻率存入對應桶中。
  3. 逆序收集結果:從高頻率到低頻率遍歷桶,收集前k個元素。

代碼實現(Java)

class Solution {public int[] topKFrequent(int[] nums, int k) {// 統計頻率Map<Integer, Integer> freqMap = new HashMap<>();for (int num : nums) {freqMap.put(num, freqMap.getOrDefault(num, 0) + 1);}// 創建桶數組List<Integer>[] bucket = new List[nums.length + 1];for (Map.Entry<Integer, Integer> entry : freqMap.entrySet()) {int freq = entry.getValue();if (bucket[freq] == null) {bucket[freq] = new ArrayList<>();}bucket[freq].add(entry.getKey());}// 收集結果int[] res = new int[k];int idx = 0;for (int i = bucket.length - 1; i >= 0 && idx < k; i--) {if (bucket[i] != null) {for (int num : bucket[i]) {res[idx++] = num;if (idx == k) break;}}}return res;}
}

復雜度分析

1、最小堆

  • 時間復雜度:O(n log k),其中n為數組長度,k為結果數量。
    空間復雜度:O(n),哈希表和堆的空間。
  • 優點:空間占用相對較低,適合k較小的情況。
    缺點:當k接近n時,時間復雜度接近O(n log n)

2、桶排序

  • 時間復雜度:O(n),所有操作均為線性時間。
    空間復雜度:O(n),桶數組和哈希表的空間。
  • 優點:時間復雜度嚴格為O(n),適合大數據量。
    缺點:需要額外空間存儲桶,最大頻率較高時空間占用大。

394. 字符串解碼

給定一個經過編碼的字符串,返回它解碼后的字符串。
編碼規則為: k[encoded_string],表示其中方括號內部的 encoded_string 正好重復 k 次。注意 k 保證為正整數。
你可以認為輸入字符串總是有效的;輸入字符串中沒有額外的空格,且輸入的方括號總是符合格式要求的。
此外,你可以認為原始數據不包含數字,所有的數字只表示重復的次數 k ,例如不會出現像 3a2[4] 的輸入。

示例 1:

輸入:s = "3[a]2[bc]"
輸出:"aaabcbc"

示例 2:

輸入:s = "3[a2[c]]"
輸出:"accaccacc"

示例 3:

輸入:s = "2[abc]3[cd]ef"
輸出:"abcabccdcdcdef"

示例 4:

輸入:s = "abc3[cd]xyz"
輸出:"abccdcdcdxyz"

提示:

  • 1 <= s.length <= 30
  • s 由小寫英文字母、數字和方括號 '[]' 組成
  • s 保證是一個有效的輸入
  • s 中所有整數的取值范圍為 [1, 300]

方法:棧輔助法

利用棧來處理嵌套的括號結構,保存每層括號外的字符串和重復次數。遍歷字符串時解析數字,遇到左括號時將當前狀態壓棧,遇到右括號時彈出棧頂元素進行字符串拼接。

  1. 初始化棧和變量:使用兩個棧分別保存當前層的字符串和重復次數,當前字符串和數字變量記錄正在處理的部分。
  2. 遍歷字符
    • 數字:累加計算多位數。
    • 左括號:壓棧當前字符串和數字,重置變量。
    • 右括號:彈出棧頂的字符串和數字,將當前字符串重復后拼接。
    • 字母:直接追加到當前字符串。
  3. 返回結果:最終拼接完成的字符串即為答案。

代碼實現(Java)

class Solution {public String decodeString(String s) {Stack<Integer> numStack = new Stack<>();Stack<StringBuilder> strStack = new Stack<>();StringBuilder currentStr = new StringBuilder();int num = 0;for (char c : s.toCharArray()) {if (Character.isDigit(c)) {num = num * 10 + (c - '0');} else if (c == '[') {strStack.push(currentStr);numStack.push(num);currentStr = new StringBuilder();num = 0;} else if (c == ']') {int k = numStack.pop();StringBuilder prevStr = strStack.pop();String temp = currentStr.toString();prevStr.append(temp.repeat(k));currentStr = prevStr;} else {currentStr.append(c);}}return currentStr.toString();}
}

復雜度分析

  • 時間復雜度O(n × m),其中n是字符串長度,m是最大重復次數。每個字符處理一次,字符串拼接的時間取決于重復次數。
  • 空間復雜度O(n),棧的深度最壞情況下與字符串長度成線性關系。

博客源文件Gitee倉庫:

gitee.com/richardmilos/allen-csdn-notes

(持續更新,未完待續)

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

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

相關文章

vulnhub靶場之loly靶機

前言 挑戰攻克該靶機30分鐘 靶機&#xff1a;loly靶機&#xff0c;IP地址為192.168.10.11 攻擊&#xff1a;kali&#xff0c;IP地址為192.168.10.6 靶機和攻擊機都采用VMware虛擬機&#xff0c;都采用橋接網卡模式 文章涉及的靶機及工具&#xff0c;都可以自行訪問官網或者項…

Deepseek API+Python測試用例一鍵生成與導出-V1.0.2【實現需求文檔圖片識別與用例生成自動化】

在測試工作中&#xff0c;需求文檔中的圖片&#xff08;如界面設計圖、流程圖&#xff09;往往是測試用例生成的重要參考。然而&#xff0c;手動提取圖片并識別內容不僅耗時&#xff0c;還容易出錯。本文將通過一個自研小工具&#xff0c;結合 PaddleOCR 和大模型&#xff0c;自…

Excel(函數篇):COUNTIF與CONUTIFS函數、SUMIF與SUMIFS函數、ROUND函數、MATCH與INDEX函數、混合引用與條件格式

目錄 COUNTIF和COUNTIFS函數COUNTIF函數COUNTIFS函數SUMIF和SUMIFS函數SUMIF函數SUMIFS函數SUMIFS函數與控件實現動態年月匯總ROUND、ROUNDUP、ROUNDDOWN函數單元格混合引用條件格式與公式,標記整行數據MATCH和INDEX函數COUNTIF和COUNTIFS函數 COUNTIF函數 統計下“蘇州”出現…

上位機數據可視化:使用QtCharts繪制波形圖

工程配置 CMake文件 find_package(Qt5 COMPONENTS Charts REQUIRED)target_link_libraries(zhd-desktop PRIVATE Qt5::Charts)包含頭文件以及名稱空間&#xff08;這個很重要&#xff0c;沒有包含名稱空間編譯器會提示找不到相關的類型&#xff09; #include <QtCharts&g…

S32K144入門筆記(十三):LPIT的API函數解讀

目錄 1. SDK中的函數 2. API函數的釋義 2.1 獲取默認參數 2.2 初始化 2.3 啟動與停止 2.4 計數值的設置于讀取 2.5 中斷API 1. SDK中的函數 在使用SDK的非抽象驅動函數時&#xff0c;函數的定義與聲明在文件lpit_driver.c和lpit_driver.h中&#xff0c;一共有19個函數&a…

CSS - Pseudo-classes(偽類選擇器)

目錄 一、介紹二、常用種類三、案例實現案例一&#xff1a;a標簽使用link/visited/hover/active案例二&#xff1a;表單元素使用focus/disabled案例三、通過其余偽類實現元素靈活選中 一、介紹 CSS 偽類&#xff08;Pseudo-classes&#xff09; 用于定義元素的特定狀態或結構位…

http proxy的原理是什么

Http代理的原理 代理服務器會自動提取請求數據包中的HTTP請求數據發送給服務端&#xff0c;并將服務端的HTTP響應數據轉發給發送請求的客戶端&#xff0c;HTTP代理服務器使用的端口通常是8080。 對于Web客戶端來說&#xff0c;代理扮演的服務器角色&#xff0c;接收請求&…

Ubuntu22.04虛擬機里安裝Yolov8流程

1. 安裝pytorch sudo apt install nvidia-cuda-toolkit nvcc --version # 官方適配地址&#xff1a;https://download.pytorch.org/whl/torch/import torch print(torch.__version__) print(torch.cuda.is_available())2. 安裝環境 # cuDNN 安裝&#xff1a;https://develop…

神經網絡微調技術解析

神經網絡微調技術 微調&#xff08;Fine-tuning&#xff09;是遷移學習的核心技術&#xff0c;通過在預訓練模型基礎上調整參數&#xff0c;使其適應特定任務或領域。以下從傳統方法、參數高效微調&#xff08;PEFT&#xff09;、新興技術三個維度展開&#xff0c;覆蓋主流技術…

Spring 聲明式事務管理

Spring 編程的方式實現事務管理&#xff0c;這樣太過麻煩&#xff0c;需要在每個方法上面加上相應的事務處理操作&#xff0c;聲明式事務處理能夠很好的解決這個問題&#xff0c;比如通過tx命名空間&#xff0c;這樣只需要配置就可以檢測到相關的方法&#xff0c;或者是通過tra…

電機控制常見面試問題(十五)

文章目錄 一、電機氣隙二、電氣時間三.電機三環控制詳解四.驅動板跳線意義五.電機開環自檢 一、電機氣隙 電機氣隙是定子和轉子之間的空隙&#xff0c;防止釘子轉子運轉時物理接觸&#xff0c;此外&#xff0c;氣隙是磁路的重要環節&#xff0c;磁場需通過氣隙傳遞能量&#x…

代碼隨想錄算法訓練營第六十五天| 圖論10

Bellman_ford 隊列優化算法&#xff08;又名SPFA&#xff09; 代碼隨想錄 import collectionsdef main():n, m map(int, input().strip().split())edges [[] for _ in range(n 1)]for _ in range(m):src, dest, weight map(int, input().strip().split())edges[src].append…

Chat2DB:讓數據庫管理像聊天一樣簡單

數據庫工具的痛點與破局 在數據爆炸的時代&#xff0c;數據庫管理工具已成為企業高效運營的剛需。然而&#xff0c;傳統工具如Navicat、DBeaver雖功能強大&#xff0c;卻讓非技術人員和SQL新手望而卻步。復雜的界面、繁瑣的手動操作、晦澀的語法規則&#xff0c;成為橫亙在數據…

Navicat for Snowflake 震撼首發,激活數據倉庫管理全新動能

近日&#xff0c;Navicat 家族迎來了一位全新成員 — Navicat for Snowflake。Snowflake 是一款基于云架構的現代數據倉庫解決方案&#xff0c;以其彈性擴展、高性能和易用性著稱。這次首發的Navicat for Snowflake 專為簡化 Snowflake 數據庫管理任務而精心打造。它憑借其直觀…

【項目合集】智能語音小車-微信小程序控制

功能需求&#xff1a; 車子檢測環境溫度、濕度&#xff0c;上報 APP、WEB 端顯示實時數據可通過 APP 控制小車前進、左轉、右轉可通過語音控制小車前進后退車上一個 LED 燈&#xff0c;可通過 WEB、小程序控制在 APP、WEB 上均可注冊登錄 硬件清單 硬件 功能 備注 ESP32 …

人工智能與人的智能,改變一生的思維模型分享【4】決策樹

決策樹&#xff08; DECISION TREE&#xff09; 一般由一個決策圖和若干可能的結果組成。是一種通過羅列解題的關鍵步驟以及各步驟發生的條件和結果&#xff0c;由此來創建到達目標的規劃。 我們很早就知道有一個方法&#xff0c;叫做當你苦悶、糾結的時候&#xff0c;把你的所…

利用余弦相似度在大量文章中找出抄襲的文章

我前面的2篇文章分別講了如果利用余弦相似度來判斷2篇文章的相似度&#xff0c;來確定文章是否存在抄襲&#xff0c;和余弦相似度的原理&#xff0c;即余弦相似度到底是怎么來判斷文章的相似性高低的等等。這一篇再說下&#xff0c;對于文章字數多和大量文章時&#xff0c;如果…

設計模式-對象創建

對象創建 前言1. Factory Method1.1 模式介紹1.2 模式代碼1.2.1 問題代碼1.2.2 重構代碼 1.3 模式類圖1.4 要點總結 2. Abstract Factory2.1 模式介紹2.2 模式代碼2.2.1 問題代碼2.2.2 重構代碼 2.3 模式類圖2.4 要點總結 3. Prototype3.1 模式介紹3.2 模式代碼3.3 模式類圖3.4…

SQLAlchemy系列教程:批量插入數據

高效地批量插入數據對于應用程序的性能至關重要。SQLAlchemy為批處理操作提供了幾種機制&#xff0c;可以最大限度地減少開銷并加快數據庫事務時間。在本指南中&#xff0c;我們將探討如何使用SQLAlchemy執行批量插入&#xff0c;包括從基礎技術到高級技術。 搭建環境 在開始之…

V2X驗證

1. 標準和規范驗證 歐洲對 DSRC 和 V2X 系統有一系列的標準和規范,主要由 ETSI (European Telecommunications Standards Institute) 和 IEEE 等組織制定。驗證通常包括以下標準和規范: ETSI EN 302 571:這是DSRC在歐洲的主要標準,規定了DSRC系統的技術要求和操作條件。ET…