LeetCode_哈希表

哈希表(散列表)

  • 一、哈希表
  • 二、有效的字母異位詞
    • 1、有效的字母異位詞(力扣242)
    • 2、贖金信(力扣383)
    • 3、字母異位詞分組(力扣49)
    • 4、找到字符串中所有字母異位詞(力扣438)
  • 三、兩個數組的交集
    • 1、兩個數組的交集(力扣349)
    • 2、兩個數組的交集 II(力扣350)
  • 三、其他的哈希表題
    • 1、快樂數(力扣202)
    • 2、兩數之和(力扣1)
    • 3、四數相加 II(力扣454)
    • 4、三數之和(力扣15)
    • 5、四數之和(力扣18)

一、哈希表

1.總結一下,當我們遇到了要快速判斷一個元素是否出現集合里的時候,就要考慮哈希法。但是哈希法也是犧牲了空間換取了時間,因為我們要使用額外的數組,set或者是map來存放數據,才能實現快速的查找。如果在做面試題目的時候遇到需要判斷一個元素是否出現過的場景也應該第一時間想到哈希法!
2.當數據量比較少時,可以考慮使用數組。直接使用set 不僅占用空間比數組大,而且速度要比數組慢,set把數值映射到key上都要做hash計算的。不要小瞧這個耗時,在數據量大的情況,差距是很明顯的。

二、有效的字母異位詞

1、有效的字母異位詞(力扣242)

//1.t是s的異位詞等價于「兩個字符串排序后相等」public static boolean isAnagram(String s, String t) {if (s.length() != t.length()){return false;}char[] c1 = s.toCharArray();char[] c2 = t.toCharArray();Arrays.sort(c1);Arrays.sort(c2);return Arrays.equals(c1,c2);}
//2.輸入字符串不包含 unicode 字符public static boolean isAnagram(String s, String t) {if (s.length() != t.length()){return false;}int[] arr = new int[26];for (int i = 0; i < s.length(); i++) {arr[s.charAt(i) - 'a'] ++;}for (int i = 0; i < t.length(); i++) {arr[t.charAt(i) - 'a'] --;if (arr[t.charAt(i) - 'a'] < 0){return false;}}return true;}

如果輸入字符串包含 unicode 字符,那就只能使用哈希表了, JAVA的char類型是支持unicode的

//3.輸入字符串包含 unicode 字符public static boolean isAnagram(String s, String t) {if (s.length() != t.length()){return false;}Map<Character,Integer> map = new HashMap<>();for (int i = 0; i < s.length(); i++) {map.put(s.charAt(i),map.getOrDefault(s.charAt(i),0) + 1);}for (int i = 0; i < t.length(); i++) {map.put(t.charAt(i),map.getOrDefault(t.charAt(i),0) - 1);if (map.get(t.charAt(i)) < 0){return false;}}return true;}

2、贖金信(力扣383)

//1.和242很像,沒啥難度public static boolean canConstruct(String ransomNote, String magazine) {if (ransomNote.length() > magazine.length()){return false;}int[] arr = new int[26];for (int i = 0; i < magazine.length(); i++) {arr[magazine.charAt(i) - 'a'] ++;}for (int i = 0; i < ransomNote.length(); i++) {arr[ransomNote.charAt(i) - 'a'] --;if (arr[ransomNote.charAt(i) - 'a'] < 0){return false;}}return true;}
//2.哈希mappublic static boolean canConstruct(String ransomNote, String magazine) {if (ransomNote.length() > magazine.length()) {return false;}Map<Character, Integer> map = new HashMap<>();for (int i = 0; i < magazine.length(); i++) {map.put(magazine.charAt(i), map.getOrDefault(magazine.charAt(i), 0) + 1);}for (int i = 0; i < ransomNote.length(); i++) {map.put(ransomNote.charAt(i),map.getOrDefault(ransomNote.charAt(i),0) - 1);if (map.get(ransomNote.charAt(i)) < 0){return false;}}return true;}

3、字母異位詞分組(力扣49)

//1.哈希mappublic List<List<String>> groupAnagrams(String[] strs) {//考慮清楚用什么來表示鍵和值Map<String,ArrayList<String>> map = new HashMap<>();for (String s : strs){char[] c = s.toCharArray();Arrays.sort(c);String key = String.valueOf(c);if (!map.containsKey(key)){map.put(key,new ArrayList<>());}map.get(key).add(s);}//map.values() 返回的是collection,直接是集合return new ArrayList<>(map.values());}

