每当我们遇到,要判断这个元素是否出现过,或者元素是否在集合中,想到哈希。
242 有效的字母异位词
题目描述:
给定两个字符串 s
和 t
,编写一个函数来判断 t
是否是 s
的字母异位词。
注意:若 s
和 t
中每个字符出现的次数都相同,则称 s
和 t
互为字母异位词。
解题思路:
哈希一下。哈希可以用数组、set和map。
穿插一下Java小知识:
1. 开始本来想用增强型for循环遍历字符串,搜了一下发现只能用于数组和实现了Iterable接口的集合类型。非要用的话只能先把String转化为一个字符数组。String str = "Hello, World!"; for(char c : str.toCharArray()) { System.out.println(c); }
2. 关于Java中length、length()、size()的区别_java string size-CSDN博客
length——数组的属性;
length()——String的方法;
size()——集合的方法;
力扣代码:
class Solution {
public boolean isAnagram(String s, String t) {
int[] arr1 = new int[26];
int[] arr2 = new int[26];
for(int i=0;i<s.length();i++){
arr1[s.charAt(i)-'a']++;
}
for(int i=0;i<t.length();i++){
arr2[t.charAt(i)-'a']++;
}
for (int i=0;i<26;i++){
arr1[i] -= arr2[i];
if(arr1[i] != 0) return false;
}
return true;
}
}
349 两个数组的交集
题目描述:
给定两个数组 nums1
和 nums2
,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。
解题思路:
数组的元素都是数字,本题说
1 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 1000
那么其实哈希可以用数组做,把nums1和2中的元素作为下标。
更通用的还是set。
力扣代码:
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
Set<Integer> set = new HashSet();
Set<Integer> res = new HashSet();
for (int i:nums1){
set.add(i);
}
for (int i:nums2){
if(set.contains(i)) res.add(i);
}
int[] ress = new int[res.size()];
int count = 0;
for (int i:res){
ress[count++] = i;
}
return ress;
}
}
1 两数之和
题目描述:
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
解题思路:
本题需要一个集合来存放遍历过的元素,然后在遍历数组的时候询问这个集合,某元素(target-nums[i])是否被遍历过,即是否在这个集合中。
不仅要知道这个元素在不在,还需要知道元素之前在nums数组中的下标。
所以key用来存元素的值,value用于存下标。
map的一些方法:
Map<String, Integer> map = new HashMap<>(); map.put("a", 1);//往map中添加键值对 //get 方法用于获取指定 key 对应的 value 值,如果 key 不存在,则返回 null。 Integer value = map.get("a"); //containsKey 和 containsValue 方法分别用于判断 Map 中是否包含指定的 key 或 value 值。
力扣代码:
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> map = new HashMap<>();
int[] res = new int[2];//结果数组
for (int i=0;i<nums.length;i++){
if(map.containsKey(target-nums[i])){
res[0] = i;
res[1] = map.get(target-nums[i]);
}
map.put(nums[i],i);
}
return res;
}
}
454 四数相加2⃣️
题目描述:
给你四个整数数组 nums1
、nums2
、nums3
和 nums4
,数组长度都是 n
,请你计算有多少个元组 (i, j, k, l)
能满足:
0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
解题思路:
力扣代码:
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
Map<Integer,Integer> map = new HashMap<>();
int res = 0;
//先遍历前两个数组
for (int i:nums1){
for(int j:nums2){
// map.put(i+j,map.get(i+j)+1);//不能直接用get,要用getOrDefault
map.put(i+j,map.getOrDefault(i+j,0)+1);
}
}
//再遍历后两个数组
for (int i:nums3){
for (int j:nums4){
res += map.getOrDefault(0-(i+j),0);
}
}
return res;
}
}
15 三数之和
题目描述:
给你一个整数数组 nums
,判断是否存在三元组 [nums[i], nums[j], nums[k]]
满足 i != j
、i != k
且 j != k
,同时还满足 nums[i] + nums[j] + nums[k] == 0
。请
你返回所有和为 0
且不重复的三元组。
注意:答案中不可以包含重复的三元组。
解题思路:
先把nums排序,再双指针。
相当于要在数组中找到 abc 使得a + b +c =0,我们这里假设 a = nums[i],b = nums[left],c = nums[right]。
如果nums[i] + nums[left] + nums[right] > 0 就说明此时三数之和大了,因为数组是排序后了,所以right下标就应该向左移动,这样才能让三数之和小一些。反之left向右移动。
注意:sum==0的时候,left和right至少移动一个,之前忘移动了直接死循环。
Java中List与Set相互转化(本题要求不重复,我就用了一下set的性质)
// List转Set List<String> tmpList = new ArrayList<>(); Set<String> tmpSet = new HashSet<>(tmpList); // Set转List Set<String> tmpSet = new HashSet<>(); List<String> tmpList = new ArrayList<>(tmpSet);
力扣代码:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Set<List<Integer>> tmp = new HashSet<>();//用来暂存结果,set用于去重
Arrays.sort(nums);
for (int i=0;i<nums.length;i++){
int left = i + 1, right = nums.length - 1;
while (left<right){
int sum = nums[i]+nums[left]+nums[right];
if (sum>0) right--;
else if (sum<0) left++;
else{
tmp.add(Arrays.asList(nums[i],nums[left],nums[right]));
left++;
}
}
}
List<List<Integer>> res = new ArrayList<>(tmp);
return res;
}
}