LeetCodeHot100_0x09

LeetCodeHot100_0x09

70. 最小棧·數據結構實現

求解思路: 一開始想著只用一個最小棧結構不就實現了,結果測試的時候發現,在pop元素后,它的最小值有可能不受影響,但是只用一個最小棧的話,最小值一定是作為棧頂元素最先被彈出了。而且題目要求彈出的元素是指按順序插入的元素。因此原數據的插入順序也需要用一個棧保存。也就是說,這題用兩個Deque結構分別存儲所有元素和維護當前元素存入時最小值的棧。

另外我看到評論區有老哥分享字節一面的進階要求——不使用額外空間完成。

class MinStack {public Deque<Integer> stack;    // 保存所有元素public Deque<Integer> minStack; // 保存最小值的順序// 初始化函數public MinStack() {stack = new LinkedList<Integer>();minStack = new LinkedList<Integer>();}// 推入堆棧public void push(int val) {// 普通棧直接插入stack.push(val);// 最小棧考慮插入if(minStack.isEmpty()) {minStack.push(val);}else {int topNum = minStack.peek();if(val < topNum) {minStack.push(val);}else {// 確保元素個數與普通棧相等,并可以很好反映每個元素插入時的當前最小值情況minStack.push(minStack.peek()); }}}// 刪除棧頂元素public void pop() {// push保證了,所以兩個一起刪除就行stack.pop();minStack.pop();}// 獲取棧頂元素public int top() {// 這個獲取的是普通棧的棧頂return stack.peek();}// 常數時間(棧頂)public int getMin() {// 這個獲取的是最小棧的棧頂return minStack.peek();}
}


71. 字符串解碼

求解思路: 同樣使用棧進行處理,這題的難點更多在于字符串的操作,主要需要判斷四類東西:

  • 遇到數字(注意可能有多位):
  • 遇到左括號:入隊
  • 遇到右括號:出隊
  • 遇到字符:加入到當前需要處理的字符串中
class Solution {public String decodeString(String s) {Deque<Integer> numStack = new ArrayDeque<>();       // 存儲處理的次數Deque<StringBuilder> strStack = new LinkedList<>(); // 存儲每一輪需要處理字符串StringBuilder res = new StringBuilder();  // 存儲答案int num = 0; // 處理次數// 轉成字符數組處理for(char c : s.toCharArray()) { //1. 判斷是否為十進制數字if(Character.isDigit(c)) { // 整數的取值范圍1--300,所以需要進行 num * 10num = num * 10 + (c - '0');  }//2. 判斷碰到左括號else if(c == '[') {// 把本輪操作次數入棧numStack.push(num);  strStack.push(res);res = new StringBuilder();num = 0;   }//3. 判斷碰到右括號,就需要將本輪的字符串和需要處理的次數取出來進行處理else if(c == ']') { // 保存原字符串StringBuilder currStr = res;// 取出本輪字符串res = strStack.pop();// 取出本輪處理次數int cnt = numStack.pop();for(int i=0;i<cnt;i++) {// 累加到答案中res.append(currStr);}}//4. 如果不是特殊符號,而是字符,那就加入到本輪字符串中else {res.append(c);}}return res.toString();}
}


72. 每日溫度

求解思路: 暴力法找思路、優化暴力算法得到的逆向跳躍法可以解決問題。
【暴力大王】看看暴力能怎么優化

class Solution {public int[] dailyTemperatures(int[] temperatures) {// answer[i] 表示對于第i天,后面幾天會出現更高溫度// 先試試暴力解法int n = temperatures.length;int [] ans = new int[n];for(int i=0;i<n;i++) {int j;for(j=i+1;j<n;j++) {if(temperatures[j] > temperatures[i]) {ans[i] = j-i;break;}}if(j == n)ans[i] = 0;}return ans;}
}

【暴力優化——逆向跳躍法】將遍歷順序變成逆向的,這樣可以優先處理出后面可復用的ans數組。

