代碼隨想錄-Day07

454. 四數相加 II

給你四個整數數組 nums1、nums2、nums3 和 nums4 ,數組長度都是 n ,請你計算有多少個元組 (i, j, k, l) 能滿足:

0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0

示例 1:

輸入:nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2]
輸出:2
解釋:
兩個元組如下:

  1. (0, 0, 0, 1) -> nums1[0] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0
  2. (1, 1, 0, 0) -> nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0
class Solution {public int fourSumCount(int[] A, int[] B, int[] C, int[] D) {Map<Integer, Integer> countAB = new HashMap<Integer, Integer>();for (int u : A) {for (int v : B) {countAB.put(u + v, countAB.getOrDefault(u + v, 0) + 1);}}int ans = 0;for (int u : C) {for (int v : D) {if (countAB.containsKey(-u - v)) {ans += countAB.get(-u - v);}}}return ans;}
}

這段代碼定義了一個名為 Solution 的類,其中包含一個方法 fourSumCount。這個方法用于解決四數之和問題:給定四個整數數組 A, B, C, 和 D,計算有多少個由一個來自 A 和一個來自 B 的數以及一個來自 C 和一個來自 D 的數構成的四元組,它們的和為 0。

邏輯分析:

  1. 初始化哈希表(Map):首先,創建一個哈希表 countAB 用于存儲數組 AB 中元素兩兩兩兩數之和的頻次。鍵為和的值,值為該和出現的次數。

  2. 計算 AB 的組合和:遍歷數組 AB 中的所有元素,計算它們的和,并在哈希表 countAB 中累積這些和的計數,使用 getOrDefault 方法來簡化計數累加邏輯,如果鍵不存在則默認值為0,然后加1。

  3. 計算四數和為0的組合數:接著,遍歷數組 CD 的元素,對于每一對 uv,檢查 countAB 是否包含 -u - v 這個鍵(即如果存在一個來自 AB 的和與 uv 之和為相反數),如果存在,則累加該和在 countAB 中的頻次到答案 ans

  4. 返回結果:最后,返回累計的滿足條件的四數之和為0的組合總數 ans

代碼特點與優化:

  • 空間換時間:通過預計算 AB 的所有組合和及其頻次,將原本需要四重循環的問題轉換為兩重循環加上查找,顯著提高了效率。
  • 哈希表(Map)使用:利用哈希表的高效查找特性,簡化了尋找特定和的操作,從原本可能的線性查找降為接近常數時間。
  • 代碼簡潔性:雖然邏輯清晰,但在實際應用中可能還需考慮邊界條件處理(如輸入數組長度為0的情況),以及優化點(如適當處理大數以避免溢出問題)。

綜上所述,這段代碼提供了一種有效且相對高效求解四數之和為0的組合數目的方法,體現了哈希表在優化搜索問題中的應用。

383. 贖金信

給你兩個字符串:ransomNote 和 magazine ,判斷 ransomNote 能不能由 magazine 里面的字符構成。

如果可以,返回 true ;否則返回 false 。

magazine 中的每個字符只能在 ransomNote 中使用一次。

示例 1:

輸入:ransomNote = “a”, magazine = “b”
輸出:false
示例 2:

輸入:ransomNote = “aa”, magazine = “ab”
輸出:false
示例 3:

輸入:ransomNote = “aa”, magazine = “aab”
輸出:true

class Solution {public boolean canConstruct(String ransomNote, String magazine) {if (ransomNote.length() > magazine.length()) {return false;}int[] cnt = new int[26];for (char c : magazine.toCharArray()) {cnt[c - 'a']++;}for (char c : ransomNote.toCharArray()) {cnt[c - 'a']--;if(cnt[c - 'a'] < 0) {return false;}}return true;}
}

這段代碼定義了一個名為 Solution 的類,其中包含一個方法 canConstruct。這個方法用于判斷能否通過重新排列給定的雜志字符串 magazine 中的字符,來拼寫出勒索要贖金信字符串 ransomNote。如果可以,則返回 true;如果不可以,則返回 false