4、找到字符串中所有字母異位詞(力扣438)

//1.自己想的public static List<Integer> findAnagrams(String s, String p) {if (s.length() < p.length()){return new ArrayList<>();}List<Integer> list = new ArrayList<>();char[] c1 = p.toCharArray();Arrays.sort(c1);for (int i = 0; i <= s.length() - p.length(); i++) {char[] c2 = s.substring(i,i + p.length()).toCharArray();Arrays.sort(c2);if (Arrays.equals(c1,c2)){list.add(i);}}return list;}
//2.滑動窗口public static List<Integer> findAnagrams(String s, String p) {int sLen = s.length(), pLen = p.length();if (sLen < pLen) {return new ArrayList<>();}//分別統計滑動窗口和p中的字符的數量int[] sCount = new int[26];int[] pCount = new int[26];List<Integer> list = new ArrayList<>();for (int i = 0; i < pLen; i++) {sCount[s.charAt(i) - 'a']++;pCount[p.charAt(i) - 'a']++;}if (Arrays.equals(sCount, pCount)) {list.add(0);}//滑動窗口向右移動,依次比較for (int i = 0; i < sLen - pLen; i++) {sCount[s.charAt(i) - 'a'] --;sCount[s.charAt(i + pLen) - 'a'] ++;if (Arrays.equals(sCount,pCount)){list.add(i + 1);}}return list;}

三、兩個數組的交集

1、兩個數組的交集(力扣349)

// 1.利用哈希表public int[] intersection(int[] nums1, int[] nums2) {Set<Integer> numsSet = new HashSet<>();Set<Integer> resSet = new HashSet<>();for (int num : nums1){numsSet.add(num);}for (int num : nums2){if (numsSet.contains(num)){resSet.add(num);}}int[] resArray = new int[resSet.size()];int index = 0;for (int i : resSet){resArray[index ++] = i;}return resArray;}
//2.雙指針public static int[] intersection3(int[] nums1, int[] nums2) {Arrays.sort(nums1);Arrays.sort(nums2);Set<Integer> set = new HashSet<>();int i = 0;int j = 0;while (i < nums1.length && j < nums2.length) {if (nums1[i] == nums2[j]) {set.add(nums1[i]);i++;j++;} else if (nums1[i] < nums2[j]) {i++;} else if (nums1[i] > nums2[j]) {j++;}}int[] ans = new int[set.size()];int index = 0;for (int value : set) {ans[index++] = value;}return ans;}
//3.二分法public static int[] intersection4(int[] nums1, int[] nums2) {Set<Integer> set = new HashSet<>();Arrays.sort(nums2);for (int target : nums1) {if (binarySearch(nums2, target)) {set.add(target);}}int index = 0;int[] ans = new int[set.size()];for (int value : set) {ans[index++] = value;}return ans;}public static boolean binarySearch(int[] num, int target) {int left = 0;int right = num.length - 1;while (left <= right) {int mid = left + (right - left) / 2;if (num[mid] == target) {return true;} else if (num[mid] < target) {left = mid + 1;} else if (num[mid] > target) {right = mid - 1;}}return false;}

2、兩個數組的交集 II(力扣350)

// 1.哈希表
public int[] intersect(int[] nums1, int[] nums2) {if (nums2.length < nums1.length){return intersect(nums2, nums1);}/* 記錄元素及元素出現的次數 */Map<Integer, Integer> numMap = new HashMap<>();for (int num : nums1) {numMap.put(num, numMap.getOrDefault(num, 0) + 1);}/* 記錄重復元素 */List<Integer> resList = new ArrayList<>();for (int num : nums2) {if (numMap.containsKey(num) && numMap.get(num) > 0){resList.add(num);numMap.put(num, numMap.get(num) - 1);}}/* 構建返回數組*/int[] resArray = new int[resList.size()];for (int i = 0; i < resList.size(); i++) {resArray[i] = resList.get(i);}return resArray;}
//2.排序+雙指針 前提:兩個數組是排好序的public int[] intersect(int[] nums1, int[] nums2) {Arrays.sort(nums1);Arrays.sort(nums2);int i = 0,j = 0;int len1 = nums1.length,len2 = nums2.length;List<Integer> list = new ArrayList<>();while(i < len1 && j < len2){if(nums1[i] == nums2[j]){list.add(nums1[i]);i ++;j ++;}else if(nums1[i] < nums2[j]){i ++;}else{j ++;}}int size = list.size();int[] ans = new int[size];for(int index = 0;index < size; index++){ans[index] = list.get(index);}return ans;}

