LeetCode 242. 有效的字母异位词
Ver1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public boolean isAnagram (String s, String t) { int [] sChars = new int [123 ]; int [] tChars = new int [123 ]; for (int i = 0 ; i < s.toCharArray().length; i++) { sChars[s.charAt(i)]++; } for (int j = 0 ; j < t.toCharArray().length; j++) { tChars[t.charAt(j)]++; } return Arrays.equals(sChars, tChars); }
Ver2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public boolean isAnagram (String s, String t) { if (s.length() != t.length()) { return false ; } int [] alphabet = new int [123 ]; for (int i = 0 ; i < s.toCharArray().length; i++) { alphabet[s.charAt(i)]++; alphabet[t.charAt(i)]--; } return Arrays.equals(alphabet, new int [123 ]); }
Ver3:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public boolean isAnagram (String s, String t) { if (s.length() != t.length()) { return false ; } int [] alphabet = new int [26 ]; for (int i = 0 ; i < s.length(); i++) { alphabet[s.charAt(i) - 'a' ]++; alphabet[t.charAt(i) - 'a' ]--; } for (int i = 0 ; i < alphabet.length; i++) { if (alphabet[i] != 0 ) { return false ; } } return true ; }
这道题的难度不高,使用数组充当哈希表,记录每个字符串中各个字符的数量,但是一些小的细节方面的优化值得注意
比如一开始脑子抽风了使用了s.toCharArray().length导致超时
开辟了两个数组用于记录字符数量
没有检查字符串长度
对两个字符串分别遍历
进阶问题:如果字符串包含unicode字符怎么办?
可以使用hashmap,以字符为key,字符的数量为value,思路一致
LeetCode 349. 两个数组的交集
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class Solution { public int [] intersection(int [] nums1, int [] nums2) { int [] digit1 = new int [1001 ]; int [] digit2 = new int [1001 ]; for (int i = 0 ; i < nums1.length; i++) { digit1[nums1[i]]++; } for (int i = 0 ; i < nums2.length; i++) { digit2[nums2[i]]++; } LinkedList<Integer> ans = new LinkedList <>(); for (int i = 0 ; i < digit1.length; i++) { if (digit1[i] > 0 && digit2[i] > 0 ) { ans.add(i); } } int [] array = new int [ans.size()]; for (int i = 0 ; i < ans.size(); i++) array[i] = ans.get(i); return array; } }
因为本题限制了数组中包含的数字的范围,所以可以使用开两个数组的方法作为哈希表,如果数字范围更大一些,则应该考虑使用set。
LeetCode 202. 快乐数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution { public boolean isHappy (int n) { HashSet<Integer> seen = new HashSet <>(); while ( n != 1 && !seen.contains(n)) { seen.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 /= 10 ; } return res; } }
这道题还是蛮有意思的,一开始没有想明白结束循环的条件,后来才意识到,无限循环意味着重复出现的n,如此,将其加入set,利用set查询时间复杂度为O(1)的优势进行快速查询,如果数字已经check过,那么结束循环,或者数字为1,结束循环。
LeetCode 1.两数之和
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Solution { public int [] twoSum(int [] nums, int target) { HashMap <Integer, Integer> visited = new HashMap <>(); for (int i = 0 ; i < nums.length; i++) { if (visited.containsKey(target - nums[i])) { return new int [] {i, visited.get(target - nums[i])}; }else { visited.put(nums[i], i); } } return null ; } }
两数之和用暴力法解决思路还是挺直接的,但是暴力法的复杂度太高了。双重遍历的复杂度为n^2,其原因是,对于每一个正在check的数字,搜寻target-nums[i]的开销太大,考虑使用set将已经check过的数字cache起来,并利用其查询O(1)的优势。