邏輯分析:

  1. 長度檢查:首先,進行一個簡單的長度檢查,如果贖金信的長度大于雜志字符串長度,顯然無法構造,直接返回 false

  2. 字符計數數組初始化:聲明一個長度為26的小寫英文字母表數組 cnt,用于計數雜志字符串中每個字符出現的次數。這里利用了小寫字母’a’到’z’在ASCII碼表中連續的特性,減去’a’后即可映射到數組的索引。

  3. 計算雜志字符頻次:遍歷雜志字符串 magazine 的字符,逐個對應回字符在數組 cnt 中計數加1。利用了字符與其在ASCII碼的關系,減去 ‘a’ 來索引數組位置。

  4. 檢查贖金信字符可用性:接著,遍歷贖金信 ransomNote 的字符,逐個檢查該字符在 cnt 數組中的計數是否足夠。如果有足夠的字符,就將計數減1;如果不夠(即計數小于0),說明該字符在雜志中數量不足,直接返回 false

  5. 返回結果:如果成功遍歷完贖金信所有字符且未返回,說明可以構造出來,最后返回 true

代碼特點:

  • 空間效率:使用固定大小的計數數組而非哈希表減少了空間消耗,因為只考慮了小寫字母,局限了字符范圍。
  • 時間效率:兩重循環,時間復雜度為O(len(ransomNote) + len(magazine)),其中len表示字符串長度,因為分別遍歷了兩次字符串。
  • 簡潔性:直接利用字符編碼特性進行索引映射,減少了額外的字符判斷和映射邏輯。

綜上所述,此方法通過直接計數字符頻次并檢查是否足夠來判斷是否能構造贖金信,是一種直觀且效率較高的實現方式。

15. 三數之和

給你一個整數數組 nums ,判斷是否存在三元組 [nums[i], nums[j], nums[k]] 滿足 i != j、i != k 且 j != k ,同時還滿足 nums[i] + nums[j] + nums[k] == 0 。請

你返回所有和為 0 且不重復的三元組。

注意:答案中不可以包含重復的三元組。

示例 1:

輸入:nums = [-1,0,1,2,-1,-4]
輸出:[[-1,-1,2],[-1,0,1]]
解釋:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元組是 [-1,0,1] 和 [-1,-1,2] 。
注意,輸出的順序和三元組的順序并不重要。
示例 2:

輸入:nums = [0,1,1]
輸出:[]
解釋:唯一可能的三元組和不為 0 。
示例 3:

輸入:nums = [0,0,0]
輸出:[[0,0,0]]
解釋:唯一可能的三元組和為 0 。

class Solution {public List<List<Integer>> threeSum(int[] nums) {int n = nums.length;Arrays.sort(nums);List<List<Integer>> ans = new ArrayList<List<Integer>>();// 枚舉 afor (int first = 0; first < n; ++first) {// 需要和上一次枚舉的數不相同if (first > 0 && nums[first] == nums[first - 1]) {continue;}// c 對應的指針初始指向數組的最右端int third = n - 1;int target = -nums[first];// 枚舉 bfor (int second = first + 1; second < n; ++second) {// 需要和上一次枚舉的數不相同if (second > first + 1 && nums[second] == nums[second - 1]) {continue;}// 需要保證 b 的指針在 c 的指針的左側while (second < third && nums[second] + nums[third] > target) {--third;}// 如果指針重合,隨著 b 后續的增加// 就不會有滿足 a+b+c=0 并且 b<c 的 c 了,可以退出循環if (second == third) {break;}if (nums[second] + nums[third] == target) {List<Integer> list = new ArrayList<Integer>();list.add(nums[first]);list.add(nums[second]);list.add(nums[third]);ans.add(list);}}}return ans;}
}

這段代碼是用于解決“三數之和”問題的Java實現,給定一個整數數組 nums,找出數組中所有和為0的三個數的組合,并返回這些組合的列表。以下是代碼的邏輯解析:

  1. 初始化:

    • 首先對數組 nums 進行排序,便于后續的雙指針操作。
    • 初始化一個空的結果列表 ans,用于存儲滿足條件的三元組。
  2. 外層循環枚舉 a:

    • 用變量 first 作為外層循環變量,從0遍歷到數組長度。

    • 避度處理重復值:若當前 first 不是第一個元素且與前一個元素值相同,則跳過,避免重復解。

    • 初始化 third 指針為數組最后一個元素,目標值 target-nums[first],以使 a + b + c = 0

