-
两数之和(Two Sum)
问题描述:
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。
解决方案:
暴力法:使用两层嵌套循环,遍历所有可能的数对,检查它们的和是否等于目标值。时间复杂度为 O(n^2)。
哈希表法:使用哈希表存储每个元素的值和索引。遍历数组时,检查 target - nums[i] 是否已经在哈希表中。如果存在,返回这两个索引。时间复杂度为 O(n)。
//1. 两数之和
public int[] twoSum(int[] nums, int target) {
//暴力法
/int[] result = new int[2];
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
if (nums[i] + nums[j] == target) {
result[0] = i;
result[1] = j;
}
}
}
return result;/
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
if (map.containsKey(target - nums[i])) {
return new int[]{map.get(target - nums[i]), i};
}else {
map.put(nums[i], i);
}
}
return new int[]{};
} -
快乐数(Happy Number)
问题描述:
编写一个算法来判断一个数是不是“快乐数”。
从一个正整数开始,每次将该数替换为它每个位上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是无限循环但始终变不到 1。
如果这个过程结束时,这个数变为 1,那么这个数就是快乐数。
解决方案:
哈希集合法:使用一个集合记录已经出现过的数,避免无限循环。如果某个数再次出现,说明进入了循环,返回 false。如果某个数变为 1,返回 true。
快慢指针法:使用两个指针,一个快一个慢,快指针每次走两步,慢指针每次走一步。如果存在循环,快慢指针最终会相遇。如果某个数变为 1,返回 true。
//第202题. 快乐数
public boolean isHappy(int n) {
Setset = new HashSet<>();
while (true){
int sum = 0;
while (n > 0) {
int temp = n % 10;
sum += temptemp;
n = n / 10;
}
if(sum==1){
return true;
}else {
if(set.contains(sum)){
return false;
}else {
set.add(sum);
n=sum;
}
}
}
///快慢指针法,效率更高
public int getNext(int n) {
int totalSum = 0;
while (n > 0) {
int d = n % 10;
n = n / 10;
totalSum += d * d;
}
return totalSum;
}public boolean isHappy(int n) {int slowRunner = n;int fastRunner = getNext(n);//无限循环则快慢指针的值会相等while (fastRunner != 1 && slowRunner != fastRunner) {slowRunner = getNext(slowRunner);fastRunner = getNext(getNext(fastRunner));}return fastRunner == 1;*/
}
-
两个数组的交集(Intersection of Two Arrays)
问题描述:
给定两个数组,编写一个函数返回它们的交集。
解决方案:
排序法:先对两个数组进行排序,然后使用双指针遍历两个数组,找到相同的元素并添加到结果集合中。最后将集合转换为数组。
哈希集合法:使用两个集合分别存储两个数组的元素,然后遍历其中一个集合,检查元素是否在另一个集合中。如果在,添加到结果集合中。最后将集合转换为数组。
代码:
//349. 两个数组的交集
public int[] intersection(int[] nums1, int[] nums2) {
/*Stream.toArray()
*功能
该方法将流中的元素收集到一个 Object[] 数组中。
返回的数组类型是 Object[],数组中的每个元素都是流中的一个元素。
*Stream.toArray(Generator<T[]> generator)
*当你需要特定类型的数组(如 Integer[]、String[] 等)时,可以使用这个方法。
* stream().mapToInt(Integer::intValue).toArray()
* 如果是先转成基本数据类型再存储到数组中,就不用在roArray()中传参
* /
Arrays.sort(nums1);
Arrays.sort(nums2);
Setset = new HashSet<>();
int i = 0, j = 0;
while (i < nums1.length && j < nums2.length) {
if (nums1[i] == nums2[j]) {
set.add(nums1[i]);
i++;
j++;
} else if (nums1[i] < nums2[j]) {
i++;
} else {
j++;
}
}
//.mapToInt(Integer::intValue),直接用数组接收比使用流效率高
return set.stream().mapToInt(Integer::intValue).toArray();
/
//少了sort排序,效率高一点。直接用数组按哈希法处理效率会更高,但是不具备普适性
Setset1 = new HashSet<>();
Setset2 = new HashSet<>(); for(int num:nums1){set1.add(num);}for(int num:nums2){if(set1.contains(num)){set2.add(num);}}int[] result = new int[set2.size()];int index = 0;for(int num:set2){result[index++]=num;}return result;*/
}
-
有效的字母异位词(Valid Anagram)
问题描述:
给定两个字符串 s 和 t,编写一个函数判断它们是否是字母异位词。
解决方案:
哈希表法:使用两个哈希表分别记录两个字符串中每个字符的出现次数,然后比较两个哈希表是否相等。
计数法:使用一个长度为 26 的数组记录每个字符的出现次数。遍历字符串 s 时,增加对应字符的计数;遍历字符串 t 时,减少对应字符的计数。最后检查数组中的所有计数是否为 0。
//242.有效的字母异位词
public boolean isAnagram(String s, String t) {
/char[] s1 = s.toCharArray();
char[] t1 = t.toCharArray();
Map<Character, Integer> map1 = new HashMap<>();
Map<Character, Integer> map2 = new HashMap<>();
for (char c : s1) {
map1.put(c, map1.getOrDefault(c, 0) + 1);
}
for (char c : t1) {
map2.put(c, map2.getOrDefault(c, 0) + 1);
}
return map1.equals(map2);/
//不具备普适性,toCharArray()遍历字符串字符比charAt()遍历字符串中字符效率高,增强for比普通for效率高
int[] s1 = new int[26];
int[] t1 = new int[26];
for (char c : s.toCharArray()) {
s1[c - 'a']++;
}
for (char c : t.toCharArray()) {
t1[c - 'a']++;
}
for (int i = 0; i < 26; i++) {
if (s1[i] != t1[i]) {
return false;
}
}
return true;
}