三、其他的哈希表題

1、快樂數(力扣202)

//1.普通方法//兩種情況:1 最終是1  2. 陷入循環public static boolean isHappy(int n) {Set<Integer> set = new HashSet<>();//如果n不是1,而且沒有陷入循環,就不停迭代while (n != 1 && !set.contains(n)){set.add(n);n = getSum(n);}return n == 1;}
//獲取一個數的各個位上的數字的平方和public static int getSum(int n){int sum = 0;while (n > 0){int num = n % 10;sum += num * num;n /= 10;}return sum;}
//2.快慢指針//兩種情況:如果成環,且不是1,返回falsepublic static boolean isHappy(int n) {int slow = n;int fast = getSum(n);while (fast != 1 && fast != slow){//慢指針每次走一步slow = getSum(fast);//快指針每次走兩步fast = getSum(getSum(slow));}return fast == 1;}

2、兩數之和(力扣1)

	public int[] twoSum(int[] nums, int target) {Map<Integer, Integer> numIndexMap = new HashMap();int[] result = new int[2];for(int i = 0;i < nums.length;i ++){if(numIndexMap.containsKey(target - nums[i])){result[0] = i;result[1] = numIndexMap.get(target - nums[i]);}numIndexMap.put(nums[i], i);}return result;}

3、四數相加 II(力扣454)

//四個數組兩兩組合,等效成兩個數組之和public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {int len = nums1.length;Map<Integer,Integer> map = new HashMap<>();for(int i = 0;i < len;i ++){for(int j = 0;j < len; j ++){map.put(nums1[i] + nums2[j],map.getOrDefault(nums1[i] + nums2[j],0) + 1);}}int count = 0;for(int i = 0;i < len;i ++){for(int j = 0;j < len; j ++){if(map.containsKey(-(nums3[i] + nums4[j]))){count += map.get(-(nums3[i] + nums4[j]));}}}return count;}

時間復雜度O(n2),空間復雜度O(n2)

4、三數之和(力扣15)

public List<List<Integer>> threeSum(int[] nums) {List<List<Integer>> resList = new ArrayList<>();if (nums == null || nums.length < 2){return resList;}Arrays.sort(nums);for (int i = 0; i < nums.length - 2; i++) {/* 最小的數大于0,直接結束 */if (nums[i] > 0){break;}/* 跳過重復值 */if (i > 0 && nums[i] == nums[i - 1]){continue;}int startIndex = i + 1;int endIndex = nums.length - 1;while (startIndex < endIndex){if (nums[startIndex] + nums[endIndex] + nums[i] == 0){resList.add(Arrays.asList(nums[startIndex], nums[endIndex], nums[i]));startIndex ++;endIndex --;while (startIndex < endIndex && nums[startIndex] == nums[startIndex - 1]){startIndex ++;}while (startIndex < endIndex && nums[endIndex] == nums[endIndex + 1]){endIndex --;}} else if (nums[startIndex] + nums[endIndex] + nums[i] < 0){startIndex ++;} else {endIndex --;}}}return resList;}

5、四數之和(力扣18)

public static List<List<Integer>> fourSum(int[] nums, int target) {List<List<Integer>> resList = new ArrayList<>();if (nums.length < 4){return resList;}/* 數組排序 */Arrays.sort(nums);int numLen = nums.length;for (int i = 0; i < numLen - 3; i++) {/* 跳過重復值 */if (i > 0 && nums[i] == nums[i - 1]){continue;}for (int j = i + 1; j < numLen - 2; j++) {/* 跳過重復值 */if (j > i + 1 && nums[j] == nums[j - 1]){continue;}int startIndex = j + 1, endIndex = numLen - 1;while (startIndex < endIndex){long curSum = (long) nums[i] + nums[j] + nums[startIndex] + nums[endIndex];if (curSum == target){resList.add(Arrays.asList(nums[i], nums[j], nums[startIndex], nums[endIndex]));startIndex ++;endIndex --;while (startIndex < endIndex && nums[startIndex] == nums[startIndex - 1]){startIndex ++;}while (startIndex < endIndex && nums[endIndex] == nums[endIndex + 1]){endIndex --;}} else if (curSum < target){startIndex ++;} else {endIndex --;}}}}return resList;}

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

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

