242. 有效的字母异位词
res[26] ;
++
--
00
判断两个单词是否字母 出现的次数都相同,因为字母只有26个小写的,所以可以考虑用数组当hash表,并且可以确定每个字母的位置(当前字母-'a'用作数组下标),第一个单词中所有字母出现的次数,应该与第二个字母的相等(res[a]++; res[b]--;)
res[26]这个数组中所有的数字都清零了证明都是相同的,否则不成立。
public boolean isAnagram(String s, String t) {
int[] res=new int[26];
for(int a=0;a<s.length();a++){
res[s.charAt(a)-'a']++;
}
for(int b=0;b<t.length();b++){
res[t.charAt(b)-'a']--;
}
for(int i=0;i<26;i++){
if(res[i]!=0){
return false;
}
}
return true;
}
349. 两个数组的交集
思路:
O(n^2) 方法就是暴力解决,需要求数组交集的情况下,可以把第一个数组变成哈希表1,减少遍历,因为只看两个数组中都重复出现的次数,再用哈希表2存哈希表1中存储过的数据,
if(hash1.contains(i)){
hash2.add(i);
}
最后返回的是数组,遍历一遍表2存储结果;
public int[] intersection(int[] nums1, int[] nums2) {
Set<Integer> exist=new HashSet<Integer>();
Set<Integer> rese=new HashSet<Integer>();
for(int i=0;i<nums1.length;i++){
exist.add(nums1[i]);
}
for(int i=0;i<nums2.length;i++){
if(exist.contains(nums2[i])){
rese.add(nums2[i]);
}
}
int j=0;
int[] res=new int[rese.size()];
for(Integer i:rese){
res[j++]=i;
}
return res;
}
202.快乐数
二刷思路:先计算每次的结果(按位取平方),总体循环退出条件是 (无限循环或者是就是1)这两种情况都需要终止循环,最终以是否是1判断true or false.
核心思路先是肯定了这其中一定有一个按位拆分,计算平方和的函数,n/10 循环变量,n%10是没位的数字,
public int getNext(int n) {
int sum = 0;
while (n > 0) {
sum += (n % 10) * (n % 10);
n /= 10;
}
return sum;
}
怎么计算一定能是快乐数呢?
我们猜测会有以下三种可能。
- 最终会得到 1。
- 最终会进入循环。
- 值会越来越大,最后接近无穷大。
第三个情况比较难以检测和处理。我们怎么知道它会继续变大,而不是最终得到 1 呢?我们可以仔细想一想,每一位数的最大数字的下一位数是多少。
对于 3 位数的数字,它不可能大于 243。这意味着它要么被困在 243 以下的循环内,要么跌到 1。4 位或 4 位以上的数字在每一步都会丢失至少1位,直到降到 3 位为止。所以我们知道,最坏的情况下,算法可能会在 243 以下的所有数字上循环,然后回到它已经到过的一个循环或者回到 1。但它不会无限期地进行下去,所以我们排除第三种选择。
哈希表用于存储已经出现过的中间数字,最后结果可能是无限循环,也可能是取到1了,所以要判断一下。
public boolean isHappy(int n) {
Set<Integer> exist = new HashSet<Integer>();
while (n != 1 && !exist.contains(n)) {
exist.add(n);
n = getNext(n);
}
return n == 1;
}
1. 两数之和
回到梦开始的地方了,我一直都是暴力解决的,所以甚至对哈希表的解法没什么印象,对时间空间复杂度也没什么追求,可以用set解决,也可以用map解决。
set需要多遍历一次。
public int[] twoSum(int[] nums, int target) {
int[] res=new int[2];
Set<Integer> gap=new HashSet<Integer>();
Boolean check=false;
for(int i=0;i<nums.length;i++){
if(gap.contains(nums[i])){
res[1]=i;
check=true;
break;
}else{
gap.add(target-nums[i]);
}
}
for(int i=0;i<res[1];i++){
if(nums[i]==target-nums[res[1]]){
res[0]=i;
break;
}
}
return res;
}
map解决相对方便一些
public int[] twoSum(int[] nums, int target) {
//hash表存之后的数据
//<数值,下标>
int n=nums.length;
Map<Integer,Integer> exist=new HashMap<Integer,Integer>();
for(int i=0;i<n;i++){
if(exist.containsKey(target-nums[i])){
return new int[]{exist.get(target-nums[i]),i};
}
else{
exist.put(nums[i],i);
}
}
return new int[0];
}