本次题目主要涉及哈希表,牢记使用哈希表的条件:用来判断一个元素是否出现在集合里
242. 有效的字母异位词
数组
题目可以归结为判断两个字符串中出现的字母及其数量是否相等,可以考虑用哈希表存放字符串元素,这里选择的哈希表结构为数组,因为字母的数量为26个有限个。只要字符串的字母出现一次,这个位置的值就加1。
而判断另一个数组是否也出现了这些字母,可以在生成的数组中对相应的字母-1,遍历完第二个字符串后,如果数组的每个位置上数值都为0,那么就返回true。时间复杂度为O(n)
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']++;// 这里a放置的相对位置是0
}
for (int i = 0; i < t.length(); i++) {
record[t.charAt(i) - 'a']--;
}
for (int i = 0; i < record.length; i++) {
if (record[i] != 0) {
return false;
}
}
return true;
}
}
349. 两个数组的交集
Set
不考虑重复元素,这里可以考虑使用Set,将nums1不重复的数值放进set里面,然后生成一个新的newset存放两个数组重复的值。最后返回的是int类型数组,注意迭代器转化的方法。时间复杂度为O(n)
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
HashSet<Integer> set =new HashSet<Integer> ();
HashSet<Integer> newset =new HashSet<Integer> ();
for(int i=0;i<nums1.length;i++){
if(!set.contains(nums1[i])){
set.add(nums1[i]);
}
}
for(int i=0;i<nums2.length;i++){
if(set.contains(nums2[i])){
newset.add(nums2[i]);
}
}
//将HashSet转化为int数组
int [] array=new int[newset.size()];
//使用迭代器
int index=0;
for(int nums:newset){
array[index]=nums;
index++;
}
return array;
}
}
数组
题目中限定了数组中的元素大小为1~1000之间,所以也可以考虑使用数组来存放,这里不存放重复值的写法是将数组的对应的数值恒定的设置为1,对于nums1,如果当前的元素在数组中的值为1,那么就放进set集合中。时间复杂度为O(n)
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
int[] array = new int[1001];
HashSet<Integer> set = new HashSet<Integer>();
for (int i = 0; i < nums1.length; i++) {
array[nums1[i]] = 1;// 避免重复值,统一设置为1
}
for (int i = 0; i < nums2.length; i++) {
if (array[nums2[i]] == 1) {// 直接看是否数值为1
set.add(nums2[i]);
}
}
// 将HashSet转化为int型数组
int[] result = new int[set.size()];
int index = 0;
for (int nums : set) {
result[index++] = nums;
}
return result;
}
}
202. 快乐数
Set
无限循环,始终变不到1,这句话表明如果n的值不为1,最后出现循环了,那么就代表不属于快乐数,判断n是否重复出现并且不是1,就和哈希表的使用条件对应了,用set来存放每一次的更新的n值即可。如果n的值在set中出现了,那么就返回false。时间复杂度O(logn)
class Solution {
public boolean isHappy(int n) {
// 无限循环,就不是快乐数
HashSet<Integer> set = new HashSet<Integer>();
while (n != 1 && !set.contains(n)) {
set.add(n);
n = newnum(n);
}
if (set.contains(n))
return false;
return n == 1;
}
// 计算下一个n的值
public int newnum(int n) {
int newnum = 0;
while (n != 0) {
int temp = n % 10;
newnum += temp * temp;
n /= 10;
}
return newnum;
}
}
1. 两数之和
暴力解法是双重循环,知道数组中的一个元素num,我们想知道target-num是否也在数组中,那么可以使用哈希表。同时要返回下标,考虑使用HashMap,这里注意,Key是存放的num,而Value存放的是下标。
class Solution {
public int[] twoSum(int[] nums, int target) {
// 哈希表是用来快速判断一个数是否出现在集合里
HashMap<Integer, Integer> newnums = new HashMap<Integer, Integer>();
for (int i = 0; i < nums.length; i++) {
if (newnums.containsKey(target - nums[i])) {
return new int[] { i, newnums.get(target - nums[i]) };// 注意这里的键是数值,值才是索引
}
newnums.put(nums[i], i);
}
return null;
}
}