  3. 中層循環枚舉 b:

    • 用變量 second 作為中層循環變量,從 first + 1 開始遍歷。
    • 處理重復值:若 second 不是 first + 1 且與前一個元素值相同,則跳過,避免重復解。
    • 維護 third 指針位置,使其滿足 nums[second] + nums[third] <= target,不斷向左移動直到符合條件或 second == third
    • secondthird 重合,說明后續增加的 second 不可能再滿足條件,直接跳出循環。
  4. 檢查并添加解:

    • nums[second] + nums[third] == target 成立時,說明找到了一個解。
    • nums[first], nums[second], nums[third] 加入臨時列表 list,然后將 list 添加到結果列表 ans 中。
  5. 返回結果:

    • 遍歷完成后返回結果列表 ans

這段代碼通過排序和雙指針技巧高效地解決了三數之和問題,時間復雜度主要受排序影響為O(nlogn),空間復雜度為O(n)(最壞情況下存儲所有解)。注意,由于代碼中存在若干處邏輯錯誤(如循環更新語句末尾的 ++ 應替換為 ;),修正后才能正常運行。

18. 四數之和

給你一個由 n 個整數組成的數組 nums ,和一個目標值 target 。請你找出并返回滿足下述全部條件且不重復的四元組 [nums[a], nums[b], nums[c], nums[d]] (若兩個四元組元素一一對應,則認為兩個四元組重復):

0 <= a, b, c, d < n
a、b、c 和 d 互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意順序 返回答案 。

示例 1:

輸入:nums = [1,0,-1,0,-2,2], target = 0
輸出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
示例 2:

輸入:nums = [2,2,2,2,2], target = 8
輸出:[[2,2,2,2]]

class Solution {public List<List<Integer>> fourSum(int[] nums, int target) {List<List<Integer>> quadruplets = new ArrayList<List<Integer>>();if (nums == null || nums.length < 4) {return quadruplets;}Arrays.sort(nums);int length = nums.length;for (int i = 0; i < length - 3; i++) {if (i > 0 && nums[i] == nums[i - 1]) {continue;}if ((long) nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) {break;}if ((long) nums[i] + nums[length - 3] + nums[length - 2] + nums[length - 1] < target) {continue;}for (int j = i + 1; j < length - 2; j++) {if (j > i + 1 && nums[j] == nums[j - 1]) {continue;}if ((long) nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) {break;}if ((long) nums[i] + nums[j] + nums[length - 2] + nums[length - 1] < target) {continue;}int left = j + 1, right = length - 1;while (left < right) {long sum = (long) nums[i] + nums[j] + nums[left] + nums[right];if (sum == target) {quadruplets.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));while (left < right && nums[left] == nums[left + 1]) {left++;}left++;while (left < right && nums[right] == nums[right - 1]) {right--;}right--;} else if (sum < target) {left++;} else {right--;}}}}return quadruplets;}
}

這段代碼是一個Java實現,用于解決尋找數組中所有和為目標值的四數組合(4Sum)的問題。給定一個整數數組 nums 和一個目標整數 target,如果 nums 中存在四個元素 a, b, c, 和 d 使得 a + b + c + d 的和等于 target,那么找出所有這樣的四元組。返回一個二維列表,其中每個列表表示一個四元組。

解析代碼邏輯:

  1. 初始化: 創建一個空的 quadruplets 列表,用于存放所有滿足條件的四元組。如果輸入數組為空或長度小于4,直接返回空列表。

  2. 排序: 對 nums 進行排序,便于使用雙指針法減少搜索空間。

  3. 三層循環:

    • 外層循環 (i): 遍歷數組,避免重復,若當前數與前一個相同則跳過。
    • 中層循環 (j): 從 i+1 開始,同樣避免重復,計算四個數之和的上下界,提前剪枝。
    • 雙指針法 (left, right): 在 j+1length-1 之間,尋找另外兩個數,使得四數之和等于 target。若找到,添加四元組到結果列表并跳過重復值,否則根據和調整指針。
  4. 返回結果: 最后返回所有滿足條件的四元組列表 quadruplets

