389. 找不同
题目来源:力扣(LeetCode)https://leetcode-cn.com/problems/find-the-difference/
题目
给定两个字符串 s 和 t,它们只包含小写字母。
字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。
请找出在 t 中被添加的字母。
示例 1:
输入:s = "abcd", t = "abcde"
输出:"e"
解释:'e' 是那个被添加的字母。
示例 2:
输入:s = "", t = "y"
输出:"y"
示例 3:
输入:s = "a", t = "aa"
输出:"a"
示例 4:
输入:s = "ae", t = "aea"
输出:"a"
提示:
0 <= s.length <= 1000
t.length == s.length + 1
s
和t
只包含小写字母
解题思路
思路:计数、位运算、求和
先审题,题目中给定两个字符串 s s s 和 t t t,它们只含小写字母。
其中字符串 t t t 由字符串 s s s 重排,在随机的位置上添加一个字母,现在要求找出 t t t 中被添加的字母。
计数
题目已说明,字符串 t t t 比字符串 s s s 多一个字母,那么我们可以先用数组统计 s s s 的字符出现的次数。
然后开始遍历字符串 t t t,数组中对应字符的次数减 1。当数组中出现负数,那么代表对应的字符就是添加的字母。
具体的代码实现如下。
class Solution:
def findTheDifference(self, s: str, t: str) -> str:
# 长度为 26 的数组,用以统计字符出现次数
str_count = [0] * 26
# 先遍历 s,统计 s 中字符出现的次数
for ch in s:
str_count[ord(ch)-ord('a')] += 1
# 再遍历 t,将出现字符对应次数减 1,
# 当出现负值,表示对应的字符就是添加的字母
for ch in t:
str_count[ord(ch)-ord('a')] -= 1
if str_count[ord(ch)-ord('a')] < 0:
return ch
return ''
复杂度分析
- 时间复杂度: O ( N ) O(N) O(N), N N N 表示字符串长度。
- 空间复杂度: O ( ∣ Σ ∣ ) O(|\Sigma|) O(∣Σ∣),其中 Σ \Sigma Σ 是字符集,这里字符串中只包含小写字母, ∣ Σ ∣ = 26 |\Sigma|=26 ∣Σ∣=26。使用长度为 26 26 26 的数组统计字符出现次数。
位运算
这道题中,字符串 t t t 比字符串 s s s 只多了一个字母,那么如果将两个字符串拼接起来,那么就可以转化为求字符串中出现次数为奇数的字符。就如站内的 136 题【136. 只出现一次的数字】(位运算)。
那么我们可以用位运算来解决这个问题。
这里再提下异或的性质:二进制位同一位相同则为 0,不同则为 1。关于异或的规律:
- 任何数与自身异或结果为 0。
- 任何数与 0 异或结果为本身。
同时,异或满足交换律、结合律(数学符号:⊕)
- 交换律:a ⊕ b = b ⊕ a
- 结合律:a ⊕ (b ⊕ c) = (a ⊕ b) ⊕ c
这里使用位运算异或具体的思路如下:
- 初始化遍历 a n s ans ans 为 0(根据上面异或的第 2 个规律);
- 遍历开始对两个字符串的字符都进行异或(将字符转换为对应的 ASCII 值);
- 最终将 a n s ans ans 转换为对应的 ASCII 字符,就是要求的结果。
具体的代码实现如下。
class Solution:
def findTheDifference(self, s: str, t: str) -> str:
# 初始化 ans 为 0
ans = 0
# 对字符串 s 的字符进行异或
for ch in s:
ans ^= ord(ch)
# 对字符串 t 的字符进行异或
for ch in t:
ans ^= ord(ch)
# 最终结果转换为 ASCII 字符
return chr(ans)
在 Python 当中,我们可以借助chr()、ord()、map()、reduce()、xor()
这些函数用一行代码来解答这个问题。代码如下。
from operator import xor
from functools import reduce
class Solution:
def findTheDifference(self, s: str, t: str) -> str:
return chr(reduce(xor, map(ord, s + t)))
其中 xor()
在 operator
库中,函数返回的是按位异或结果。
reduce()
在
p
y
t
h
o
n
3.
x
\rm{python3.x}
python3.x 版本中已经移动到 functools
库中,调用前需要导入。
chr()
,ord()
,map()
这三者则均为内置函数,可直接调用。
不过在力扣中,大部分常用库已经被自动导入。
这些函数的作用,均可在官方文档中找到相应的解释,如有不理解,不妨翻阅一下。
复杂度分析
- 时间复杂度: O ( N ) O(N) O(N)。
- 空间复杂度: O ( 1 ) O(1) O(1)。
求和
这里借鉴 官方题解 给出的思想。先分别计算字符串 s s s 和字符串 t t t 各个字符对应的 ASCII 码值之和。因为 t t t 比 s s s 只多了一个字母,那么用 t t t 中各个字符的 ASCII 值和减去 s s s 各个字符的 ASCII 值和,最终差值转换为 ASCII 字符即是所求结果。
class Solution:
def findTheDifference(self, s: str, t: str) -> str:
add_s = 0
add_t = 0
# 计算 s 中各个字符的 ASCII 值和
for ch in s:
add_s += ord(ch)
# 计算 t 中各个字符的 ASCII 值和
for ch in t:
add_t += ord(ch)
# 计算差值,转换为 ASCII 字符
return chr(add_t - add_s)
这里同样也可以借助 sum()、chr()、ord()、map()
这些函数,用一行代码来尝试实现。
class Solution:
def findTheDifference(self, s: str, t: str) -> str:
return chr(sum(map(ord, t))- sum(map(ord, s)))
复杂度分析
- 时间复杂度: O ( N ) O(N) O(N)。
- 空间复杂度: O ( 1 ) O(1) O(1)。
欢迎关注
公众号 【书所集录】
如有错误,烦请指出,欢迎指点交流。如果觉得写得还可以,还请点个赞,谢谢。