Hash table
一般哈希表都是用来快速判断一个元素是否出现集合里。
例如要查询一个名字是否在这所学校里。
要枚举的话时间复杂度是O(n),但如果使用哈希表的话, 只需要O(1)就可以做到。
Hash Function
通过hashCode把名字转化为数值,一般hashcode是通过特定编码方式,可以将其他数据格式转化为不同的数值,这样就把学生名字映射为哈希表上的索引数字了。
Hash Colision
如果学生的数量大于哈希表的大小怎么办,此时就算哈希函数计算的再均匀,也避免不了会有几位学生的名字同时映射到哈希表同一个索引下标的位置。
- 发生冲突的元素都被存储在链表中
- 保证tableSize大于dataSize, 依靠哈希表中的空位来解决碰撞问题
常见的三种哈希结构
- 数组
- set (集合)
- map(映射)
当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。
但是哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。
For Future References
文章讲解:https://programmercarl.com/哈希表理论基础.html
242. Valid Anagram
Given two strings s
and t
, return true
if t
is an anagram of s
, and false
otherwise.
An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.
Example 1:
Input: s = "anagram", t = "nagaram"
Output: true
Example 2:
Input: s = "rat", t = "car"
Output: false
Constraints:
1 <= s.length, t.length <= 5 * 104
s
andt
consist of lowercase English letters.
Follow up: What if the inputs contain Unicode characters? How would you adapt your solution to such a case?
暴力的解法,两层for循环,同时还要记录字符是否重复出现,很明显时间复杂度是 O(n^2)。
数组其实就是一个简单哈希表,而且这道题目中字符串只有小写字符,那么就可以定义一个数组,来记录字符串s里字符出现的次数。
定一个数组叫做record,大小为26 就可以了,初始化为0,因为字符a到字符z的ASCII也是26个连续的数值。
record用来上记录字符串s里字符出现的次数。
遍历 字符串s的时候,只需要将 s[i] - ‘a’ 所在的元素做+1 操作即可,并不需要记住字符a的ASCII,只要求出一个相对数值就可以了。 这样就将字符串s中字符出现的次数,统计出来了。
在遍历字符串t的时候,对t中出现的字符映射哈希表索引上的数值再做-1的操作。
最后检查一下,
- record数组如果有的元素不为零0,说明字符串s和t一定是谁多了字符或者谁少了字符,return false。
- record数组所有元素都为零0,说明字符串s和t是字母异位词,return true。
class Solution {
public boolean isAnagram(String s, String t) {
int[] record = new int[26];
for (int i = 0; i < s.length(); i++) {
record[s.charAt(i) - 'a']++;
}
for (int i = 0; i < t.length(); i++) {
record[t.charAt(i) - 'a']--;
}
for (int count: record) {
if (count != 0) {
return false;
}
}
return true;
}
}
Time Complexity:O(n)
Space Complexity:O(1)
For Future References
题目链接:https://leetcode.com/problems/valid-anagram/
文章讲解: https://programmercarl.com/0242.有效的字母异位词.html
视频讲解:https://www.bilibili.com/video/BV1YG411p7BA/
349. Intersection of Two Arrays
Given two integer arrays nums1
and nums2
, return an array of their intersection. Each element in the result must be unique and you may return the result in any order.
Example 1:
Input: nums1 = [1,2,2,1], nums2 = [2,2]
Output: [2]
Example 2:
Input: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
Output: [9,4]
Explanation: [4,9] is also accepted.
Constraints:
1 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 1000
输出结果中的每个元素一定是唯一的,也就是说输出的结果的去重的, 同时可以不考虑输出结果的顺序
暴力的解法时间复杂度是O(n^2)
如果哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费。
import java.util.HashSet;
import java.util.Set;
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
if (nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0) {
return new int[0];
}
Set<Integer> set1 = new HashSet<>();
Set<Integer> resSet = new HashSet<>();
//遍历数组1
for (int i : nums1) {
set1.add(i);
}
//遍历数组2的过程中判断哈希表中是否存在该元素
for (int i : nums2) {
if (set1.contains(i)) {
resSet.add(i);
}
}
//将结果几何转为数组
return resSet.stream().mapToInt(x -> x).toArray();
}
}
Time Complexity:O(n)
Space Complexity:O(n)
For Future References
题目链接:https://leetcode.com/problems/intersection-of-two-arrays/
文章讲解: https://programmercarl.com/0349.两个数组的交集.html
视频讲解:https://www.bilibili.com/video/BV1ba411S7wu/
202. Happy Number
Write an algorithm to determine if a number n
is happy.
A happy number is a number defined by the following process:
- Starting with any positive integer, replace the number by the sum of the squares of its digits.
- Repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1.
- Those numbers for which this process ends in 1 are happy.
Return true
if n
is a happy number, and false
if not.
Example 1:
Input: n = 19
Output: true
Explanation:
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1
Example 2:
Input: n = 2
Output: false
Constraints:
1 <= n <= 231 - 1
题目中说了会 无限循环,那么也就是说求和的过程中,sum会重复出现,这对解题很重要!
所以这道题目使用哈希法,来判断这个sum是否重复出现,如果重复了就是return false, 否则一直找到sum为1为止。
class Solution {
public boolean isHappy(int n) {
Set<Integer> record = new HashSet<>();
while (n != 1 && !record.contains(n)) {
record.add(n);
n = getNextNumber(n);
}
return n == 1;
}
private int getNextNumber(int n) {
int res = 0;
while (n > 0) {
int temp = n % 10;
res += temp * temp;
n = n / 10;
}
return res;
}
}
For Future References
题目链接:https://leetcode.com/problems/happy-number/
文章讲解: https://programmercarl.com/0202.快乐数.html
1. 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:
Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Explanation: Because nums[0] + nums[1] == 9, we return [0, 1].
Example 2:
Input: nums = [3,2,4], target = 6
Output: [1,2]
Example 3:
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.
Follow-up:
Can you come up with an algorithm that is less than O(n^2) time complexity?
暴力的解法是两层for循环查找,时间复杂度是O(n^2)。
需要一个集合来存放我们遍历过的元素,然后在遍历数组的时候去询问这个集合,某元素是否遍历过,也就是 是否出现在这个集合。
我们不仅要知道元素有没有遍历过,还有知道这个元素对应的下标,需要使用 key value结构来存放,key来存元素,value来存下标,那么使用map正合适。
- 数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。
- set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x 和 y的下标。所以set 也不能用。
此时就要选择另一种数据结构:map ,map是一种key value的存储结构,可以用key保存数值,用value在保存数值所在的下标。
map目的用来存放我们访问过的元素,因为遍历数组的时候,需要记录我们之前遍历过哪些元素和对应的下表,这样才能找到与当前元素相匹配的(也就是相加等于target)
{key:数据元素,value:数组元素对应的下表}。
public int[] twoSum(int[] nums, int target) {
int[] res = new int[2];
if(nums == null || nums.length == 0){
return res;
}
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < nums.length; i++){
int temp = target - nums[i];
if(map.containsKey(temp)){
res[1] = i;
res[0] = map.get(temp);
}
map.put(nums[i], i);
}
return res;
}
Time Complexity:O(n)
Space Complexity:O(n)
For Future References
题目链接:https://leetcode.com/problems/two-sum/
文章讲解: https://programmercarl.com/0001.两数之和.html
视频讲解:https://www.bilibili.com/video/BV1aT41177mK/
标签:return,https,nums,int,随想录,Day,哈希,com,349 From: https://www.cnblogs.com/bluesociety/p/16733165.html