HashMap哈希表
HashMap
- 用Array+Linkedlist(chaining,另有openaddress的实现)实现的能在平均O(1)的时间内快速增删查的数据结构
- 表内存储的数据需要实现equals()和hashCode()
LinkedHashMap
- 有顺序的hashmap,遍历顺序是key插入的顺序
- 所有的key按顺序存成一个linkedlist
TreeMap
- 有顺序(sorted)的map,遍历顺序是key从小到大
- 所有的key存成一个红黑树(self-balanacing binary tree)
- 增删查O(logn)
HashSet
- 没有value的hashmap
适用场景(when to use)
当需要快速查找数据时,可以利用HashMap加速查找
注意是要查找的数据结构实现了equals()和hashCode()
Array 和 HashMap的区别在于:
Array无法快速查找,HashMap可以
Array里的元素是有顺序的,HashMap没有
Array的overhead比较小,HashMap实现比较复杂
例题
Two Sum
Given an array of integers nums
and an integer target
, return indices of the two numbers such that they add up to target
. You may assume that each input would have exactly one solution, and you may not use the same element twice.
You can return the answer in any order.
Example 1:
ini
Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Explanation: Because nums[0] + nums[1] == 9, we return [0, 1].
Example 2:
ini
Input: nums = [3,2,4], target = 6
Output: [1,2]
Example 3:
ini
Input: nums = [3,3], target = 6
Output: [0,1]
Constraints:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
- Only one valid answer exists.
Solution 1: Brute Force
csharp
class Solution { public int[] twoSum(int[] nums, int target) { for(int i = 0; i < nums.length; i++) { for(int j = 0; j < nums.length; j++) { if(nums[i] + nums[j] == target && i != j) { return new int[]{i, j}; } } } return new int[]{-1,-1}; }}
Solution 2:
当需要快速查找数据时,可以利用HashMap加速查找
查找对象:目前见过的值 - index
HashMap:
记录下之前见过的{key: 值,value:index}
对于array里的每一个数,如果map里存在target-x,那就找到了答案
Solution Step:
- Initialize HashMap (possible with initial size to improve performance)
- For each number x in array
a. if target - x exists in array, return the indices
b. put{x, index(x)}
时间复杂度:O(n)
空间复杂度:O(n)
sql
class Solution { public int[] twoSum(int[] nums, int target) { Map<Integer, Integer> map = new HashMap(nums.length); //when putting the initial size, the both runtime/memory increases significantly for(int i = 0; i < nums.length; i++) { if(map.containsKey(target - nums[i])) { return new int[]{map.get(target - nums[i]),i}; } else { map.put(nums[i],i); } } return new int[]{-1,-1}; }}
Extention: 如果return的是值不是index的话:
Two Pointer(array needs to be sorted, or we sort by ourself),Opposite Direction
Each iteration we will have a sum of two pointers -> array[i] + array[j]
case 1: array[i] + array[j] == target -> we found the answer
case 2: array[i] + array[j] > target -> too big, move the right pointer to left
case 3: array[i] + array[j] < target -> too small, move the left pointer to right
Solution:
- Sort the input array
- Initialize two pointers, i = 0 and j = n - 1
- while i < j:
a. arr[i] + arr[j] == target --> return
b. arr[i] + arr[j] > target --> j--
c. arr[i] + arr[j] < target --> i++
csharp
class Solution { public int[] twoSum(int[] nums, int target) { Arrays.sort(nums); int i = 0, j = nums.length - 1; while(i < j) { int sum = nums[i] + nums[j]; if(sum == target) { return new int[]{nums[i], nums[j]}; } else if (sum > target) { j--; } else { i++; } } return null;}
- Subarray Sum Equals K
Given an array of integers nums
and an integer k
, return the total number of subarrays whose sum equals tok
.
A subarray is a contiguous non-empty sequence of elements within an array.
Example 1:
ini
Input: nums = [1,1,1], k = 2
Output: 2
Example 2:
ini
Input: nums = [1,2,3], k = 3
Output: 2
Constraints:
-
1 <= nums.length <= 2 * 104
-
-1000 <= nums[i] <= 1000
-
-107 <= k <= 107
Note: 所有的subarray sum都可以通过sum(0,x) - sum(0,y) 来计算
思路:
当需要快速查找数据时,可以利用HashMap加速查找
查找对象: all sum seen so far until current index -> # of times it occurs
当current sum - k 存在于map内,那么answer += map.get(sum - k)
因为sum - k存在于map说明之前sum(0, x) = k 出现了y次, 那么:
subarray sum = current sum - sum(0,x) = k 多出现了y次
要点:Map内一开始存在一个{0, 1}, 代表sum = 0 默认出现了1次
Solution:
- Initialize HashMap with {0, 1}
- Initialize sum = 0, result = 0
- For each number x in array
a. sum += x
b. if sum - k in the map -> result += map.get(sum-k)
c. put sum into the map, increase its count if exists
python
class Solution { public int subarraySum(int[] nums, int k) { Map<Integer, Integer> map = new HashMap(nums.length); map.put(0,1); int sum = 0, count = 0; for(int x : nums) { sum += x; if(map.containsKey(sum -k)) { count += map.get(sum-k); } map.put(sum, map.getOrDefault(sum,0)+1); } return count; }}