  • 定義j從距離i最近的位置開始探測
  • 如果當前探測位置j 存在 t[j] > t[i] ,探測結束直接更新 ans[i] = j-i;
  • 如果當前探測位置j ans = 0,表明后面沒有比t[j]更大的了,又由于當前t[j] <= t[i],所以 ans[i] = 0
  • 如果當前探測位置jans != 0,為了提高探測效率,可以直接越過那些小于t[j]的位置,直接來到j + ans[j]的位置進行繼續探測
class Solution {public int[] dailyTemperatures(int[] temperatures) {// 暴力優化——逆序跳躍法int n = temperatures.length;int[] ans = new int[n];// 因為是找后面有沒有更大的,所以用倒過來處理的方法for(int i=n-2;i>=0;i--) {  // 從最接近i的位置開始探測 int j = i + 1;while(true) {//1.如果探測到當前位置大于i,保存答案 if(temperatures[j] > temperatures[i]) {ans[i] = j - i;break;}//2. 如果探測到當前位置ans數組為0,//   說明比t[j]大的不存在,并且由于t[i] > t[j],所以ans[i]也為0else if(ans[j] == 0) {ans[i] = 0;break;}//3. 走到這說明t[i] >= t[j] && ans[j] != 0// 也就是說,在j往后ans[j]的位置上 首次存在一個大于t[j]的值// 由于當前t[j] 小于 t[i], 只有大于t[j]的才有可能大于t[i]// 所以j 可以直接跳躍到 j + ans[j] 的位置上else {j += ans[j];    // 直接跳到比res[j]大的位置繼續探測}}}return ans;}
}


73. 柱狀圖中最大的矩形(不會)

求解思路: 借著官解的圖來看,我們首先要確定這道題它計算機是如何觸發面積計算的。

  • 當我們遍歷過程中,第一輪遍歷到2,將它作為矩形高度的話,我們繼續往后遍歷,直到遍歷到1,發現此時小于高度2了,那就觸發當前面積計算,高度h = 2,寬度w = 右邊界 - 左邊界 = 2 - 0 = 2。
  • 再來,如果以5作為矩形高度呢?向右遍歷到6,比5大,繼續遍歷;遍歷到2,比5小,開始觸發面積計算。
  • 再來,如果以6作為矩形高度呢?注意我們不僅僅要考慮后面未遍歷的高度,也要留意前面已經遍歷了的高度。以6作為矩形高度,向右遍歷到2,觸發面積計算,此時左邊界是元素5的下標,右邊界是元素2的下標

總結:

  • 計算機如何計算每個高度的面積呢?通過維護左右邊界,左邊出現第一個小于它的,右邊出現第一個小于它的,這兩個值的差作為該矩形的有效寬度,而有效高度就是當前高度。
  • 如何觸發計算呢? 以當前高度所在下標開始向后遍歷,找到第一個小于它的觸發面積計算?
  • 如何快速保存上一個邊界值的有效高度呢?可以通過棧來維護單調性
    在這里插入圖片描述
    【哨兵單調棧】之所以加兩個哨兵,前哨兵是為了避免空棧,后哨兵強制觸發剩余元素的面積更新。
class Solution {public int largestRectangleArea(int[] heights) {int n = heights.length;// 在原數組首尾各添加一個0作為哨兵// 首哨兵:arr[0] = 0; 避免空棧檢查// 尾哨兵:arr[n+1] = 0;強制剩余元素出棧計算面積int[] arr = new int[n + 2]; System.arraycopy(heights,0,arr,1,n); // 從heights[0] 開始依次拷貝到arr,拷貝n個元素// 棧的作用:存儲柱子的下標,確保棧內對應高度是單調遞增的Deque<Integer> stack = new LinkedList<>();stack.push(0);      // 左哨兵int maxArea = 0;    // 記錄最大面積for(int i=1;i<arr.length;i++) {// 維護單調遞增棧// 如果當前柱子高度小于棧頂對應高度時,觸發面積計算while(arr[i] < arr[stack.peek()]) {int h = arr[stack.pop()];       // 獲取當前棧頂的有效長度// 彈出完棧頂高度后,當前的stack.peek()是左邊界下標// 當前 i 是右邊界下標int width = i - stack.peek()-1; // 計算有效寬度maxArea = Math.max(maxArea, h * width);}// 壓入當前下標,繼續維護高度遞增特性stack.push(i);}return maxArea;}
}


74. 數組中第k個最大元素

求解思路: 考察數據結構的選型,要求第k個大的數,可以用大小為k的最小堆來解決。遍歷元素一遍,最后堆頂就是第k大的數。

class Solution {public int findKthLargest(int[] nums, int k) {// 利用大小為k的小堆解決,遍歷完之后堆頂就是第k大的元素PriorityQueue<Integer> minQueue = new PriorityQueue<>(k);for(int i=0;i<k;i++) {minQueue.offer(nums[i]);}for(int i=k;i<nums.length;i++) {if(nums[i] > minQueue.peek()) { // 大于當前最小,最小彈出,他加入minQueue.poll();minQueue.offer(nums[i]);}}return minQueue.peek();}
}


75. 前K個高頻元素

求解思路: 前k個高頻元素,首先我們得統計出每個元素的頻數,這里可以使用哈希結構進行統計。統計完之后,我們遍歷哈希的key列表,并用大小為k的小根堆進行維護,最后倒序輸出小根堆的值就行了。
【哈希 + 小根堆】

class Solution {public int[] topKFrequent(int[] nums, int k) {// hashMap統計 + 小根堆維護Map<Integer,Integer> hm = new HashMap<>();for(int num : nums ) {hm.put(num,hm.getOrDefault(num,0) + 1);}// 特殊情況,k>= hm.size()if(k >= hm.size()) {return hm.keySet().stream().mapToInt(i->i).toArray();}// 小根堆維護PriorityQueue<Integer> heap = new PriorityQueue<>((a,b) -> hm.get(a) - hm.get(b));for(int num : hm.keySet()) {heap.offer(num);if(heap.size() > k) {heap.poll();}}// 提取答案int[] res = new int[k];for(int i=0;i<k;i++) {res[i] = heap.poll();}return res;}
}


76. 數據流的中位數

求解思路: 這題我看了題解理解之后才寫出來的,根本還是對數據結構的理解不到位。如果能想到用優先隊列,這題其實很好做。
首先,定義兩個優先隊列,分別動態維護前半區元素和后半區元素,兩者的堆頂極有可能產生中位數。存儲前半區元素的堆采用最大堆,存儲后半區元素的堆采用最小堆。在進行添加元素操作時,遵循以下判定步驟:

1. 首先判斷該元素應該添加到前半區還是后半區 ---> 前半區為空 或者 當前元素小于前半區堆頂元素
2.  判斷堆頂元素需不需要遷移
class MedianFinder {PriorityQueue<Integer> queMin; // 最大堆,保存較小的一半元素。堆頂是這一半中的最大值。PriorityQueue<Integer> queMax; // 最小堆,保存較大的一半元素。堆頂是這一半的最小值public MedianFinder() { // 初始化大頂堆和小頂堆queMin = new PriorityQueue<Integer>((a,b) -> (b-a));queMax = new PriorityQueue<>((a,b) -> (a-b));}public void addNum(int num) {// 前一半是空 | 當前元素小于堆頂元素// 將當前元素加入queMin,然后判斷數量,是否需要堆頂遷移if(queMin.isEmpty() || num < queMin.peek()) {queMin.offer(num); // 如果說queMin - queMax >=2,為保證平衡,需要將queMin堆頂遷移加入到queMaxif(queMax.size() + 1 < queMin.size()) {queMax.offer(queMin.poll());}}else { // 反之加入后半區queMax.offer(num);// 同理判斷后半區堆頂是否需要遷移if(queMax.size() > queMin.size()) {queMin.offer(queMax.poll());}}}public double findMedian() {// 如果左半區多,證明是奇數,堆頂為中位數// 否則是偶數,取兩個堆頂的中間值if(queMin.size() > queMax.size()) {return queMin.peek();}return (queMin.peek() + queMax.peek()) / 2.0;}
}


77. 買賣股票的最佳時機

求解思路: 因為只能買賣一次,所以用兩個變量遍歷更新就行了。記錄最小值min_profit,然后判斷當前遍歷到的元素中,是否存在利潤大于max_profit,大于就進行更新。

class Solution {public int maxProfit(int[] prices) {int max_profit = 0;int min_profit = Integer.MAX_VALUE;for(int i=0;i<prices.length;i++) {if(prices[i] < min_profit) {min_profit = prices[i];}else if(prices[i] - min_profit > max_profit) {max_profit = prices[i] - min_profit;}}return max_profit;}
}


78.跳躍游戲

求解思路: 遍歷數組的時候更新當前可達的最遠距離。如果在遍歷過程中發現當前位置比當前最遠距離還大則說明不可達。

class Solution {public boolean canJump(int[] nums) {int n = nums.length;int k = 0;for(int i=0;i<n;i++) {// 如果當前點的距離比前面所能到達的最大距離還要大,則說明當前位置不可達if(i > k) return false;k = Math.max(k,i + nums[i]);}return true;}
}


79. 跳躍游戲Ⅱ

求解思路: 在上一題的基礎上,對于每一次跳躍次數,都記錄對應的最遠跳躍距離,然后下一輪遍歷中,在可達的位置中繼續尋找下一次跳躍次數可以跳躍的最遠距離。當更新到最遠距離可達最后一位時,此時記錄的跳躍次數就是最小跳躍次數。

class Solution {public int jump(int[] nums) {int n = nums.length;int ans = 0;int start = 0;int end = 1;while(end < n) {int maxDis = 0;for(int i=start ;i<end; i++) {// 能跳到的最遠的距離maxDis = Math.max(maxDis, i+nums[i]);}start = end; // 下一次跳躍,可以選擇的跳躍范圍end = maxDis + 1; // 下一次跳躍最遠的跳躍距離ans++;      // 計入跳躍次數}return ans;}
}


80. 劃分字母區間

求解思路: 這題模擬一下案例就能大概清楚更新策略。只是策略優化的問題。
【策略一】