相關文章

2.變量和常量

1.變量2.2 變量的基本使用2.3 變量的本質 2.4 變量命名規則與規范 2.5 變量拓展-數組 1.數組的基本使用 2.常量

Java并發核心基礎解析

目錄 一、背景 二、Java線程模型 三、Synchronized實現原理 3.1 鎖的使用 3.2 解釋執行 3.3 JIT執行 3.4 鎖的狀態 3.5 monitorenter 3.5.1 偏向鎖 3.5.2 輕量級鎖 3.5.3 重量級鎖 3.6 monitorexit 3.6.1 偏向鎖 3.6.2 輕量級鎖 3.6.3 重量級 四、可見性的真相…

線程池111

線程池框圖C語言線程池詳解&#xff1a;從基礎到實現通俗理解線程池想象你開了一家快遞站&#xff0c;每天要處理很多包裹派送&#xff1a;?沒有線程池?&#xff1a;每來一個包裹就雇一個新快遞員&#xff0c;送完就解雇問題&#xff1a;頻繁招聘解雇成本高&#xff08;線程創…

Qt-Advanced-Docking-System

直譯一下 &#xff1a; 先進的停靠系統 github: mfreiholz/Qt-Advanced-Docking-System: Advanced Docking System for Qt 這是這個項目的起源 這個最后一次更新&#xff1a; githubuser0xFFFF/Qt-Advanced-Docking-System: Advanced Docking System for Qt 這是另一個人復刻…

湖南(源點咨詢)市場調研 如何在行業研究中快速有效介入 中篇

我們接著起頭篇來說邁克爾波特認為一個行業內存在著五種基本競爭力量&#xff0c;即潛在入侵者、替代產品、供方、需方以及行業內現有競爭者。如附圖&#xff1a;即&#xff1a;同行業內現有競爭者的競爭能力、潛在競爭者進入的能力、替代品的替代能力、供應商的討價還價能力、…

【無標題】消息隊列(Message Queue)是一種**進程間通信(IPC)機制

消息隊列&#xff08;Message Queue&#xff09;是一種進程間通信&#xff08;IPC&#xff09;機制&#xff0c;它允許進程通過在隊列中添加和讀取消息來交換數據。與管道&#xff08;命名/匿名&#xff09;相比&#xff0c;消息隊列具有結構化消息、異步通信和消息持久化等特點…

mac中多版本JDK配置和切換

下載 從jdk官網下載即可&#xff0c;找到自己要用的版本。 官網&#xff1a;https://www.oracle.com/java/technologies/downloads/#jdk21-mac 我這里下載的jdk1.8和21。 根據自己芯片下載&#xff0c;一般都是m芯片。下載好后&#xff0c;點擊&#xff0c;一直下一步就行&…

【JVM】流程匯總

【JVM】流程匯總【一】編譯過程和內存分布【1】案例程序&#xff1a;簡單的 Java 類【2】Java 編譯過程&#xff1a;從.java到.class&#xff08;1&#xff09;編譯命令&#xff08;2&#xff09;編譯結果&#xff08;3&#xff09;字節碼的作用【3】Java 運行過程&#xff1a;…

專業MP3瘦身工具WinMP3Shrink 1.1,綠色單文件,極速壓縮

[軟件名稱]: 專業MP3瘦身工具WinMP3Shrink 1.1 [軟件大小]: 1.1 MB [軟件大小]: 夸克網盤 | 百度網盤 軟件介紹 WinMP3Shrink 是一款免費的 MP3 壓縮軟件&#xff0c;能夠有效減少 MP3 文件的體積&#xff0c;同時還能增強音質。即使不重新編碼&#xff0c;通過移除保留空間…

LeetCode 每日一題 2025/8/4-2025/8/10

