一、有效的字母异位词
力扣242
使用数组作为哈希表存储字符串中a-z这26个字母的出现次数,将字符串中每个字母与字母a的差值映射为数组的下标('a'-'a'=0,'z'-'a'=25),数组中的元素值即为该下标代表的字母出现的次数,这样可以得到一个字符串中每个字母出现的次数。
本题的巧妙之处在于,可以同时记录字符串s和t的每个字母的出现次数,并齐映射到同一个数组time中,如果一个字母在s中出现就将数组对应元素加一,在t中出现就将数组对应元素减一,这样,如果最终得到的数组的中的每个元素的值都为0,则说明这两个字符串是有效的字母异位词。
时间复杂度: O(n)
空间复杂度: O(1)
class Solution {
public boolean isAnagram(String s, String t) {
int[] time = new int[26];
for(int i = 0; i < s.length(); i++){
//该字符与字母a的差值即为time数组下标
time[s.charAt(i) - 'a']++;
}
for(int i = 0; i < t.length(); i++){
//s使得time[i]加1,则t就使得time[i]减一,最后保证数组为0
//如果数组数组有数不为0,说明s和t不为字母异位词
time[t.charAt(i) - 'a']--;
}
for(int i = 0; i < time.length; i++){
if(time[i] != 0){
return false;
}
}
return true;
}
}
二、两个数组的交集
力扣349
思路与上题类似,将nums1和nums2中的元素值映射为n1和n2两个数组的下标(nums1[2] = 56,则n1[56]++),如果有满足使得n1和n2在该处同时不为0的下标,则说明该下标对应的数在num1和num2中同时出现,将该下标存入一个数组result中。最后遍历result数组得到两个数组的交集元素。
时间复杂度: O(n + m)
空间复杂度: O(n)
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
//时间复杂度: O(n)
//空间复杂度: O(1)
int[] n1 = new int[1002]; //0 <= nums1[i], nums2[i] <= 1000共有1001个映射,多给一个冗余
int[] n2 = new int[1002];
int index = 0;
//构建哈希表,将num1和nums2中的数对应于n1下标
for(int i = 0; i < nums1.length; i++){
index = nums1[i];
n1[index]++;
}
for(int i = 0; i < nums2.length; i++){
index = nums2[i];
n2[index]++;
}
//将nums1和nums2相同元素存入list中
List<Integer> list = new ArrayList();
for(int i = 0; i < n1.length; i++){
if(n1[i] > 0 && n2[i] > 0){
list.add(i);
}
}
//将list转为数组
//O(m)
int[] result = new int[list.size()];
for(int i = 0; i < list.size(); i++){
result[i] = list.get(i);
}
return result;
}
}
三、快乐数
力扣202
getLastNumber方法用于计算一个数每位的平方和。
如果一个数是快乐数,则说明在其每位数平方和计算过程中没有出现过相同的结果,因为如果本次调用getLastNumber计算结果在之前的计算中出现过,则如果继续计算下去会导致无数次这种循环。因此,可以通过循环计算一个数的每位平方和,当出现计算结果为1(该数为快乐数)和已知结果(无限循环)时,退出循环。
时间复杂度: O(logn)
空间复杂度: O(logn)
class Solution {
//得到每一位数的平方和
int getLastNumber(int n){
int num = 0;
while(n > 0){
int temp = n % 10;
num += temp * temp;
n /= 10;
}
return num;
}
public boolean isHappy(int n) {
Set<Integer> result = new HashSet<>();
while(n != 1 && !result.contains(n)){
result.add(n);
n = getLastNumber(n);
}
if(n == 1){
return true;
}else{
return false;
}
}
}
四、两数之和
力扣1
对于数组中的元素,通过target-num[i]来在已经遍历过的数中查找是否存在满足条件的数。因为不知道要遍历多少才能找到符合条件的数,所以用Map来存储已经遍历过的数,将数的值设置为key,将其对应数组下标设为value,如果出现值等于target-num[i]的数,则根据其值(key)返回其数组下标(value)。
时间复杂度: O(n)
空间复杂度: O(n)
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] result = new int[2];
if(nums.length == 0 && nums == null){
return result;
}
//Map用来存储已经访问过的数组元素,并且将该元素的值作为key,将该元素在数组的下标作为value
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < nums.length; i++){
int temp = target - nums[i];
//在map中查找的时间复杂度理论上是o(1)
//在map中查找是否有符合条件的值
if(map.containsKey(temp)){
result[0] = map.get(temp);
result[1] = i;
break;
}
map.put(nums[i], i);
}
return result;
}
}