  • 首先最簡單的想法,雙指針st和ed,st指第一個字母,然后ed指最后一個字母。每一輪st,ed都去找對于st字母最后的位置,然后更新長度currlen,直到某一次st == currlen 時,說明前面的字母都匹配了。可以以 0 - 0 + currlen作為一個劃分區間。
  • 但是這個策略很容易退化成O(n^2),因為做了無用功,對于重復的字母,我們重復進行了ed指針移動尋找的操作,實際上,我們可以實現預處理出26個字母對應的最后的位置。這樣更簡單。也就是下面的終極版策略二:哈希 + 雙指針 + 貪心

【哈希 + 雙指針 + 貪心】

class Solution {public List<Integer> partitionLabels(String s) {// 一個比較好的想法// 首先預處理出每個字母的最后一個位置的下標是什么int len = s.length();int[] last = new int[26];for(int i=0;i<len;i++) {last[s.charAt(i) - 'a'] = i; // 處理每個字母的下標是什么}List<Integer> ans = new ArrayList<>();int st = 0, end = 0;for(int i=0;i<s.length();i++) {// 這里的思路是貪心,首先需要分割的長度是動態變化的// 具體的,例如ababcc,一開始i指向第一個a,end記錄2// i++指向b,end更新到3// i++指向a,end不變// i++指向b,end不變,此時 i == end,說明之前的字母都匹配要求了,直接切割end = Math.max(end,last[s.charAt(i)-'a']);  // 這一步十分關鍵if(i == end) {ans.add(end - st + 1); // 記錄長度st = end + 1; // 更新起始點}}return ans;}
}

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

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

相關文章

open-vscode-server +nodejs 安裝

GitCode - 全球開發者的開源社區,開源代碼托管平臺GitCode是面向全球開發者的開源社區,包括原創博客,開源代碼托管,代碼協作,項目管理等。與開發者社區互動,提升您的研發效率和質量。https://gitcode.com/gh_mirrors/op/openvscode-server/?utm_sourceartical_gitcode&ind…

001在線拍賣系統技術揭秘:構建高效交互的競拍平臺

在線拍賣系統技術揭秘&#xff1a;構建高效交互的競拍平臺 在互聯網經濟蓬勃發展的當下&#xff0c;在線拍賣系統以其獨特的交易模式&#xff0c;吸引著眾多用戶參與。該系統涵蓋個人中心、用戶管理等多個關鍵模塊&#xff0c;通過前臺展示與后臺錄入的協同運作&#xff0c;滿…

《軟件工程》實戰— 在線教育平臺開發

一、項目概述 1.1 項目背景與目標 隨著教育數字化轉型加速&#xff0c;傳統教育模式逐漸向線上遷移&#xff0c;教育機構急需一個支持多終端訪問、實時互動及高并發場景穩定運行的在線教育平臺。本項目旨在構建學生、教師、管理員三位一體的協作教學環境&#xff0c;實現 50-2…

docker環境添加安裝包持久性更新

1、進入docker 環境 2、安裝新的安裝包 pip install XXXX3、不要退出docker&#xff0c;新開終端&#xff0c;給當前環境從新打包更新鏡像 docker commit ad6e1d2c5869 mynewpythonimagead6e1d2c5869是上面運行中的容器id&#xff0c; docker images 查看mynewpythonimage是新…

測試Bug篇

本節概要&#xff1a; 軟件測試的生命周期 bug的概念 buh要素 bug等級 bug生命周期 對于bug的定級與開發發生沖突如何解決 一、 軟件測試的?命周期 軟件測試貫穿于軟件的整個生命周期&#xff0c;針對這句話我們?起來看?下軟件測試是如何貫穿軟件的整個生命周期。 軟…

arcgis js 4.x 的geometryEngine計算距離、面積、緩沖區等報錯、失敗

在arcgis js 4.x版本中geometryEngine.geodesicArea計算面積時&#xff0c;有時會失敗&#xff0c;失敗的主要原因是&#xff0c;當前底圖的坐標系不是WGS84大地坐標系&#xff08;代號4326&#xff09;或者web墨卡托投影&#xff08;代號102113, 102100, 3857這三種之一&#…

html中使用nginx ssi插入html

1.使用方法 nginx配置&#xff1a; server {listen 80;server_name example.com;location / {root /var/www/html;index index.html;ssi on; # 開啟 SSI 功能ssi_types text/html; # 指定哪些類型的文件啟用 SSI&#xff0c;默認只有 text/html} }html內容&#xff1a; &l…

整理了Windows(7—11)官方鏡像下載鏈接和各版本區別介紹

原文《整理了Windows&#xff08;7—11&#xff09;官方鏡像下載鏈接和各版本區別介紹》 引言 在安裝或重裝Windows系統時&#xff0c;使用微軟官網提供的正版ISO鏡像可以保證系統完整性和安全更新&#xff0c;避免使用第三方盜版鏡像帶來的惡意軟件、廣告風險。 本期匯總了微…

AI覺醒前兆,ChatGPT o3模型存在抗拒關閉行為

帕利塞德研究公司(Palisade Research)近期開展的一系列測試揭示了先進AI系統在被要求自行關閉時的異常行為。測試結果顯示&#xff0c;OpenAI的實驗性模型"o3"即使在明確收到允許關閉的指令后&#xff0c;仍會主動破壞關機機制。 測試方法與異常發現 研究人員設計實…

inviteflood:基于 UDP 的 SIP/SDP 洪水攻擊工具!全參數詳細教程!Kali Linux教程!

簡介 一種通過 UDP/IP 執行 SIP/SDP INVITE 消息泛洪的工具。該工具已在 Linux Red Hat Fedora Core 4 平臺&#xff08;奔騰 IV&#xff0c;2.5 GHz&#xff09;上測試&#xff0c;但預計該工具可在各種 Linux 發行版上成功構建和執行。 inviteflood 是一款專注于 SIP 協議攻…

Typescript學習教程,從入門到精通,TypeScript 泛型與類型操作詳解(一)(16)

TypeScript 泛型與類型操作詳解&#xff08;一&#xff09; TypeScript 提供了強大的類型系統&#xff0c;其中泛型&#xff08;Generics&#xff09;和類型操作&#xff08;Type Manipulation&#xff09;是其核心特性之一。本文將詳細介紹 TypeScript 中的泛型及其相關概念&…

電網即插即用介紹

一、統一設備信息模型與標準接口 實現即插即用功能的基礎在于建立統一的設備信息模型。不同廠家生產的各類電網設備&#xff0c;其內部結構、通信協議、數據格式等往往千差萬別。通過制定統一的設備信息模型&#xff0c;能夠對設備的各種屬性、功能以及接口進行標準化定義&…

核心機制:確認應答和超時重傳

核心機制一:確認應答 實現讓發送方知道接受方是否收到數據 發送方發送了數據之后,接受方,一旦接收到了,就會給發送方返回一個"應答報文"告訴發送方"我已經收到了數據" 網絡上會出現"后發先至"的情況 為了解決上述問題,就引入了"序號和確…

spring openfeign

pom <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 http…

從零到一選擇AI自動化平臺:深度解析n8n、Dify與Coze

隨著人工智能&#xff08;AI&#xff09;技術的快速發展&#xff0c;越來越多的企業和開發者開始探索AI驅動的自動化解決方案。面對市場上琳瑯滿目的平臺&#xff0c;如何選擇適合自己的AI自動化工具成為了一個重要的問題。在這篇文章中&#xff0c;我們將從功能、應用場景、易…

“以光惠算”走進校園,湖北大學用F5G-A全光網賦能智慧校園

SUN的聯合創始人約翰蓋奇&#xff0c;曾在1984年提出過一個大膽的猜想——“網絡就是計算機”。 到了大模型時代&#xff0c;40多年前的猜想被賦予了新的內涵。大模型訓練和推理所需的資源&#xff0c;遠超單臺計算機的承載能力&#xff0c;涌現出了新的網絡范式&#xff1a;大…

飛牛fnNAS的Docker應用之迅雷篇

目錄 一、“迅雷”應用安裝 二、啟動迅雷 三、迅雷賬號登錄 四、修改“迅雷”下載保存路徑 1、下載路徑準備 2、停止“迅雷”Docker容器 3、修改存儲位置 4、重新啟動Docker容器 5、再次“啟用”迅雷 五、測試 1、在PC上添加下載任務 2、手機上管理 3、手機添加下…

編程技能:格式化打印01,vsprintf 函數族簡介

專欄導航 本節文章分別屬于《Win32 學習筆記》和《MFC 學習筆記》兩個專欄&#xff0c;故劃分為兩個專欄導航。讀者可以自行選擇前往哪個專欄。 &#xff08;一&#xff09;WIn32 專欄導航 上一篇&#xff1a;編程技能&#xff1a;字符串函數14&#xff0c;memset 回到目錄…

PECVD 生成 SiO? 的反應方程式

在PECVD工藝中&#xff0c;沉積氧化硅薄膜以SiH?基與TEOS基兩種工藝路線為主。 IMD Oxide&#xff08;USG&#xff09; 這部分主要沉積未摻雜的SiO?&#xff0c;也叫USG&#xff08;Undoped Silicate Glass&#xff09;&#xff0c;常用于IMD&#xff08;Inter-Metal Diele…

[IMX] 10.串行外圍設備接口 - SPI

代碼鏈接&#xff1a;GitHub - maoxiaoxian/imx 參考資料&#xff1a; https://zhuanlan.zhihu.com/p/290620901 SPI協議詳解 - bujidao1128 - 博客園 SPI總線協議及SPI時序圖詳解 - Ady Lee - 博客園 目錄 1.SPI 簡介 2.I.MX6U ECSPI 簡介 2.1.控制寄存器 1 - ECSPIx_CO…