补充题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
- 题解
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))