關鍵點:

  • 排序 是基礎,使得雙指針法可行。
  • 剪枝策略 減少不必要的循環,提高效率。
  • 避免重復 通過跳過相同元素,確保結果唯一性。

注意:代碼中有部分地方需要修正以確保正確性,例如 quadruplets.add(Arrays.asList(...)) 應該為 quadruplets.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]))。此外,確保所有邏輯分支和邊界條件正確處理。

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

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

相關文章

系統磁盤高級管理、lvm例子、創建pv、創建VG、創建lv、磁盤擴展

LVM&#xff1a; 邏輯卷&#xff0c;動態調整分區大小&#xff0c;擴展性好 創建pv pvcreate &#xff1a; 將實體 partition 創建成為 PV &#xff1b; pvscan &#xff1a; 搜尋目前系統里面任何具有 PV 的磁盤&#xff1b; pvdisplay &#xff1a; 顯示出目前系統上面…

GNSS仿真測試之三種常用坐標系與轉換

作者介紹 在當今的全球導航衛星系統&#xff08;GNSS&#xff09;技術領域&#xff0c;仿真測試是評估和驗證GNSS接收機性能的關鍵環節&#xff0c;全球導航衛星系統&#xff08;GNSS&#xff09;仿真測試是確保GNSS接收機和導航解決方案在實際部署前能夠正確、可靠地工作的關鍵…

【git】學習記錄: 貯藏功能

Git 貯藏修改是一種臨時存儲工作目錄中已經修改但尚未提交的更改的機制。通過貯藏修改&#xff0c;你可以將當前的工作目錄狀態保存起來&#xff0c;以便你可以在之后的時間點重新應用這些更改&#xff0c;或者在不同的分支間切換時避免沖突。 要使用 Git 貯藏修改&#xff0c…

Linux(centos)常用命令

Linux&#xff08;Centos&#xff09;常用命令使用說明文檔 切換到/home目錄下 使用cd命令切換目錄&#xff0c;例如&#xff1a; cd /home列出/home目錄下的所有文件 使用ls命令列出目錄下的文件和子目錄&#xff0c;例如&#xff1a; ls /home新建目錄dir1 使用mkdir命…

頭歌OpenGauss數據庫-I.復雜查詢第1關:獲取前N名成績

本關任務&#xff1a;編寫函數來實現獲取前N名成績的方法。 提示&#xff1a;前面的實驗沒有提供編寫自定義函數的示例&#xff0c;需要參考OpenGauss數據庫文檔學習自定義函數的使用。 score表內容如下&#xff1a; IdScore13.5223.6534.2343.8554.2363.65 --#請在BEGIN - END…

python windows 開發.exe程序筆記

import win32api import win32gui import win32con import time import tkinter as tk## pyinstaller --onefile t4.py 將python 代碼打包為windows可執行文件 .exe ## airtext 大漠 def clickGoogle():hw win32gui.FindWindow("Chrome_WidgetWin_1", "新標…

解決Redis 緩存雪崩(過期時間不一致) 和 緩存穿透(黑名單)

解決Redis 緩存雪崩&#xff08;過期時間不一致&#xff09; 和 緩存穿透&#xff08;黑名單&#xff09; public Product getdetailById(Integer id) {String key "product." id;// 查詢黑名單中是否有該keyBoolean b hashOperations.hasKey(PROODUCT_DETAIL_B…

算法 Hw7

Hw 7 Graph Algorithm 1 Edge detection2 Reachability3 Bitonic shortest paths 1 Edge detection 由 Cut Property 可知&#xff1a;如果 e 是從某個集合 S 到補集 V?S 的開銷最小的邊&#xff0c;則 e 一定所有最小生成樹中。 由 Cycle Property 可知&#xff1a;如果 e 是…

Gradle常見問題及總結

使用android studio開發項目&#xff0c;難免遇到gradle相關的錯誤&#xff0c;在此總結。 gradle插件與gradle home版本關系錯誤 參考更新 Gradle Gradle下載太慢 Index of /gradle/ (tencent.com) 是國內下載地址,手動下載對應版本即可 緩存不刷新 問題描述 maven發布…

jenkins插件之xunit

