LeetCode1.两数之和
import java.util.Arrays;
import java.util.HashMap;
public class LeetCode_1 {//力扣第一题: 两数之和
//给定一个整数数组 nums 和一个整数目标值, target请你在该数组中找出 和为目标值 target的那两个整数,并返回它们的数组下标。
//你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
//你可以按任意顺序返回答案。
//示例 1:
//输入:nums = [2,7,11,15], target = 9
//输出:[0,1]
//解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1]
public static void main(String[] args) {
int[] nums = {2, 7, 11, 15};
System.out.println(Arrays.toString(Solution.twoSum2for(nums, 9)));
}
static class Solution {
public int[] twoSum(int[] nums, int target) {
//使用哈希表法优化,去除一层for循环
//题目关键词:要找到对应的两个整数以及他们的数组下标,所以我们同时要得到值和下标,所以得使用map来存
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
map.put(nums[i], i); //map存储数组的所有元素以及对应的下标
}
//todo 自己第一次使用哈希表法做的时候用了先后的两个for循环先完成哈希表的填充再找满足条件的值,其实这两步可以合并到一个for里面,即先找值,值没找到就放入哈希表
//todo 二刷时记得使用单个for进一步优化
for (int j = 0; j < nums.length; j++) {
if (map.containsKey(target - nums[j])) {
if (map.get(target - nums[j]) == j) {
continue;
}
return new int[]{map.get(target - nums[j]), j};
}
}
return new int[]{};
}
public static int[] twoSum2for(int[] nums, int target) {
//暴力思路:两层for循环
for (int i = 0; i < nums.length; i++) {
for (int j = 0; j < nums.length; j++) {
if (i == j) {
continue;
}
if (nums[i] + nums[j] == target) {
return new int[]{i, j};
}
}
}
return null;
}
}
}
LeetCode202.快乐数
class Solution {
//202.判断一个数是否是快乐数
//「快乐数」 定义为:
// 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
// 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 todo 可以无限循环是解题的关键
// 如果这个过程 结果为 1,那么这个数就是快乐数。
//如果 n 是 快乐数 就返回 true ;不是,则返回 false
public boolean isHappy(int n) {
HashSet<Integer> hashSet = new HashSet<>();
//看到题目字眼"重复这个过程,直到这个数变为1,也可能是无限循环始终变不到,就要开始思考使用循环,循环的终止条件?
while (n != 1 && !hashSet.contains(n)) { //终止条件为要么 n在这个过程中变为1了,要么一直无限循环了(也就是出现了重复的数字->转变为判断一个元素是否在某个集合中出现过->哈希法
hashSet.add(n);//这里一定是先add,不然就漏解了
int count = 0;
while (n>0) { // n % 10 != 0 这个条件并不符合获取n的每一位数字的逻辑。
// 因为除以 10 需要考虑到 n 是否大于 0,而不是判断余数是否不等于 0,如果n等于120,一上来n%10就直接等于0了
count += (n %10) * (n % 10);
n=n/10;
}
n = count;
}
return n==1;
}
}
LeetCode242.有效字母异位词
public class LeetCode_242 {//242.有效字母异位词 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词
//示例 1:
//
//输入: s = "anagram", t = "nagaram"
//输出: true
//
//示例 2:
//
//输入: s = "rat", t = "car"
//输出: false
public static void main(String[] args) {
Solution.isAnagram("anagram", "nagaram");
}
static class Solution {
public static boolean isAnagram(String s, String t) {
//思路:判断两个字符串的组成字符是否相同可以转换为将其中一个字符串的每个字符用哈希法存入一张哈希表中
// ,然后判断另一个字符串的字符是否与这张哈希表一模一样 todo 也就是说,当我们遇到类似"求某个元素是否在某个集合中出现过相关的问题,都可以尝试采用哈希表法去解题"
int[] hashTable = new int[26]; //Java中可以作为哈希表的数据结构有三种:1.数组(当元素比较少或者元素哈希索引值不会太分散导致浪费大量空间时优先使用数组 )
// 2.Set(可以存放大量元素,可去重) 3.Map(key-value 结构,当我们一个元素需要存两类值时使用,比如要同时知道某个数字的值以及出现在数组中的位置)
//本题只用简单比较元素是否在哈希表中出现过,而不需要知道顺序,并且如果使用字符串的ASCII码作为哈希索引值大小并不大,字符串的字符数也不会很多,所以直接使用数组作为哈希表
for (int i = 0; i < s.length(); i++) {
hashTable[s.charAt(i) - 'a']++;
}
for (int j = 0; j < t.length(); j++) {
hashTable[t.charAt(j) - 'a']--; //
// todo 这里没有想到 -a 因为26个英文字母中a的ASCII码值最小,所以每个都-a 就可以把数组的索引值固定在26以内减小创建哈希表所需要的数组大小
}
for (int n = 0; n < hashTable.length; n++) {
if (hashTable[n] != 0)
return false;
}
return true;
}
}
}
LeetCode349.求两个数组的交集
import java.util.HashSet;
public class LeetCode_349 { //349.求两个数组的交集 给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一的 我们可以不考虑输出结果的顺序
public static void main(String[] args) {
//示例 1:
//
//输入:nums1 = [1,2,2,1], nums2 = [2,2]
//输出:[2]
//
//示例 2:
//
//输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
//输出:[9,4]
//解释:[4,9] 也是可通过的
//提示:
// 1 <= nums1.length, nums2.length <= 1000
// 0 <= nums1[i], nums2[i] <= 1000
}
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
//set法 三种set中我们使用查找高效的hashSet
HashSet<Integer> hashSet = new HashSet<Integer>();
HashSet<Integer> resultSet = new HashSet<>();
for (int i : nums1) {
hashSet.add(i);
}//先把其中一个数组的所有数字都放到一个set集合里面
for (int i : nums2) {
if (hashSet.contains(i)) {
resultSet.add(i);//在这个set集合中判断另一个数组的哪些数字在我们这个set里出现,如果出现说明就是两个数组的交集中的元素
//放入到resultSet中,因为set不允许有重复元素,所以放入的时候会自动去重,得到的结果转成int数组就是我们要的结果
}
}
return resultSet.stream().mapToInt(result-> result).toArray();
}
}
}