hash table
Tips:
- The data range is small, and an array can be used to simulate hashing
- It is important to think clearly about what is the key of the hash
- Some problems seem to require two hash tables, but can actually be solved with one
valid anagrams
Title: 242. Valid anagrams
Given two strings s
and t
, write a function to determine t
whether they are s
anagrams of .
Note : If the number of occurrences of each character in s
and t
is the same, it is said that s
and t
are anagrams of each other.
输入: s = "anagram", t = "nagaram"
输出: true
Array analog hashing:
public boolean isAnagram(String s, String t) {
if (s.length() != t.length()) return false;
int[] map = new int[128];
for (char c : s.toCharArray()) map[c]++;
for (char c : t.toCharArray())
if (--map[c] < 0) return false;
for (int i : map) if (i != 0) return false;
return true;
}
Sort by:
public boolean isAnagram(String s, String t) {
char[] cs1 = s.toCharArray();
char[] cs2 = t.toCharArray();
Arrays.sort(cs1);
Arrays.sort(cs2);
return String.valueOf(cs1).equals(String.valueOf(cs2));
}
ransom letter
Give you two strings: ransomNote
and magazine
, to judge ransomNote
whether it can be magazine
composed of characters inside.
Return if yes true
; otherwise return false
.
magazine
Each character in can only ransomNote
be used once in .
输入:ransomNote = "a", magazine = "b"
输出:false
Array analog hashing:
public boolean canConstruct(String s1, String s2) {
int[] map = new int[123]; // s2 中字符出现的次数
for (char c : s2.toCharArray()) map[c]++;
for (char c : s1.toCharArray()) if (--map[c] < 0) return false;
return true;
}
Anagram grouping*
Given an array of strings, please combine anagrams together. The list of results can be returned in any order.
An anagram is a new word obtained by rearranging the letters of a source word, usually in all of the source words exactly once.
输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]
After sorting the two anagrams , the result is the same.
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> map = new HashMap<>();
for (String s : strs) {
// 对字符数组进行排序, 排序后的字符串作为哈希表的 key
char[] cs = s.toCharArray();
Arrays.sort(cs);
String key = String.valueOf(cs);
System.out.println(key);
if (!map.containsKey(key)) map.put(key, new ArrayList<>());
map.get(key).add(s);
}
return new ArrayList<>(map.values());
}
Find all anagrams in a string
Given two strings s
and p
, find all substrings of anagramss
in and return the starting indices of these substrings. The order in which answers are output is not considered. An anagram refers to a character string (including the same character string) formed by rearranging the same letter.p
输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。
Double pointer + array analog hash: similar to [[01_array#minimum coverage substring]]
public List<Integer> findAnagrams(String s, String p) {
List<Integer> res = new ArrayList<>();
int[] map = new int[123];
for (char c : p.toCharArray()) map[c]++; // map[c] < 0 表示满足需求
int cnt = 0; // cnt == p.length() 表示满足需求
for (int l = 0, r = 0; r < s.length(); r++) {
if (map[s.charAt(r)]-- > 0) cnt++;
while (l < r && map[s.charAt(l)] < 0) map[s.charAt(l++)]++;
if (r - l + 1 == cnt && cnt == p.length())
res.add(l);
}
return res;
}
intersection of two arrays
Given two arrays nums1
and sum nums2
, return their intersection . Each element in the output must be unique . We can ignore the order of the output results .
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]
public int[] intersection(int[] nums1, int[] nums2) {
int[] map = new int[1001];
List<Integer> list = new ArrayList<>();
for (int n : nums1) map[n]++;
for (int n : nums2) {
if (map[n] != 0) {
list.add(n);
map[n] = 0; // *
}
}
int[] res = new int[list.size()];
for (int i = 0; i < res.length; i++)
res[i] = list.get(i);
return res;
}
Intersection of Two Arrays II
Given the sum of two integer arrays nums1
, nums2
please return the intersection of the two arrays as an array. The number of occurrences of each element in the returned result should be consistent with the number of occurrences of the element in both arrays (if the number of occurrences is inconsistent, consider taking a smaller value). The order of the output results can be ignored.
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
int[] map = new int[1001];
for (int n : nums1) map[n]++;
List<Integer> list = new ArrayList<>();
for (int n : nums2) {
if (map[n] != 0) {
list.add(n);
map[n]--; // *
}
}
int[] res = new int[list.size()];
for (int i = 0; i < res.length; i++)
res[i] = list.get(i);
return res;
}
}
happy number
Topic: Happy Numbers
Write an algorithm to determine n
whether a number is a happy number.
"Happy Number" is defined as:
- For a positive integer, each time the number is replaced by the sum of the squares of the digits in each position.
- Then repeat this process until the number becomes 1, or it may be an infinite loop but it never becomes less than 1.
- If the result of this process is 1, then the number is a happy number.
Ifn
it is a happy number , it returnstrue
; if it is not, it returnsfalse
.
输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
class Solution {
public boolean isHappy(int n) {
Set<Integer> set = new HashSet<>();
while (n != 1) {
n = squareSum(n);
if (set.contains(n)) return false;
set.add(n);
}
return true;
}
int squareSum(int n) {
int sum = 0;
while (n != 0) {
sum += Math.pow(n % 10, 2);
n /= 10;
}
return sum;
}
}
sum of two numbers
Topic: 1. The sum of two numbers
Given an integer array nums
and an integer target value , please find the two integers whose sum is the target valuetarget
in the array , and return their array subscripts. You can assume that there is only one answer for each input. However, the same element in the array cannot appear repeatedly in the answer. You can return answers in any order. target
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
if (map.containsKey(target - nums[i]))
return new int[] {
i, map.get(target - nums[i]) };
map.put(nums[i], i);
}
return new int[] {
};
}
Adding Four Numbers II
Topic: 454. Adding Four Numbers II
Given you four integer arrays nums1
, nums2
, nums3
and nums4
, the lengths of the arrays are all n
, please calculate how many tuples (i, j, k, l)
can satisfy:
0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
输入: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
Think of n1 + n2 as a hash key:
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
Map<Integer, Integer> map = new HashMap<>();
int count = 0;
for (int n1 : nums1)
for (int n2 : nums2)
map.put(n1 + n2, map.getOrDefault(n1 + n2, 0) + 1);
for (int n3 : nums3)
for (int n4 : nums4)
if (map.containsKey(-n3 - n4))
count += map.get(-n3 - n4);
return count;
}
sum of three numbers
Given an array of integers nums
, determine whether there is a triple [nums[i], nums[j], nums[k]]
that satisfies i != j
, i != k
and j != k
, and satisfies at the same time nums[i] + nums[j] + nums[k] == 0
. Please
return all 0
triples whose sum is and are not repeated.
Note : Duplicate triplets are not allowed in the answer.
输入: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] 。
注意,输出的顺序和三元组的顺序并不重要。
Pay attention to combining sorting to remove duplication:
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
int n = nums.length;
Arrays.sort(nums); // 排序
for (int i = 0; i < n; i++) {
if (nums[i] > 0) break;
if (i > 0 && nums[i] == nums[i - 1]) continue; // 去重
int l = i + 1, r = n - 1;
while (l < r) {
if (nums[l] + nums[r] < -nums[i]) l++;
else if (nums[l] + nums[r] > -nums[i]) r--;
else {
res.add(Arrays.asList(nums[i], nums[l], nums[r]));
while (l < r && nums[l] == nums[l + 1]) l++; // 去重
while (l < r && nums[r] == nums[r - 1]) r--; // 去重
l++;
r--;
}
}
}
return res;
}
sum of four numbers
You are given an n
array of integers nums
, and a target value target
. Please find and return the quadruples that meet all the following conditions and are not repeated [nums[a], nums[b], nums[c], nums[d]]
(if the two quadruple elements correspond to each other, the two quadruples are considered to be repeated):
0 <= a, b, c, d < n
a
,b
,c
andd
are different from each othernums[a] + nums[b] + nums[c] + nums[d] == target
You can return answers in any order .
输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> res = new ArrayList<>();
int n = nums.length;
Arrays.sort(nums);
for (int i = 0; i < n - 3; i++) {
if (i > 0 && nums[i] == nums[i - 1]) continue; // 去重
// 剪枝: 最小的情况 > target 则不可能满足; 最大的情况 < target 有可能满足
if ((long) nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) break;
if ((long) nums[i] + nums[n - 3] + nums[n - 2] + nums[n - 1] < target) continue;
for (int j = i + 1; j < n - 2; j++) {
if (j > i + 1 && nums[j] == nums[j - 1]) continue; // 去重
// 剪枝: 最小的情况 > target 则不可能满足; 最大的情况 < target 有可能满足
if ((long) nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) break;
if ((long) nums[i] + nums[j] + nums[n - 2] + nums[n - 1] < target) continue;
int l = j + 1, r = n - 1;
while (l < r) {
long sum = (long) nums[i] + nums[j] + nums[l] + nums[r]; // 防止溢出
if (sum < target) l++;
else if (sum > target) r--;
else {
res.add(Arrays.asList(nums[i], nums[j], nums[l], nums[r]));
while (l < r && nums[l] == nums[l + 1]) l++; // 去重
while (l < r && nums[r] == nums[r - 1]) r--; // 去重
l++;
r--;
}
}
}
}
return res;
}