242.有效的字母异位词
题目链接
思路:
1.首先想到的是用一个数组来记录每个字母出现的次数
2.其次,也可以把数组替换为HashMap
3.用map来做这道题不能通过containsKey来做,因为字符串长度可能不同。
方法一:数组
时间复杂度O(n)
空间复杂度O(1)
class Solution {
public boolean isAnagram(String s, String t) {
int[] records = new int[26];
for (int i = 0; i < s.length(); i++) {
records[s.charAt(i) - 'a']++;
}
for (int i = 0; i < t.length(); i++) {
records[t.charAt(i) - 'a']--;
}
for (int i = 0; i < records.length; i++) {
if (records[i] != 0) {
return false;
}
}
return true;
}
}
方法二:哈希表
一定要记录每个字母出现的次数
1.这道题不推荐使用哈希表来记录,因为时间复杂度可空间复杂度都是O(n)
2.注意第二个for循环中的map.put(s.charAt(i), map.getOrDefault(s.charAt(i), 0) - 1);
不能使用map.get(),因为当字符串t存在字符串s没有的字符时,会产生npe
class Solution {
public boolean isAnagram(String s, String t) {
HashMap<Character, Integer> map = new HashMap<>();
for (int i = 0; i < t.length(); i++) {
map.put(t.charAt(i), map.getOrDefault(t.charAt(i), 0) + 1);
}
for (int i = 0; i < s.length(); i++) {
map.put(s.charAt(i), map.getOrDefault(s.charAt(i), 0) - 1);
}
Set<Character> set = map.keySet();
for (Character c : set) {
if (map.get(c) != 0) {
return false;
}
}
return true;
}
}
349. 两个数组的交集
题目链接
思路:
1.可以用set来做,先把一个数组放入set,另一个再来放,如果放不进去就放入结果
2.可以用map来做,两个数组都存入map,最后把计数为2的key放入结果(不能使用这种方法,因为一个数组中可能有多个相同的元素)
3.也可以就用contains或者containsKey来判断
用map最后也要用set来进行去重
方法一:set
时间复杂度O(n)
空间复杂度O(n)
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
if (nums1.length == 0 || nums1 == null || nums2.length == 0 || nums2 == null) {
return new int[0];
}
Set<Integer> set = new HashSet<>();
Set<Integer> resSet = new HashSet<>();
for (int num : nums1) {
set.add(num);
}
for (int num : nums2) {
if (set.contains(num)) {
resSet.add(num);
}
}
return resSet.stream().mapToInt(Integer::intValue).toArray();
}
}
202. 快乐数
题目链接
思路:很直白的解法,注意使用set来防止循环
class Solution {
public boolean isHappy(int n) {
Set<Integer> record = new HashSet<>();
while (n != 1 && !record.contains(n)) {
record.add(n);
n = getNextNumber(n);
}
return n == 1;
}
private int getNextNumber(int n) {
int res = 0;
while (n > 0) {
int temp = n % 10;
res += temp * temp;
n = n / 10;
}
return res;
}
}
1. 两数之和
题目链接
思路:
1.用map存储所有数组元素和下标,这就是map的好处,再遍历的时候,直接record.containsKey(target - nums[i])
2.注意6 = 3 + 3
这种情况,所以要加上 i != record.get(target - nums[i])
,不能是自己本身相加
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> record = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
record.put(nums[i], i);
}
for (int i = 0; i < nums.length; i++) {
if (record.containsKey(target - nums[i]) && i != record.get(target - nums[i])) {
return new int[] {i, record.get(target - nums[i])};
}
}
return null;
}
}
拓展
leetcode上还有三数之和,四数之和等,其实我们都可以把他看作在两数之和的基础上来做可以写出一个n数之和的模板
1.返回的不是下标
2.数组升序排序,因为用的双指针
public static List<List<Integer>> nSumTarget(int[] nums, int startIndex, int target, int n) {
if (nums == null) {
return new ArrayList<>();
}
int len = nums.length;
List<List<Integer>> res = new ArrayList<>();
if (n < 2 || len < n) {
return res;
}
if (n == 2) {
int lo = startIndex;
int hi = len - 1;
while (lo < hi) {
int sum = nums[lo] + nums[hi];
int left = nums[lo];
int right = nums[hi];
if (sum < target) {
while (lo < hi && nums[lo] == left) {
lo++;
}
} else if (sum > target) {
while (lo < hi && nums[hi] == right) {
hi--;
}
} else if (sum == target) {
ArrayList<Integer> path = new ArrayList<>();
path.add(nums[lo]);
path.add(nums[hi]);
res.add(path);
while (lo < hi && nums[lo] == left) {
lo++;
}
while (lo < hi && nums[hi] == right) {
hi--;
}
}
}
} else {
for (int i = startIndex; i < len; i++) {
List<List<Integer>> lists = nSumTarget(nums, i + 1, target - nums[i], n - 1);
for (List<Integer> list : lists) {
list.add(nums[i]);
res.add(list);
}
while (i < len - 1 && nums[i] == nums[i + 1]) {
i++;
}
}
}
return res;
}