热题系列章节21

补充题14. 阿拉伯数字转中文数字

补充题9. 36进制加法

85. 最大矩形

在这里插入图片描述

class Solution:
    def maximalRectangle(self, matrix: List[List[str]]) -> int:
        if not matrix:return 0
        m,n=len(matrix),len(matrix[0])
        # 记录当前位置上方连续“1”的个数
        pre=[0]*(n+1)
        res=0
        for i in range(m):
            for j in range(n):
                # 前缀和
                pre[j]=pre[j]+1 if matrix[i][j]=="1" else 0
 
            # 单调栈
            stack=[-1]
            for k,num in enumerate(pre):
                while stack and pre[stack[-1]]>num:
                    index=stack.pop()
                    res=max(res,pre[index]*(k-stack[-1]-1))
                stack.append(k)
 
        return res

210. 课程表 II

在这里插入图片描述
这是一个典型的拓扑排序题目, 对拓扑排序不熟悉的,可以看下这个文章 - 揭开「拓扑排序」的神秘面纱,可以说讲的非常详细了。
Ok,我们回到这道题。以题目例2来说:

由于题目本身课程的依赖关系是这么给我们的:[[1,0],[2,0],[3,1],[3,2]] 这种数据格式我们不方便直接使用, 因此我们将其改造成图的一种表示方式邻接矩阵。
在这里插入图片描述
可以看到我们浪费了很多空间,这就是邻接矩阵的坏处, 而实际上对于这道题来说,没有必要真的搞一个邻接矩阵,比如这样就行了:
在这里插入图片描述
可以看出空间复杂度要更好一点。
构建矩阵的过程代码:

adjacent = [[] for _ in range(numCourses)]
for cur, pre in prerequisites:
    adjacent[cur].append(pre)

接下来是算法的重点,我们对每一个课程进行一次深度遍历, 并且用visited数组记录每一个课程的访问状态,这样我们可以判断有没有环的存在,如果有环则返回[]。

而对于visited,我们使用三色标记法,即没有访问的,访问过但是没有访问完毕的以及完全访问完毕的标记不同颜色。 在这里我用0表示没有访问过,1表示访问过但是没有访问完毕,2访问完毕。

DFS 核心逻辑:

def dfs(i):
    # 访问过,还没访问完又回来了,说明有环
    if visited[i] == 1:
        return False
    # 已经完全访问完毕,说明行得通
    if visited[i] == 2:
        return True
    # 遍历前标记1
    visited[i] = 1
    for j in adjacent[i]:
        if not dfs(j):
            return False
    # 遍历后标记2
    visited[i] = 2
    # 为2的都可以加入res了
    res.append(i)
    return True

class Solution:
    def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:
        res = []
        visited = [0] * numCourses
        adjacent = [[] for _ in range(numCourses)]

        def dfs(i):
            if visited[i] == 1:
                return False
            if visited[i] == 2:
                return True
            visited[i] = 1
            for j in adjacent[i]:
                if not dfs(j):
                    return False

            visited[i] = 2
            res.append(i)
            return True
        for cur, pre in prerequisites:
            adjacent[cur].append(pre)
        for i in range(numCourses):
            if not dfs(i):
                return []
        return res

444. 切披萨的方案数

56. 下一个更大元素 III

给你一个正整数 n ,请你找出符合条件的最小整数,其由重新排列 n 中存在的每位数字组成,并且其值大于 n 。如果不存在这样的正整数,则返回 -1 。
注意 ,返回的整数应当是一个 32 位整数 ,如果存在满足题意的答案,但不是 32 位整数 ,同样返回 -1 。

示例 1:
输入:n = 12
输出:21

示例 2:
输入:n = 21
输出:-1

提示:
1 <= n <= 231 - 1

  1. 题解
    2.1 解法1: 线性解法
    主要思想:
    1.将数转化为字符串
    2.从右往左找到比左比右小的数字
    3.再从右往左找到比该数字大的数, 然后交换
    4.逆置后面的数

算法举例如下: 247531
1.从右往左找到比左比右小的数字,是4
2.从右往左找到比4的数字5,交换后是 257431 (不是最小整数!)
3.然后翻转 7431 -> 251347

注意点:
1.下标超界
2.最后先转成 long 类型, 再判断数是否超出最大整数
代码与 31. 下一个排列 基本一致, 只不过变成字符串

class Solution {
public:
    int nextGreaterElement(int n) {
        auto nums = to_string(n);
        int i = (int) nums.length() - 2;
        while (i >= 0 && nums[i] >= nums[i + 1]) {
            i--;
        }
        if (i < 0) {
            return -1;
        }

        int j = nums.size() - 1;
        while (j >= 0 && nums[i] >= nums[j]) {
            j--;
        }
        swap(nums[i], nums[j]);
        reverse(nums.begin() + i + 1, nums.end());
        long ans = stol(nums);
        return ans > INT_MAX ? -1 : ans;
    }
};

670. 最大交换

给定一个非负整数,你至多可以交换一次数字中的任意两位。返回你能得到的最大值。

示例 1 :
输入: 2736
输出: 7236
解释: 交换数字2和数字7。

示例 2 :
输入: 9973
输出: 9973
解释: 不需要交换。

class Solution:
    def maximumSwap(self, num: int) -> int:
        num = [int(ch) for ch in str(num)]
        for i in range(len(num)):
            max_idx, mav_val = i, num[i]
            for j in range(i + 1, len(num)):
                if mav_val <= num[j] and num[i] < num[j]:
                    max_idx, mav_val = j, num[j]
            if max_idx != i:
                num[i], num[max_idx] = num[max_idx], num[i]
                break
        return int("".join(str(i) for i in num))

1044. 最长重复子串

给你一个字符串 s ,考虑其所有 重复子串 :即 s 的(连续)子串,在 s 中出现 2 次或更多次。这些出现之间可能存在重叠。
返回 任意一个 可能具有最长长度的重复子串。如果 s 不含重复子串,那么答案为 “” 。

示例 1:
输入:s = “banana”
输出:“ana”

示例 2:
输入:s = “abcd”
输出:“”

在解决Leetcode上的算法问题时,常常会遇到需要寻找最长重复子串的情况。最长重复子串是指在一个字符串中,找到连续出现多次的相同字符序列,且该序列的长度最长。本文将介绍如何使用Python来解决这类问题,并且给出一个实际的Leetcode问题作为示例。

解决方法
在解决最长重复子串的问题时,我们可以采用滑动窗口的方法来进行求解。具体步骤如下:

定义一个滑动窗口,用于记录当前的字符序列。
遍历整个字符串,每次都将当前字符加入滑动窗口。
判断当前字符是否与滑动窗口的最后一个字符相同,如果相同,则继续向后遍历。
如果不同,则更新最长重复子串的长度,并将滑动窗口移动到当前字符处。

def longestRepeatedSubstring(s):
    n = len(s)
    res = 0
    dp = [[0] * n for _ in range(n)]

    for i in range(1, n):
        for j in range(i):
            if s[i] == s[j]:
                dp[i][j] = dp[i-1][j-1] + 1
                res = max(res, dp[i][j])

    return res

# 测试代码
s = "abcdeabcdeabcde"
print(longestRepeatedSubstring(s))

剑指 Offer 33. 二叉搜索树的后序遍历序列

面试题 17.24. 最大子矩阵

10. 分割数组的最大值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值