242.有效的字母异位词
题目链接: 力扣
思路
这道题目是要判断来判断 t 是否是 s 的字母异位词。其本质就是判断这两个字符串中的字符出现的种类和次数是否都是一样的。因为26个字母的字符编码是连续的数字,字母的数字是固定的,而且也是连续的,所以可以创建一个长度为26的数组来记录每个字母出现的次数
如果要判断的不是单纯的小写英文字母,没有规律,此时就要换一种记录方式了,使用Map集合记录更为合适,没有特别的长度限制
有效的字母异位词
对于只有纯小写英文字母的判断:
第一步:创建数组容器
第二步:遍历s字符串,通过增加数字记录每个字母出现的次数
第三步:遍历t字符串,通过减小数字记录每个字母出现的次数
第四步:判断数组中的全部是否为0
class Solution { public boolean isAnagram(String s, String t) { if (s.length() != t.length()) { return false; } // 使用数组作为哈希表记录每个字母出现的次数 // 首先创建数组容器 int[] record = new int[26]; // 遍历s字符串,通过增加数字记录每个字母出现的次数 for (int i = 0 ; i < s.length() ; i++) { record[s.charAt(i) - 'a']++; } // 遍历t字符串,通过减小数字记录每个字母出现的次数 for (int i = 0 ; i < t.length() ; i++) { record[t.charAt(i) - 'a']--; } // 判断是否数组中全部的数字为0 for (int i = 0 ; i < record.length ; i++) { if ( record[i] != 0 ) { return false; } } return true; } }
对于UniCode编码的字符的判断:
使用Map作为容器
class Solution { public boolean isAnagram(String s, String t) { if (s.length() != t.length()) { return false; } // 创建容器 Map<Character,Integer> maps = new HashMap<>(); // 遍历第一个字符串 for (int i = 0 ; i < s.length() ; i++) { char ch = s.charAt(i); maps.put(ch,maps.getOrDefault(ch,0) + 1); } // 遍历第二个字符串 for (int i = 0 ; i < t.length() ; i++) { char ch = t.charAt(i); maps.put(ch,maps.getOrDefault(ch,0) - 1); if (maps.get(ch) < 0) { return false; } } return true; } }
349. 两个数组的交集
题目链接:力扣
思路
首先这个题目的两个注意点:1、结果中的元素一定是唯一的 2、不考虑输出结果的顺序 。这种情况下最容易想到的就是Set集合。set集合的特点就是无序不可重复。
所以首先将nums1的所有数字记录到一个set1集合中,此时这个set1集合中是nums1的所有出现过的数字
再次遍历nums2数组,如果再set1集合中包含这个数字,就将数字记录到set2集合中
两个数组的交集
第一步:对数组nums1进行遍历,将数字添加到set集合中
第二步:遍历nums2数组,将再set1集合中出现过的数组记录到set2中
第三步:将set2集合转换成int[]数组
不常用的知识点:
将set集合转换成int[]数组
setNums2.stream().mapToInt(x -> x).toArray();
class Solution { public int[] intersection(int[] nums1, int[] nums2) { // 创建容器,这里采用Set集合,无序不可重复 Set<Integer> setNums1 = new HashSet<>(); Set<Integer> setNums2 = new HashSet<>(); // 对数组nums1进行遍历,将数字添加到set集合中 for (Integer i : nums1) { setNums1.add(i); } for (Integer i : nums2) { // 这里写复杂了,忘记contains()方法了 /** for (Integer j : setNums1) { if (i.equals(j)) { setNums2.add(i); } } */ if (setNums1.contains(i)) { setNums2.add(i); } } return setNums2.stream().mapToInt(x -> x).toArray(); } }
202. 快乐数
题目链接:力扣
思路
还是要注意读题,一开始自己思考的时候就是想着怎么判断这个数字知道1,忽略了题目中所说的会出现无限循环的情况
这个题目的两个难点:
1、一个难点就是求和的过程,如果对取数值各个位上的单数操作不熟悉的话,做这道题
也会比较艰难
2、判断不断地将一个数的每一位数字平方和后的走向,能判断出出现的情况,才能通过其中的原理来选择合适的集合
来自力扣官方:我们使用哈希集合而不是向量、列表或数组的原因是因为我们反复检查其中是否存在某数字。检查数字是否在哈希集合中需要 O(1)的时间,而对于其他数据结构,则需要 O(n)的时间。选择正确的数据结构是解决这些问题的关键部分。
快乐数
第一步:照题目的要求做数位分离,求平方和
第二步:判断出了数字的走向就两种情况,要么最后是1,要么最后就是在无限循环,那就不断去判断就好了,这也是为什么选择set集合的原因(因为set集合无序不可重复)
class Solution { public boolean isHappy(int n) { Set<Integer> serNums = new HashSet<>(); while (n != 1 && !serNums.contains(n)) { serNums.add(n); n = getNextNumber(n); } return n == 1; } // 取各个位上的数值 public int getNextNumber(int num) { int sum = 0; while (num > 0) { int temp = num % 10; sum += temp * temp; num = num / 10; } return sum; } }
1. 两数之和
题目链接:力扣
思路
当需要查询一个元素是否出现过,或者一个元素是否在集合里的时候,就要第一时间想到哈希法
我们不仅要知道元素有没有遍历过,还有知道这个元素对应的下标,需要使用 key value结构来存放,key来存元素,value来存下标,那么使用map正合适。
哈希法还有两种就是数组和Set,用数组查找我们还有知道元素对应的下标,那就相当于暴力解法了。set只能存数字不重复,我还需要一个下标进行存储,所以使用map比较合适
而且使用map的时候,需要考虑两个一样的数等于目标和的情况:如果先把所有的数都存进map里面,会把重复的数字和下标略去,所以一定要边添加边判断
两数之和
暴力解法
class Solution { public int[] twoSum(int[] nums, int target) { // 创建数组接收结果 int[] result = new int[2]; // 遍历nums集合,得到每一个数字与目标值对应的差 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; } }
哈希法
第一步:创建接收下标的集合,创建Map集合
第二步:遍历数组,判断集合中是否有满足teaget-nums[i] 存在的数字
第三步:如果不存在,就将此时的数字和对应的下标添加到集合中,如果存在就将此时对应的两个数字的下标存储到数组中
class Solution { public int[] twoSum(int[] nums, int target) { int[] result = new int[2]; Map<Integer,Integer> mapNums = new HashMap<>(); for (int i = 0 ; i < nums.length ; i++) { int temp = target - nums[i]; if (mapNums.containsKey(temp)) { result[0] = i; result[1] = mapNums.get(temp); } mapNums.put(nums[i],i); } return result; } }
要注意一个点就是面对重复的的数字,如果先将数字全部移到Map集合中,重复的就不能收集进去了。比如[3,3],使用下面这种方法就会返回[1,1],结果应该是[0,1]的,以下是错误的代码:(记录一下,这种写法忽略了[3,3]这种情况)
class Solution { public int[] twoSum(int[] nums, int target) { int[] result = new int[2]; Map<Integer,Integer> mapNums = new HashMap<>(); for (int i = 0 ; i < nums.length ; i++) { mapNums.put(nums[i],i); } for (int i = 0 ; i < nums.length ; i++) { if (mapNums.containsKey(target - nums[i])) { result[0] = i; result[1] = mapNums.get(target - nums[i]); } } return result; } }