389. 找不同
题目描述
给定两个字符串 s
和 t
,它们只包含小写字母。
字符串 t
由字符串 s
随机重排,然后在随机位置添加一个字母。
请找出在 t
中被添加的字母。
示例 1:
输入:s = "abcd", t = "abcde"
输出:"e"
解释:'e' 是那个被添加的字母。
示例 2:
输入:s = "", t = "y"
输出:"y"
方法一:统计每个字母出现次数
我看到这个题目的第一反应是用两个数组 a
和 b
分别统计字符串 s
和 t
中每个字符出现的次数,然后遍历两个数组,数组b
比数组 a
多一个的便是多出来的字母;
class Solution {
public char findTheDifference(String s, String t) {
int[] a = new int[26];
int[] b = new int[26];
for (int i = 0; i < s.length(); i++) {
a[s.charAt(i) - 'a']++;
b[t.charAt(i) - 'a']++;
}
b[t.charAt(t.length()-1) - 'a']++;
char ans = 0;
for (int i = 0; i < 26; i++) {
if (b[i] > a[i]) {
ans = (char) (i + 'a');
}
}
return ans;
}
}
不过官方解答中的减法确实是比我的要好。空间复杂度要少。具体如下:
- 首先遍历字符串
s
,对其中的每个字符都将计数值加1
; - 然后遍历字符串
t
,对其中的每个字符都将计数值减1
。 - 当发现某个字符计数值为负数时,说明该字符在字符串
t
中出现的次数大于在字符串s
中出现的次数,因此该字符为被添加的字符。
class Solution {
public char findTheDifference(String s, String t) {
int[] cnt = new int[26];
for (int i = 0; i < s.length(); ++i) {
char ch = s.charAt(i);
cnt[ch - 'a']++;
}
for (int i = 0; i < t.length(); ++i) {
char ch = t.charAt(i);
cnt[ch - 'a']--;
if (cnt[ch - 'a'] < 0) {
return ch;
}
}
return ' ';
}
}
方法二:求和
将字符串 s
中每个字符的 ASCII 码的值求和,得到 ans1
;对字符串 t
同样的方法得到 ans2
。两者的差值 ans2-ans1
即代表了被添加的字符。
class Solution {
public char findTheDifference(String s, String t) {
char ans1 = 0, ans2 = 0;
for (char c:s.toCharArray()) {
ans1 += c;
}
for (char c:t.toCharArray()) {
ans2 += c;
}
return (char) (ans2 -ans1;
}
}
方法三:位运算
如果将两个字符串拼接成一个字符串,则问题转换成求字符串中出现奇数次的字符。类似于「136. 只出现一次的数字」,我们使用位运算的技巧解决本题。
class Solution {
public char findTheDifference(String s, String t) {
int ret = 0;
for (int i = 0; i < s.length(); ++i) {
ret ^= s.charAt(i);
}
for (int i = 0; i < t.length(); ++i) {
ret ^= t.charAt(i);
}
return (char) ret;
}
}