Python剑指offer打卡-38

Python剑指offer打卡-38

划分字母区间

题目类型:贪心法

题目难度:🌟🌟🌟

  • 问题描述

    问题描述:
        字符串 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一字母
    最多出现在一个片段中。返回一个表示每个字符串片段的长度的列表。
    
    解题方法:
    贪心法
    时间复杂度:O(N)
    空间复杂度:O(1)
    
    原题链接:https://leetcode-cn.com/problems/partition-labels/solution/
    
  • 代码

    class Solution:
        def partitionLabels(self, s: str) -> List[int]:
    
            # 统计每一个字符的最大右边界
            hast_table = [0] * 26
            for i, c in enumerate(s):
                hast_table[ord(c) - ord("a")] = i
            # 划分区间
            # 寻找最优边界
            res = []
            left, right = 0, 0
            for i, c in enumerate(s):
                # 扩充边界
                # 在当前区间内是否含有比当前值所在边界大的索引边界
                right = max(right, hast_table[ord(c) - ord("a")])
                if i == right:
                    res.append(right - left + 1)
                    left = right + 1
    
            return res
    

腐蚀的橘子

题目类型:BFS

题目难度:🌟🌟🌟

  • 问题描述

    问题描述:
    在给定的网格中,每个单元格可以有以下三个值之一:
    值0代表空单元格;
    值1代表新鲜橘子;
    值2代表腐烂的橘子。
    每分钟,任何与腐烂的橘子(在 4 个正方向上)相邻的新鲜橘子都会腐烂。
    返回直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回-1。
    
    解题方法:
    BFS
    时间复杂度:O(mn)
    空间复杂度:O(mn)
    
    原题链接:https://leetcode-cn.com/problems/rotting-oranges/
    
  • 代码

    class Solution:
        def orangesRotting(self, grid) -> int:
    
            m, n = len(grid), len(grid[0])
            # 标记腐烂橘子的位置
            time = 0
            deque = []
            for i in range(m):
                for j in range(n):
                    if grid[i][j] == 2:
                        deque.append((i, j, time))
    
            # 开始腐烂新鲜橘子
            while deque:
                i, j, time = deque.pop(0)
                for di, dj in [(1, 0), (-1, 0), (0, 1), (0, -1)]:
                    if 0 <= i + di < m and 0 <= j + dj < n and grid[i + di][j + dj] == 1:
                        grid[i + di][j + dj] = 2
                        deque.append((i + di, j + dj, time + 1))
            # 无法腐蚀的橘子
            for row in grid:
                if 1 in row: return -1
    
            return time
    

整数拆分

题目类型:数学

题目难度:🌟🌟🌟

  • 问题描述

    问题描述:
        给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的
    乘积最大化。 返回你可以获得的最大乘积。
    
    
    解题方法:
    数学推导
    时间复杂度:O(1)
    空间复杂度:O(1)
    
    原题链接:https://leetcode-cn.com/problems/integer-break/
    
  • 代码

    class Solution:
        def integerBreak(self, n: int) -> int:
    
            if n <= 3: return n - 1
            # 求解整数和余数
            a, b = n//3, n%3
            if b == 0: return 3**(a)
            if b == 1: return 3**(a - 1)*4
            return 3**(a)*2
    

字母异位词分组

题目类型:排序

题目难度:🌟🌟🌟

  • 问题描述

    问题描述:
        给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回
    结果列表。字母异位词 是由重新排列源单词的字母得到的一个新单词,所有源单词
    中的字母通常恰好只用一次。
    
    解题方法:
    方法1:
    排序:由于互为字母异位词的两个字符串包含的字母相同,因此对两个字符串分别进
    行排序之后得到的字符串一定是相同的,故可以将排序之后的字符串作为哈希表的
    键。
    方法2:
    计数:相同字符下的字符编码相同
    时间复杂度:O(nklogk)
    空间复杂度:O(nk)
    
    原题链接:https://leetcode-cn.com/problems/group-anagrams/
    
  • 代码

    class Solution:
        def groupAnagramsofRank(self, strs):
            mp = collections.defaultdict(list)
    
            for str in strs:
                # 属于同一变换下的字符排序结果相同
                key = "".join(sorted(str))
                mp[key].append(str)
    
            return list(mp.values())
    
    
        def groupAnagramsofCount(self, strs):
            mp = collections.defaultdict(list)
    
            for str in strs:
                counts = [0]*26
                for c in str:
                    counts[ord(c) - ord("a")] += 1
    
                mp[tuple(counts)].append(str)
    
            return list(mp.values())
    

数字1的个数

题目类型:数学

题目难度:🌟🌟🌟🌟

  • 问题描述

    问题描述:
        给定一个整数 n,计算所有小于等于 n 的非负整数中数字 1 出现的个数。
    
    解题方法:
    数学推导
    时间复杂度:O(N)
    空间复杂度:O(1)
    
    原题链接:https://leetcode-cn.com/problems/number-of-digit-one/
    
  • 代码

    图解算法

    在这里插入图片描述

    class Solution:
        def countDigitOne(self, n: int) -> int:
    
            dight, res = 1, 0
            cur, low, high = n % 10, 0, n // 10
            while high != 0 or cur != 0:
                if cur == 0:
                    res += high * dight
                elif cur == 1:
                    res += high * dight + 1 + low
                else:
                    res += high * dight + dight
                # 更新位置
                low += cur * dight
                cur = high % 10
                high = high // 10
                dight = dight * 10
    
            return res
    

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值