LeetCode 389. 找不同 | Python

389. 找不同


题目来源:力扣(LeetCode)https://leetcode-cn.com/problems/find-the-difference/

题目


给定两个字符串 st,它们只包含小写字母。

字符串 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
  • st 只包含小写字母

解题思路


思路:计数、位运算、求和

先审题,题目中给定两个字符串 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)

欢迎关注


公众号 【书所集录


如有错误,烦请指出,欢迎指点交流。如果觉得写得还可以,还请点个赞,谢谢。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
你好!对于LeetCode上的问994.腐烂的橘子,你可以使用Python来解决。下面是一个示例代码: ```python from collections import deque def orangesRotting(grid): # 记录网格的行数和列数 row, col = len(grid), len(grid[0]) # 定义四个方向:上、下、左、右 directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] # 使用队列来保存腐烂的橘子的位置 queue = deque() # 记录新鲜橘子的数量 fresh_count = 0 # 遍历整个网格,初始化队列和新鲜橘子的数量 for i in range(row): for j in range(col): if grid[i][j] == 2: # 腐烂的橘子 queue.append((i, j)) elif grid[i][j] == 1: # 新鲜橘子 fresh_count += 1 # 如果新鲜橘子的数量为0,直接返回0 if fresh_count == 0: return 0 # 初始化分钟数 minutes = 0 # 开始进行BFS,直到队列为空 while queue: # 记录当前分钟数下,队列中的元素数量 size = len(queue) # 遍历当前分钟数下的所有腐烂的橘子 for _ in range(size): x, y = queue.popleft() # 遍历四个方向 for dx, dy in directions: nx, ny = x + dx, y + dy # 判断新位置是否在网格内,并且是新鲜橘子 if 0 <= nx < row and 0 <= ny < col and grid[nx][ny] == 1: # 将新鲜橘子变为腐烂状态 grid[nx][ny] = 2 # 将新鲜橘子的位置加入队列 queue.append((nx, ny)) # 新鲜橘子的数量减1 fresh_count -= 1 # 如果当前分钟数下,没有新鲜橘子了,结束循环 if fresh_count == 0: break # 每遍历完一层,分钟数加1 minutes += 1 # 如果最后还有新鲜橘子,返回-1,否则返回分钟数 return -1 if fresh_count > 0 else minutes ``` 你可以将给定的网格作为参数传递给`orangesRotting`函数来测试它。请注意,该代码使用了BFS算法来遍历橘子,并计算腐烂的分钟数。希望能对你有所帮助!如果有任何疑问,请随时问我。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值