链接:https://leetcode.cn/problems/find-the-difference/description/
题目
简单来说 t 是由 s 随机重排,并添加一个字母而来的,那么已知:
- t 的长度比 s 的长度大,并且为 1
- s 和 t 中存在的字母数量 除了 t 新增的字母,其他都是一致的
解法一
思路
通过使用 哈希表,通过对两个字符串的字符索引(规则:字母 - 'a';例如:b,那么索引就为 1)分别进行哈希表计数,最终对比两张哈希表中的数量,数量不同,则说明当前索引对应的字母就是 t 新添加的字母
因为 s 和 t 的范围为 26个小写字母,那么直接通过 int 数组去模拟哈希表即可,例如:'a' 就代表数组索引 0,'b' 就代表数组索引 1
代码
/** * 执行用时分布 2 ms 击败 67.07% 消耗内存分布 42.42 MB 击败 62.25% * 利用 哈希表 字符计算找不同,只要两张 哈希表 的数量不同,则当前下标 + 'a' 就能得到添加的 字母 */ public char findTheDifference(String s, String t) { // s 为空(s.length = 0),那就说明 t的长度为1,并且就是答案 if (s.isEmpty()){ return t.charAt(0); } // 因为 t 为 s 的随机重排,所以需要计数,才能知道新增的 字母是哪一个 // 定义两个数组用于存放对应字母有多少个 int[] sMap = new int[26]; int[] tMap = new int[26]; // 遍历 s 和 t for (int i = 0; i < s.length(); i++){ // s 下标 = 字母 与 'a' 的 Unicode 码点距离(a 到 z 是按顺序的),例如:'b' - 'a' = 1 int sIndex = s.charAt(i) - 'a'; sMap[sIndex]++; // 等同于上面,只是换种写法 tMap[t.charAt(i) - 'a']++; } // 因为 t 少遍历了一次,所以这里再进行处理 tMap[t.charAt(t.length() - 1) - 'a']++; // 对比 sMap 和 tMap 的数量,就能找出不同 for (int i = 0; i < 26; i++){ // 数量不相同,代表找到了不同,直接返回即可 if (sMap[i] != tMap[i]){ return (char)('a' + i); } } // 不可能走到这里,因为上面已经遍历完了,返回 'a',只是因为不能返回空 return 'a'; }
解法二
思路
既然 t 字符串中的字母除了新增加的 字母,其余的都与 s 一致(排除字母随机重排的因素),那么就可以将 两张哈希表缩少为 一张哈希表。
每当遍历 s 和 t 字符串的一个字母时,s 出现的字母,哈希表对应的数组索引 减一,t 出现的字母,哈希表对应的数组索引 加一。遍历结束后,哈希表中只有一个值为 1,其他为0。
最终遍历哈希表,如果值为 1,直接返回对应的字母即可
代码
/** * 执行用时分布 2 ms 击败 67.07% 消耗内存分布 42.14 MB 击败 97.27% * 使用 哈希表,并对 s 和 t 字符串对应的字母,进行抵消的方式,最终只要哈希表中索引不为 0,就是 t 字符串新增的字母 */ public char findTheDifference(String s, String t) { // 使用 数组 模拟哈希表 int[] map = new int[26]; // 遍历 s 和 t for (int i = 0; i < s.length(); i++){ // s 对应的字母,就往 哈希表中对应的索引 减 1 map[s.charAt(i) - 'a']--; // t 对应的字母,就往 哈希表中对应的索引 加 1 map[t.charAt(i) - 'a']++; } // 因为 t 少遍历了一次,所以这里再进行处理 map[t.charAt(t.length() - 1) - 'a']++; // 遍历哈希表 for (int i = 0; i < 26; i++){ if (map[i] != 0){ return (char)('a' + i); } } return 'a'; }
解法三
思路
还是和 上面解法二的思路差不多,只不过,现在不用哈希表了,直接使用 int 进行加减,此消彼长,最后加减得到的数,就是 t 新增的字母
代码
/** * 执行用时分布 2 ms 击败 67.07% 消耗内存分布 42.34 MB 击败 79.87% * 使用 int 直接计数的方式,对字符串 s 出现的字母 和 字符串 t 出现的字母,相互抵消,最终得到的结果就是 t 新添加的子母 */ public char findTheDifference3(String s, String t) { int sum = 0; // 遍历 s 和 t for (int i = 0; i < s.length(); i++){ // sum = sum + t.charAt(i) + 'a' - (s.charAt(i) - 'a') // sum = sum + t.charAt(i) - s.charAt(i); sum += t.charAt(i) - s.charAt(i); } // 因为 t 少遍历了一次,所以这里再进行处理 sum += t.charAt(t.length() - 1) - 'a'; return (char)('a' + sum); }