分析測試工具執行的結果&#xff0c;并圖形化&#xff0c;比如phpunit&#xff0c;phpstan,可分析junit格式的結果 安裝jenkins插件 搜索xunit并安裝 項目配置 配置 - Build Steps 您的項目 - 配置 - Build Steps, 新增 Run with timeout 超時時間根據實際情況配置 Build…

Day38 貪心算法part05

LC435無重疊區間(未掌握) 思路&#xff1a;先對數組進行排序&#xff0c;找到非重疊的區間的個數&#xff0c;然后區間的總數減去非重疊區間的個數即是需要移除的區間的個數與LC452用最少數量的箭引爆氣球類似&#xff0c;但是不同的是[1,2]和[2,3]在此題并不是重疊區間但是在…

oracle怎么處理json格式

向數據庫導入json相關jar包 loadjava -r -f -u bsuser/XXXX192.168.10.31/bsorcl json.jar 要刪除的話&#xff0c;刪除指定jar dropjava -u bsuser/XXXX192.168.10.31/bsorcl json.jar select * from user_java_classes 然后我們就可以取到json串中任意節點的值

Linux完整版命令大全(四)

2. linux系統設置命令 alias 功能說明&#xff1a;設置指令的別名。語  法&#xff1a;alias[別名][指令名稱]補充說明&#xff1a;用戶可利用alias&#xff0c;自定指令的別名。若僅輸入alias&#xff0c;則可列出目前所有的別名設置。 alias的效力僅及于該次登入的操作。…

行列視(RCV)部署在互聯網還是部署在企業內部?

行列視&#xff08;RCV&#xff09;的部署方式可以根據企業的具體需求和情況來靈活選擇。它既可以部署在互聯網上&#xff0c;也可以部署在企業內部。 對于希望實現遠程訪問、多地點協同工作或者與第三方服務集成等需求的企業&#xff0c;可以選擇將行列視&#xff08;RCV&…

Postgresql源碼(129)JIT函數中如何使用PG的類型llvmjit_types

0 總結 llvmjit_types文件分三部分 類型定義&#xff1a;llvm通過變量找到對應結構體的定義&#xff0c;在通過結構體內的偏移量宏使用成員變量。模版函數定義&#xff1a; 第一&#xff1a;AttributeTemplate被當做一個函數屬性的模板&#xff08;例如nofree、nosync等clang…

SpringBoot項目中redis序列化和反序列化LocalDateTime失敗

實體類中包含了LocalDateTime 類型的屬性&#xff0c;把實體類數據存入Redis后變成這樣&#xff1a; 此時&#xff0c;存入redis不會報錯&#xff0c;但是從redis獲取的時候&#xff0c;會報錯&#xff1a; com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Ca…

Springboot項目打包:將依賴的jar包輸出到指定目錄

場景 公司要對springboot項目依賴的jar包進行升級&#xff0c;但是遇到一個問題&#xff0c;項目打包之后&#xff0c;沒辦法看到他里面依賴的jar包&#xff0c;版本到底是不是升上去了&#xff0c;沒辦法看到。 下面是項目打的jar包 我們通過反編譯工具jdgui&#xff0c;來…

VUE3和VUE2

VUE3和VUE2 上一篇文章中&#xff0c;我們對VUE3進行了一個初步的認識了解&#xff0c;本篇文章我們來進一步學習一下&#xff0c;順便看一下VUE2的寫法VUE3是否能做到兼容&#x1f600;。 一、新建組件 我們在components中新建一個組件&#xff0c;名稱為Peron&#xff0c;…

緩存降級

當Redis緩存出現問題或者無法正常工作時,需要有一種應對措施,避免直接訪問數據庫而導致整個系統癱瘓。緩存降級就是這樣一種機制。 主要的緩存降級策略包括: 本地緩存降級 當Redis緩存不可用時,可以先嘗試使用本地進程內緩存,如Guava Cache或Caffeine等。這樣可以減少對Redis…

陰影映射(線段樹)

實時陰影是電子游戲中最為重要的畫面效果之一。在計算機圖形學中&#xff0c;通常使用陰影映射方法來實現實時陰影。 游戲開發部正在開發一款 2D 游戲&#xff0c;同時希望能夠在 2D 游戲中模仿 3D 游戲的光影效果&#xff0c;請幫幫游戲開發部&#xff01; 給定 x-y 平面上的…