雜湊對映用法及演算法例題
本文為博主演算法學習過程中的學習筆記,主要內容來源於其他平臺或書籍,出處請參考下方 參考&感謝 一節。
用法
雜湊對映 是用於儲存 (key, value)
鍵值對的一種實現。
使用雜湊對映的第一個場景是,我們 需要更多的資訊,而不僅僅是鍵。然後通過雜湊對映 建立金鑰與資訊之間的對映關係。
另一個常見的場景是 按鍵聚合所有資訊。我們也可以使用雜湊對映來實現這一目標。
例題
1、兩數之和
題目描述
給定一個整數陣列 nums 和一個目標值 target,請你在該陣列中找出和為目標值的那 兩個 整數,並返回他們的陣列下標。
你可以假設每種輸入只會對應一個答案。但是,你不能重複利用這個陣列中同樣的元素。
示例:
給定 nums = [2, 7, 11, 15], target = 9
因為 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
解題思路及實現
HashMap
入門的經典題。
簡單的方式是使用雙層迴圈進行暴力破解,這種演算法時間複雜度為O(N^2)
。
而使用HashMap
則可以將問題在一層迴圈中進行解決,時間複雜度僅O(N)
:
class Solution {
public int[] twoSum(int[] nums, int target) {
HashMap<Integer, Integer> map = new HashMap<>();
int[] result = new int[2];
for (int i = 0; i < nums.length; i++) {
int value = nums[i];
int find = target - value;
if (map.containsKey(find) && map.get(find) != i) {
result[0] = i;
result[1] = map.get(find);
break;
}
map.put(nums[i], i);
}
return result;
}
}
2、同構字串
題目描述
給定兩個字串 s 和 t,判斷它們是否是同構的。
如果 s 中的字元可以被替換得到 t ,那麼這兩個字串是同構的。
所有出現的字元都必須用另一個字元替換,同時保留字元的順序。兩個字元不能對映到同一個字元上,但字元可以對映自己本身。
你可以假設 s 和 t 具有相同的長度。
示例:
輸入: s = “egg”, t = “add”
輸出: true
輸入: s = “foo”, t = “bar”
輸出: false
解題思路及實現
通過2個HashMap
儲存各自字元對應最初的索引,然後進行比較,當字元對應的最初索引不同時,說明2個字串不是同構的:
class Solution {
public boolean isIsomorphic(String s, String t) {
char[] char1 = s.toCharArray();
char[] char2 = t.toCharArray();
HashMap<Character, Integer> map1 = new HashMap<>();
HashMap<Character, Integer> map2 = new HashMap<>();
for (int i = 0; i < char1.length; i++) {
char c1 = char1[i];
char c2 = char2[i];
if (!map1.containsKey(c1))
map1.put(c1, i);
if (!map2.containsKey(c2))
map2.put(c2, i);
if (map1.get(c1) != map2.get(c2))
return false;
}
return true;
}
}
3、兩個列表的最小索引總和
題目描述
https://leetcode-cn.com/problems/minimum-index-sum-of-two-lists/
解題思路及實現
這道題的難點是發現對映關係,即 最愛餐廳 -> 索引值 的對映關係。
通過遍歷將該對映關係儲存到HashMap
中後,再次通過一次遍歷找出索引值和最小的餐廳,因為索引值最小的情況可能不止一個,因此用一個List
進行維護,最終將答案遍歷輸出:
class Solution {
public String[] findRestaurant(String[] list1, String[] list2) {
HashMap<String, Integer> map = new HashMap<>();
List<Integer> posList = new ArrayList<>();
int minPosNum = Integer.MAX_VALUE;
for (int i = 0; i < list1.length; i++) {
map.put(list1[i], i);
}
for (int i = 0; i < list2.length; i++) {
String favorite = list2[i];
Integer position = map.get(favorite);
if (position != null) {
int posNum = i + position;
if (minPosNum > posNum) {
minPosNum = posNum;
posList.clear();
posList.add(i);
} else if (minPosNum == posNum) {
posList.add(i);
}
}
}
String[] result = new String[posList.size()];
for (int i = 0; i < posList.size(); i++)
result[i] = list2[posList.get(i)];
return result;
}
}
4、字串中的第一個唯一字元
題目描述
給定一個字串,找到它的第一個不重複的字元,並返回它的索引。如果不存在,則返回 -1。
示例:
s = “leetcode”
返回 0.
s = “loveleetcode”
返回 2.
您可以假定該字串只包含小寫字母。
解題思路及實現
比較簡單,通過2次遍歷,第一次遍歷將每個字元對應出現的次數進行儲存,第二次遍歷每個字元的出現次數,當出現次數為1
,返回該字元的索引即可。
class Solution {
public int firstUniqChar(String s) {
char[] arr = s.toCharArray();
HashMap<Character, Integer> map = new HashMap<>();
// 遍歷將所有字元的頻率輸出到Map中
for (int i = 0; i < arr.length; i++) {
char c = arr[i];
if (map.containsKey(c)) {
map.put(c, map.get(c) + 1);
} else {
map.put(c, 1);
}
}
for (int i = 0; i < arr.length; i++) {
char c = arr[i];
if (map.get(c) == 1)
return i;
}
return -1;
}
}
5、兩個陣列的交集 II
題目描述
給定兩個陣列,編寫一個函式來計算它們的交集。
輸入: nums1 = [1,2,2,1], nums2 = [2,2]
輸出: [2,2]
輸入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
輸出: [4,9]
輸出結果中每個元素出現的次數,應與元素在兩個陣列中出現的次數一致。
我們可以不考慮輸出結果的順序。
解題思路及實現
仍然是通過2次遍歷,第一次遍歷將nums1[]
每個數字對應出現的次數進行儲存,第二次遍歷nums2[]
,然後和之前的結果進行匹配,最終返回結果。
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
HashMap<Integer, Integer> map = new HashMap<>();
// 遍歷陣列將所有元素和其數量存入map中
for (int i = 0; i < nums1.length; i++) {
int key = nums1[i];
if (map.containsKey(key)) {
map.put(key, map.get(key) + 1);
} else {
map.put(key, 1);
}
}
int[] result = new int[nums2.length];
int pos = 0;
for (int i = 0; i < nums2.length; i++) {
int key = nums2[i];
if (map.containsKey(key) && map.get(key) >= 1) {
result[pos] = key;
pos++;
map.put(key, map.get(key) - 1);
}
}
return Arrays.copyOf(result, pos);
}
}
6、存在重複元素 II
題目描述
給定一個整數陣列和一個整數 k,判斷陣列中是否存在兩個不同的索引 i 和 j,使得 nums [i] = nums [j]
,並且 i 和 j 的差的絕對值最大為 k。
輸入: nums = [1,2,3,1], k = 3
輸出: true
輸入: nums = [1,0,1,1], k = 1
輸出: true
輸入: nums = [1,2,3,1,2,3], k = 2
輸出: false
解題思路及實現
題目理解了就好做了,關鍵是陣列內相同的數字最小距離是否不大於k
,做一次遍歷,每次都將數字作為key
,其索引作為value
進行儲存。
遍歷結束前,只要有一個滿足要求就可以返回true
,否則最終返回false
即可。
class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int key = nums[i];
if (map.containsKey(key)) {
int oldPos = map.get(key);
if (i - oldPos <= k) {
return true;
} else {
map.put(key, i);
}
} else {
map.put(key, i);
}
}
return false;
}
}
參考 & 感謝
文章絕大部分內容節選自LeetCode
,概述:
- https://leetcode-cn.com/explore/learn/card/hash-table/205/practical-application-hash-map/809/
例題:
- https://leetcode-cn.com/problems/two-sum/
- https://leetcode-cn.com/problems/isomorphic-strings/
- https://leetcode-cn.com/problems/minimum-index-sum-of-two-lists/
- https://leetcode-cn.com/problems/first-unique-character-in-a-string/
- https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/
- https://leetcode-cn.com/problems/contains-duplicate-ii/
關於我
Hello,我是 卻把清梅嗅 ,如果您覺得文章對您有價值,歡迎 ❤️,也歡迎關注我的 部落格 或者 GitHub。
如果您覺得文章還差了那麼點東西,也請通過關注督促我寫出更好的文章——萬一哪天我進步了呢?
相關文章
- 演算法面試通關40講 - 雜湊表/對映演算法面試
- 力扣-706. 設計雜湊對映力扣
- 查詢演算法及雜湊表演算法
- rust學習九.3-集合之雜湊對映表Rust
- 淺析Java中的雜湊值HashCode的作用及用法Java
- 3.1 雜湊演算法演算法
- 雜湊技術【雜湊表】查詢演算法 PHP 版演算法PHP
- 淺析雜湊演算法演算法
- 雜湊查詢演算法演算法
- 雜湊演算法簡介演算法
- Hash,雜湊,雜湊?
- 幾道和雜湊(雜湊)表有關的面試題面試題
- 22 | 雜湊演算法(下):雜湊演算法在分散式系統中有哪些應用?演算法分散式
- 七夕也要學起來,雜湊雜湊雜湊!
- 【六褘-Java】雜湊演算法記憶體圖;set集合低層採用雜湊表儲存元素;雜湊演算法的流程Java演算法記憶體
- 【ybtoj】二分演算法例題演算法
- 【資料結構與演算法學習】雜湊表(Hash Table,雜湊表)資料結構演算法
- 你知道雜湊演算法,但你知道一致性雜湊嗎?演算法
- MD5雜湊加密演算法加密演算法
- js實現資料結構及演算法之雜湊表(Hashtable)JS資料結構演算法
- 雜湊
- 什麼是雜湊演算法?雜湊競猜遊戲開發原理詳解演算法遊戲開發
- 【尋跡#3】 雜湊與雜湊表
- js 雜湊雜湊值的模組JS
- 雜湊表(雜湊表)原理詳解
- traceroute命令的用法例項分享
- torch.einsum 的用法例項
- 雜湊遊戲系統丨雜湊遊戲系統開發(演示版)丨雜湊遊戲開發原始碼及案例遊戲開發原始碼
- 雜湊表
- 雜湊碰撞
- 字串雜湊字串
- 樹雜湊
- 2024.3.26 雜湊
- 雜湊索引索引
- JavaScript閉包原理與用法例項JavaScript
- 演算法與資料結構——雜湊表演算法資料結構
- RIPEMD演算法:多功能雜湊演算法的瑰寶演算法
- java高階用法之:JNA型別對映應該注意的問題Java型別