記錄了初步解題思路 以及本地實現代碼&#xff1b;并不一定為最優 也希望大家能一起探討 一起進步 目錄8/4 904. 水果成籃8/5 3477. 水果成籃 II8/6 3479. 水果成籃 III8/7 3363. 最多可收集的水果數目8/8 808. 分湯8/9 231. 2 的冪8/10 869. 重新排序得到 2 的冪8/4 904. 水果…

Python爬蟲實戰:研究Ruia框架,構建博客園文章采集系統

1. 引言 1.1 研究背景與意義 在數字化時代,數據已成為驅動科技創新與產業升級的核心生產要素。互聯網作為全球最大的信息載體,蘊含著億級結構化、半結構化與非結構化數據,這些數據在商業決策、學術研究、公共服務等領域具有不可替代的價值。網絡爬蟲技術作為自動獲取網絡公…

Office安裝使用?借助Ohook開源工具?【圖文詳解】微軟Office產品

一、問題背景 很多用戶在使用 Office 軟件一段時間后&#xff0c;會遇到以下問題。 二、解決方案 Ohook 是 Office 獨有的可用方式&#xff0c;源自 GitHub 上的開源項目&#xff0c;代碼開源&#xff08;開源地址&#xff1a;https://github.com/asdcorp/ohook&#xff09;。 …

LeetCode簡單題 - 學習

力扣題庫 - 簡單題 - 僅記錄學習 來源地址&#xff1a; 力扣 (LeetCode) 全球極客摯愛的技術成長平臺 1. 兩數之和 給定一個整數數組 nums 和一個整數目標值 target&#xff0c;請你在該數組中找出 和為目標值 target 的那 兩個 整數&#xff0c;并返回它們的數組下標。 你…

Android Camera 打開和拍照APK源碼

完整下載路徑: 【免費】AndroidcameraAPK完整源碼(包括打開攝像頭和拍照保存功能)Android10驗證可完整運行資源-CSDN下載 效果: 源碼: package com.example.mycamera;import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appco…

【系統分析師】軟件需求工程——第11章學習筆記(上)

軟件需求工程是包括創建和維護軟件需求文檔所必需的一切活動的過程。可分為兩大工作&#xff1a;需求開發需求獲取需求分析需求定義&#xff08;編寫需求規格說明書&#xff09;需求驗證需求管理定義需求基線處理需求變更需求跟蹤在需求開發階段需要確定軟件所期望的用戶類型&a…

機器學習第七課之支持向量機SVM

目錄 簡介&#xff1a; 一、什么是支持向量機 二、如何選取最佳的超平面 1.超平面方程 (優化目標) 2.如何尋找最優的超平面 3.舉例分析 4.軟間隔?編輯 三、核函數 1舉例 2常用核函數 3.多項式核函數 4.高斯核函數: 四、svm的優缺點 五、支持向量機的API 六、案例…

P3232 [HNOI2013] 游走,solution

原題&#xff1a; link&#xff0c;點擊這里喵。 題意&#xff1a; 給定一個 nnn 個點 mmm 條邊的無向連通圖&#xff0c;圖無重邊和自環&#xff0c;頂點從 111 編號到 nnn&#xff0c;邊從 111 編號到 mmm。 小 Z 在該圖上進行隨機游走&#xff0c;初始時小 Z 在 111 號頂…

Docker容器部署discuz論壇與線上商城

準備 關閉防火墻&#xff0c;上下文[rootdocker ~]# systemctl disable --now firewalld[rootdocker ~]# setenforce 0下載應用yum remove runc -y ### rocky8才需要yum install -y yum-utils yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/cento…

Linux入門指南:26個基礎命令全解析

目錄 一.基礎概念與入門 1.Linux操作系統簡介 2.終端與shell的基本概念 3.命令行界面的優勢 二.基礎指令 1.whoami ?2.useradd/userdel/passwd ?3.pwd ?4.ls ?5.cd 6.touch 7.mkdir 8.tree 9.rmdir/rm 10.man 11.cp 12.mv 13.cat 14.le…

【后端】Java 8 特性 `User::getId` 語法(方法引用)介紹

文章目錄核心概念解析&#xff1a;方法引用的四種類型&#xff1a;關鍵特性&#xff1a;使用場景推薦&#xff1a;何時避免使用&#xff1a;性能說明&#xff1a;在 Java 中&#xff0c; User::getId 是一種稱為 方法引用&#xff08;Method Reference&#xff09; 的語法糖&a…