一天一道LeetCode(61-90)

文章目录

  • 一天一道LeetCode(61-90)
    • 61.旋转链表
    • 62.不同路径
    • 63.不同路径 II
    • 64.最小路径和
    • 65.有效数字(未解决)
    • 66.加一
    • 67.二进制求和
    • 68.文本左右对齐
    • 69.x 的平方根
    • 70.爬楼梯
    • 71.简化路径
    • 72.编辑距离
    • 73.矩阵置零
    • 74.搜索二维矩阵
    • 75.颜色分类
    • 76.最小覆盖子串
    • 77.组合
    • 78.子集
    • 79.单词搜索
    • 80.删除排序数组中的重复项 II
    • 81.搜索旋转排序数组 II
    • 82.删除排序链表中的重复元素 II
    • 83.删除排序链表中的重复元素
    • 84.柱状图中最大的矩形
    • 85.最大矩形
    • 86.分隔链表
    • 87.扰乱字符串
    • 88.合并两个有序数组
    • 89.格雷编码(未解决)
    • 90.子集 II

61.旋转链表

题目

给定一个链表,旋转链表,将链表每个节点向右移动k个位置,其中k是非负数

实例

输入: 1->2->3->4->5->NULL, k = 2
输出: 4->5->1->2->3->NULL
解释:
向右旋转 1 步: 5->1->2->3->4->NULL
向右旋转 2 步: 4->5->1->2->3->NULL
输入: 0->1->2->NULL, k = 4
输出: 2->0->1->NULL
解释:
向右旋转 1 步: 2->0->1->NULL
向右旋转 2 步: 1->2->0->NULL
向右旋转 3 步: 0->1->2->NULL
向右旋转 4 步: 2->0->1->NULL
class ListNode:def __init__(self, x):self.val = xself.next = None
class Solution:def rotateRight(self, head, k):if not head:return None# 获取链表长度p = headlength = 0while p :length += 1p = p.next# 让k对length取余,避免重复循环导致超时k = k % lengthif k == 0:return headpre, post = head, head# 让一个指针先走k步for i in range(k):post = post.next# 两个指针一起走while post.next:pre = pre.nextpost = post.nexttmp = pre.nextpre.next = Nonepost.next = headreturn tmp

62.不同路径

题目

一个机器人位于一个m x n 网格的左上角(起始点在下图中标记为"start"),机器人每次只能向下或者向右移动一步,机器人试图到达网格的右下角(图中标记为"finish"),总共有多少条不同的路径?

实例

输入: m = 3, n = 2
输出: 3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1. 向右 -> 向右 -> 向下
2. 向右 -> 向下 -> 向右
3. 向下 -> 向右 -> 向右
输入: m = 7, n = 3
输出: 28

思路

动态规划

机器人智能向下或者向右移动一步,对于任意的i, j,机器人只能从左侧或者上方移动过来,特别的对于上边界或左边界,机器人只有一种移动方式,就有如下公式:

d p [ i ] [ j ] = { 1 (i = 0, j = 0) d p [ i ] [ j − 1 ] (i = 0, j  ≠ 0) d p [ i − 1 ] [ j ] (i  ≠ 0, j = 0) d p [ i − 1 ] [ j ] + d p [ i ] [ j − 1 ] (i  ≠ 0, j  ≠ 0 ) dp[i][j] = \begin{cases}1& \text{(i = 0, j = 0)}\\dp[i][j - 1]& \text{(i = 0, j $\neq$ 0)}\\dp[i - 1][j]& \text{(i $\neq$ 0, j = 0)}\\dp[i - 1][j] + dp[i][j - 1]& \text{(i $\neq$ 0, j $\neq 0 $)}\end{cases} dp[i][j]=⎩⎪⎪⎪⎨⎪⎪⎪⎧​1dp[i][j−1]dp[i−1][j]dp[i−1][j]+dp[i][j−1]​(i = 0, j = 0)(i = 0, j ​= 0)(i ​= 0, j = 0)(i ​= 0, j ​=0)​

在该题中还可以简化为:

d p [ i ] [ j ] = { 1 (i = 0 or j = 0) d p [ i − 1 ] [ j ] + d p [ i ] [ j − 1 ] (i  ≠ 0 , j  ≠ 0 ) dp[i][j] = \begin{cases}1& \text{(i = 0 or j = 0)}\\dp[i - 1][j] + dp[i][j - 1]& \text{(i $\not= 0 $, j $\not= 0$)}\end{cases} dp[i][j]={1dp[i−1][j]+dp[i][j−1]​(i = 0 or j = 0)(i ​=0, j ​=0)​

class Solution:def uniquePaths(self, m, n):dp[[1]*n for _ in range(m)]for i in range(1, m):for j in range(1, n):dp[i][j] = dp[i][j - 1] + dp[i - 1][j]return dp[-1][-1]

63.不同路径 II

题目

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。

现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?

网格中的障碍物和空位置分别用1和0来表示

实例

输入:
[[0,0,0],[0,1,0],[0,0,0]
]
输出: 2
解释:
3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:
1. 向右 -> 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右 -> 向右
class Solution:def uniquePathsWithObstacles(self, obstacleGrid):m, n = len(obstacleGrid[0]), len(obstacleGrid)dp = [1] + [0]*mfor i in range(0, n):for j in range(0, m):dp[j] = 0 if obstacleGrid[i][j] else dp[j]+dp[j-1]return dp[-2]

64.最小路径和

题目

给定一个包含非负整数的m x n网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和最小(每次只能向下或者向右移动一步)

实例

输入:
[[1,3,1],[1,5,1],[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小

思路

动态规划

  • 状态定义:设dp为大小m x n矩阵,其中dp[i][j]的值代表走到(i, j)的最小路径和

  • 转移方程:根据题目,只能向右或者向下走,也就是说,当前单元格(i, j)只能从左方单元格(i - 1, j)或上方单元格(i, j - 1)走到,因此只需要考虑矩阵的左边界和上边界

    走到当前单元格(i, j)的最小路径和 = “从左方单元格(i - 1, j)与从上方单元格(i, j - 1)走来的两个最小路径和中较小的 + 当前单元格值grid[i][j],具体分为以下4中情况:

    • 1.当左边和上边都不是矩阵边界时:即当 i ≠ 0 , j ≠ 0 i \not= 0, j \not= 0 i​=0,j​=0时,dp[i][j] = min(dp[i - 1][j], dp[i][j - 1] + grid[i][j])
    • 2.当只有左边是矩阵边界时:只能从上面来,即当 i = 0 , j ≠ 0 i = 0, j \not= 0 i=0,j​=0时,dp[i][j] = dp[i][j - 1] + grid[i][j]
    • 3.当只有上边是矩阵边界时:只能从左边来,即当 i ≠ 0 , j = 0 i \neq 0, j = 0 i​=0,j=0 时,dp[i][j] = dp[i - 1][j] + grid[i][j]
    • 4.当左边和上边都是矩阵边界时:即当 i = 0 , j = 0 i = 0, j = 0 i=0,j=0时,其实就是起点,dp[i][j] = grid[i][i]
  • 初始状态:dp初始化即可,不需要修改初始0值

class Solution:def minPathSum(self, grid):for i in range(len(grid)):for j in range(len(grid[0])):if i == j == 0:continueelif i == 0:grid[i][j] = grid[i][j - 1] + grid[i][j]elif j == 0:grid[i][j] = grid[i - 1][j] + grid[i][j]else:grid[i][j] = min(grid[i - 1][j], grid[i][j - 1]) + grid[i][j]return grid[-1][-1]

65.有效数字(未解决)

题目

验证给定的字符串是否可以解释为十进制数字

实例

"0" => true
" 0.1 " => true
"abc" => false
"1 a" => false
"2e10" => true
" -90e3   " => true
" 1e" => false
"e3" => false
" 6e-1" => true
" 99e2.5 " => false
"53.5e93" => true
" --6 " => false
"-+3" => false
"95a54e53" => false

说明

可能存在于有效十进制数字中的字符表:

  • 数字 0-9
  • 指数 - “e”
  • 正/负号 - “+”/"-"
  • 小数点 - “.”

66.加一

题目

给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一

最高位数字存放在数组的首位,数组中每个元素只存储单个数字

可以假设除了整数0之外,这个整数不会以0开头

实例

输入: [1,2,3]
输出: [1,2,4]
解释: 输入数组表示数字 123
输入: [4,3,2,1]
输出: [4,3,2,2]
解释: 输入数组表示数字 4321
# 投机解法
class Solution:def plusOne(self, digits):cur = ''for ele in digits:cur += str(ele)cur = int(cur) + 1res = [int(i) for i in str(cur)]return res
# 正常解法
class Solution:def plusOne(self, digits):carry = 1for i in range(len(digits)-1, -1, -1):if digits[i] == 9:if carry == 1:digits[i] = 0carry = 1else:digits[i] += carrycarry = 0if carry == 1:digits = [1] + digitsreturn digits

67.二进制求和

题目

给你一个二进制字符串,返回他们的和(用二进制表示)

输入为非空字符串且只包含数字1和0

实例

输入: a = "11", b = "1"
输出: "100"
输入: a = "1010", b = "1011"
输出: "10101"

提示

  • 每个字符串仅由字符 '0''1' 组成。
  • 1 <= a.length, b.length <= 10^4
  • 字符串如果不是 "0" ,就都不含前导零。
class Solution:def addBinary(self, a, b):if len(a) < len(b):a, b = b, an = len(a)# 补齐b不足的位为0b = '0' * (n - len(b)) + bresult = ''summ = 0 # 进位值for i in range(n):a_1 = int(a[-i-1])b_1 = int(b[-i-1])# 当前数位相加余2,连接更小位数的值result = str((a_1 + b_1 + summ) % 2) + result# 当前位数之和整除2,得到下一位运算的进位值summ = (a_1 + b_1 + summ) // 2# 判断最高位是否需要进位if summ == 1:result = '1' + resultreturn result
# 内置方法
class Solution:def addBinary(self, a, b):return bin(int(a, 2) + int(b, 2))[2:]

68.文本左右对齐

题目

给定一个单词数组和一个长度maxWidth,重新排版单词,使其成为每行恰好有maxWidth个字符,且左右两段对齐的文本

应该使用“贪心算法”来放置给定的单词,也就是说,尽可能多的往每行中放置单词,必要时可以使用空格填充,使得每行恰好有maxWidth个字符

要求尽可能均匀分配单词间的空格数量,如果某一行单词间的空格不能均匀分配,则左侧放置的空格数要多于右侧的空格数

文本的最后一行应为左对齐,且单词之间不插入额外的空格

说明

  • 单词是指由非空格字符组成的字符序列。
  • 每个单词的长度大于 0,小于等于 maxWidth
  • 输入单词数组 words 至少包含一个单词。

实例

输入:
words = ["This", "is", "an", "example", "of", "text", "justification."]
maxWidth = 16
输出:
["This    is    an","example  of text","justification.  "
]
输入:
words = ["What","must","be","acknowledgment","shall","be"]
maxWidth = 16
输出:
["What   must   be","acknowledgment  ","shall be        "
]
解释: 注意最后一行的格式应为 "shall be    " 而不是 "shall     be",因为最后一行应为左对齐,而不是左右两端对齐。       第二行同样为左对齐,这是因为这行只包含一个单词
输入:
words = ["Science","is","what","we","understand","well","enough","to","explain","to","a","computer.","Art","is","everything","else","we","do"]
maxWidth = 20
输出:
["Science  is  what we","understand      well","enough to explain to","a  computer.  Art is","everything  else  we","do                  "
]

思路

设定一下几个变量:

ans 最后答案 / cur_c 当前行的字母数 / cur_w 当前行的单词数 / wl 当前行的单词列表

然后一个单词一个单词的过,判断加上这个单词是否会超过最大长度,一行的最低长度是:

cur_c + cur_w - 1

如果大于maxWidth,就把这一行加入ans中,所有单词过完了再把余下的词放入最后一行

如何安排每一行的单词:

1.如果这一行只有一个单词,单词左对齐,后面补满空格

2.一行多个单词

​ 空格正好可以平均分配,求出平均每个间隔几个空格,直接调用python的join方法

​ 有多余的空格,题目要求左边空格多于右边,先算平均每个间隔几个空格,然后余下几个,如果平均b个,余下x个,则前x个间隔空b + 1个,后面的都空b个

class Solution:def fullJustify(self, words, maxWidth):ans = []   # 最后的答案cur_c = 0  # 当前行的字母数cur_w = 0  # 当前行的单词数wl = []    # 当前行的单词列表for i, wd in enumerate(words):l = len(wd)if cur_c + l + cur_w > maxWidth: # 加上这个单词是否会超过最大长度if cur_w == 1: # 当前行仅有一个超长的单词,后面全部补空格ans.append(wl[0] + ' ' * (maxWidth-cur_c))else:left = maxWidth - cur_c # 这行一共有几个空格if left % (cur_w-1) == 0: # 空格刚好平均分配ans.append((' '*(left//(cur_w-1))).join(wl))else: # 空格不能平均分配x = left % (cur_w-1)  # 多余的空格b = left // (cur_w-1) # 平均每个间隔最少的空格数cans = wl[0]for i in range(x): # 前 x 个间隔空 b + 1 个cans += ' ' * (b+1) + wl[i+1]for i in range(x+1, len(wl)): # 后面的都空 b 个cans += ' ' * b + wl[i]ans.append(cans)cur_c = lcur_w = 1wl = [wd]else:cur_c += lcur_w += 1wl.append(wd)if cur_w > 0: # 所有单词过完了把余下的词放入最后一行cans = ' '.join(wl)cans += ' ' * (maxWidth - len(cans))ans.append(cans)return ans

69.x 的平方根

题目

实现int sqrt(int x)函数,计算并返回x的平方根,其中x 是非负整数

由于返回类型是整数,结果只保留整数的部分,小数部分被舍去

实例

输入: 4
输出: 2
输入: 8
输出: 2
说明: 8 的平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去

思路

牛顿迭代

y = f ( x ) = x 2 − C y = f(x) = x^2 - C y=f(x)=x2−C,其中C表示待求出平方根的那个整数,C的平方就是函数的零点

牛顿迭代的本质是借助泰勒级数,从初始值开始快速向零点逼近

任取一个 x 0 x_0 x0​作为初始值,在每一步的迭代中,我们找到函数图像上的点 ( x i , f ( x i ) ) (x_i, f(x_i)) (xi​,f(xi​)),过该点做一条斜率为该点倒数 f ′ ( x i ) f'(x_i) f′(xi​)的直线,与横轴的交点记为 x i + 1 x_{i+1} xi+1​, x i + 1 x_{i+1} xi+1​相较于 x i x_i xi​而言距离零点更接近,在经过多次迭代后,可以得到一个距离零点非常接近的交点,下图是两次迭代得到 x 1 和 x 2 x_1和x_2 x1​和x2​的过程

选取 x 0 = C x_0 = C x0​=C作为初始值

在每一步迭代中,通过当前的交点 x i x_i xi​,找到函数图像上的点 ( x i , x i 2 − C ) (x_i, x_i^2-C) (xi​,xi2​−C),做一条斜率为 f ′ ( x i ) = 2 x i f'(x_i) = 2x_i f′(xi​)=2xi​的直线,直线方程为:

y l = 2 x i ( x − x i ) + x i 2 − C = 2 x i x − ( x i 2 + C ) yl = 2x_i(x - x_i) + x_i^2 - C = 2x_ix - (x_i^2 + C) yl=2xi​(x−xi​)+xi2​−C=2xi​x−(xi2​+C)

与横轴的交点为方程 2 x i x − ( x i 2 + C ) = 0 2x_ix - (x_i^2 +C) = 0 2xi​x−(xi2​+C)=0的解,即为更新的迭代结果 x i + 1 x_{i+1} xi+1​, x i + 1 = 1 2 ( x i + C x i ) x_{i+1} = \frac{1}{2}(x_i+\frac{C}{x_i}) xi+1​=21​(xi​+xi​C​)

在进行k次迭代后, x k x_k xk​的值与真实的零点 C \sqrt{C} C ​足够接近,即可作为答案

class Solution:def mySqrt(self, x):if x == 0:return 0C, x0 = float(x), float(x)while True:xi = 0.5 * (x0 + C / x0)if abs(x0 - xi) < 1e-7:breakx0 = xireturn int(x0)

方法二

二分查找

由于x的平方根的整数部分ans是满足 k 2 < = x k^2 <= x k2<=x的最大k值,可以对k进行二分查找

二分查找的下界为0,上界可以设定为x,在二分查找的每一步中,我们只需要比较中间元素mid的平方与x的大小关系,并通过比较的结果调整上下界的范围

class Solution:def mySqrt(self, x):l, r, ans = 0, x, -1while l <= r:mid = (l + r) // 2if mid * mid <= x:ans = midl = mid + 1else:r = mid - 1return ans

70.爬楼梯

题目

假设你正在爬楼梯,需要n阶才能到达楼顶

每次你可以爬1或2个台阶,有多少种不同的方法可以爬到楼顶?

实例

输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1.  1 阶 + 1 阶
2.  2 阶
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1.  1 阶 + 1 阶 + 1 阶
2.  1 阶 + 2 阶
3.  2 阶 + 1 阶

思路

其实就是斐波那契数列

class Solution:def climbStairs(self, n):count = 0tmp1 = 0tmp2 = 1ans = 0while count < n :ans = tmp1 + tmp2tmp1 = tmp2tmp2 = anscount += 1return ans

71.简化路径

题目

以Unix风格给出一个文件的绝对路径,你需要简化它,将其转换为规范路径

在Unix风格的文件系统中,一个点.,表示当前目录本身,此外,两个点..,表示将目录切换到上一级(指向父目录),两者都可以是复杂相对路径的组成部分

请注意,返回的规范路径必须始终以斜杠/开头,并且,两个目录名之间必须只有一个斜杠/,最后一个目录名(如果存在),不能以/结尾,此外,规范路径必须是表示绝对路径的最短字符串

实例

输入:"/home/"
输出:"/home"
解释:注意,最后一个目录名后面没有斜杠
输入:"/../"
输出:"/"
解释:从根目录向上一级是不可行的,因为根是你可以到达的最高级
输入:"/home//foo/"
输出:"/home/foo"
解释:在规范路径中,多个连续斜杠需要用一个斜杠替换
输入:"/a/./b/../../c/"
输出:"/c"
输入:"/a/../../b/../c//.//"
输出:"/c"
输入:"/a//bc/d//././/.."
输出:"/a/b/c"

思路

把当前目录压入栈中,遇到..,弹出栈顶,最后返回栈中元素

class Solution:def simplifyPath(self, path):stack = []path = path.split('/')for item in path:if item == '..':if stack:stack.pop()elif item and item != '.':stack.append(item)return '/' + '/'.join(stack)

72.编辑距离

题目

给你两个单词word1和word2,请你计算出将word1转换成word2所用的最少操作数

可以对一个单词进行如下三种操作:

1.插入一个字符

2.删除一个字符

3.替换一个字符

实例

输入:word1 = "horse", word2 = "ros"
输出:3
解释:
horse -> rorse (将 'h' 替换为 'r')
rorse -> rose (删除 'r')
rose -> ros (删除 'e')
输入:word1 = "intention", word2 = "execution"
输出:5
解释:
intention -> inention (删除 't')
inention -> enention (将 'i' 替换为 'e')
enention -> exention (将 'n' 替换为 'x')
exention -> exection (将 'n' 替换为 'c')
exection -> execution (插入 'u')

思路

动态规划

dp[i][j]代表word1 到i位置转换成word2到j位置需要最少步数

所以,当word1[i] == word2[j], dp[i][j] = dp[i - 1][j - 1]

word1[i] != word2[j], dp[i][j] = min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1] + 1),其中dp[i - 1][j - 1]表示替换操作,dp[i - 1][j]表示删除操作,dp[i][j - 1]表示插入操作

补充:

以 word1 为 “horse”,word2 为 “ros”,且 dp[5][3] 为例,即要将 word1的前 5 个字符转换为 word2的前 3 个字符,也就是将 horse 转换为 ros,因此有:

(1) dp[i-1][j-1],即先将 word1 的前 4 个字符 hors 转换为 word2 的前 2 个字符 ro,然后将第五个字符 word1[4](因为下标基数以 0 开始) 由 e 替换为 s(即替换为 word2 的第三个字符,word2[2])

(2) dp[i][j-1],即先将 word1 的前 5 个字符 horse 转换为 word2 的前 2 个字符 ro,然后在末尾补充一个 s,即插入操作

(3) dp[i-1][j],即先将 word1 的前 4 个字符 hors 转换为 word2 的前 3 个字符 ros,然后删除 word1 的第 5 个字符

注意,针对第一行,第一列要单独考虑,引入'',如下图所示:

第一行,是word1为空变成word2最少步数,就是插入步数

第一列,是word2为空,需要的最少步数,就是删除操作

# 自底向上
class Solution:def minDistance(self, word1, word2):n1 = len(word1)n2 = len(word2)dp = [[0] * (n2 + 1) for _ in range(n1 + 1)]for j in range(1, n2 + 1):dp[0][j] = dp[0][j - 1] + 1for i in range(1, n1 + 1):dp[i][0] = dp[i - 1][0] + 1for i in range(1, n1 + 1):for j in range(1, n2 + 1):if word1[i - 1] == word2[j - 1]:dp[i][j] = dp[i - 1][j - 1]else:dp[i][j] = min(dp[i][j - 1], dp[i - 1][j], dp[i - 1][j - 1]) + 1return dp[-1][-1]

73.矩阵置零

题目

给定一个m x n 的矩阵,如果一个元素为0,则将其所在行和列的所有元素都设为0,请使用原地算法

实例

输入:
[[1,1,1],[1,0,1],[1,1,1]
]
输出:
[[1,0,1],[0,0,0],[1,0,1]
]
输入:
[[0,1,2,0],[3,4,5,2],[1,3,1,5]
]
输出:
[[0,0,0,0],[0,4,5,0],[0,3,1,0]
]

思路

1.用 O ( m + n ) O(m + n) O(m+n)额外空间

扫两遍matrix,第一遍用集合记录哪些行,哪些列有0,第二遍置0

class Solution:def setZeroes(self, matrix):row = len(matrix)col = len(matrix[0])row_zero = set()col_zero = set()for i in range(row):for i in range(col):if matrix[i][j] == 0:row_zero.add(i)col_zero.add(j)for i in range(row):for j in range(col):if i in row_zero or j in col_zero:matrix[i][j] = 0

2.用 O ( 1 ) O(1) O(1)空间

用matrix第一行和第一列记录该行该列是否有0作为标志位,但是对于第一行和第一列要设置一个标志位,为了防止自己这一行(一列)也有0的情况

class Solution:def setZeroes(self, matrix):row = len(matrix)col = len(matrix[0])row0_flag = Falsecol0_flag = False# 找第一行是否有0for j in range(col):if matrix[0][j] == 0:row0_flag = Truebreak# 第一列是否有0for i in range(row):if matrix[i][0] == 0:col0_flag = Truebreak# 把第一行或者第一列作为 标志位for i in range(1, row):for j in range(1, col):if matrix[i][j] == 0:matrix[i][0] = matrix[0][j] = 0# 置0for i in range(1, row):for j in range(1, col):if matrix[i][0] == 0 or matrix[0][j] == 0:matrix[i][j] = 0if row0_flag:for j in range(col):matrix[0][j] = 0if col0_flag:for i in range(row):matrix[i][0] = 0

74.搜索二维矩阵

题目

编写一个高效的算法来判断m x n 矩阵中,是否存在一个目标值,该矩阵有如下特性:

  • 每行中的整数从左到右按升序排列
  • 每行的第一个整数大于前一行的最后一个整数

实例

输入:
matrix = [[1,   3,  5,  7],[10, 11, 16, 20],[23, 30, 34, 50]
]
target = 3
输出: true
输入:
matrix = [[1,   3,  5,  7],[10, 11, 16, 20],[23, 30, 34, 50]
]
target = 13
输出: false
# 法一(推荐):从左下角开始查找,如果比当前值大,则去上一行找,如果比当前值小,则向后找
class Solution:def searchMatrix(self, matrix, target):row = len(matrix) - 1col = len(matrix[0]) - 1i = rowj = 0while j <= col and i >= 0 :if target < matrix[i][j]:i -= 1elif target > array[i][j]:j += 1else:return Truereturn False
# 法二:转换成一维数组,然后使用二分查找
class Solution:def searchMatrix(self, matrix, target):if not matrix or not matrix[0]:return Falseleft, right = 0, len(matrix) * len(matrix[0]) - 1array = [column for row in matrix for column in row]while left <= right:mid = ((right - left) >> 1) + leftif array[mid] == target:return Trueelif array[mid] < target:left = mid + 1else:right = mid - 1return False

75.颜色分类

题目

给定一个包含红色,白色和蓝色,一共n个元素的数组,原地对他们进行排序,使得相同颜色的元素相邻,比男找红色,白色,蓝色的顺序排序

使用0, 1, 2分别表示红色,白色,蓝色

实例

输入: [2,0,2,1,1,0]
输出: [0,0,1,1,2,2]

思路
三指针

1.定义0的右界bound_0 = 0, 2的左界bound_2 = n - 1,n为数组长度,cur为当前元素

2.当cur <= bound_2时,进入循环

​ 若nums[cur] == 0,此时和0的右界bound_0进行交换,并更新右界和cur,即bound_0 += 1,cur += 1

​ 若nums[cur] == 2,和2的左界bound_2进行交换,并更新左界,向左移动,即bound_2 -= 1

​ 若nums[cur] == 1,则将cur指向下一元素

class Solution:def sortColors(self, nums):n = len(nums)bound_0 = 0bound_2 = n - 1cur = 0while cur <= bound_2:if nums[cur] == 0:nums[cur], nums[bound_0] = nums[bound_0], nums[cur]bound_0 += 1cur += 1elif nums[cur] == 2:nums[cur], nums[bound_2] = nums[bound_2], nums[cur]dound_2 -= 1else:cur += 1

补充

三色旗问题

假设有一条绳子,上面有红,白,蓝三种颜色的棋子,起初绳子上的棋子颜色并没有顺序,希望将之分类,并排序为蓝,白,红的顺序,要如何移动次数才会最少,(只能在绳子上进行移动,并且一次只能调换两色旗子)

方法一:直接交换蓝旗和红旗的位置,剩下的就是白旗位置

方法二:从绳子开头进行,那么遇到蓝色往前移,遇到白色留在中间,遇到红色后移

'''1.如果w所在的位置为白色,则w+1,表示未处理的部分移至白色群组;2.如果w部分为蓝色,则b与w的元素对调,而b与w必须各+1,表示两个群组都多了一个元素当w指向的是蓝色而要和b的指向交换时,如果b指向的不是蓝色,则交换,否则,如果b指向     的是蓝色,则也没有必要把两个蓝色的旗子交换,这时只需要把b和w都往后移一位3.如果w所在的位置是红色,则将w与r交换,但r要减1,表示未处理的部分减1当w指向的是红色而和r交换时,如果此时r指向的是红色,显然没有必要把两个红色旗子交       换,所以这时应该把r前移,知道r指向的不是红色的时候才和w指向的旗子交换
'''
# 定义三个标识,wFlag和bFlag初始状态为0,表示在开头,rFlag初始为len(color)-1表示在末尾
color = ['R','B','R','W','R','R','W','B','B','W']
wFlag, bFlag, rFlag = 0, 0, len(color) - 1# 当红旗索引小于白旗索引,表示剩下的旗子都是红色,程序结束
while wFlag <= rFlag:if color[wFlag] == 'W':wFlag += 1elif color[wFlag] == 'B':color[bFlag], color[wFlag] = color[wFlag], color[bFlag]bFlag += 1wFlag += 1else:while wFlag < rFlag and color[rFlag] == 'R':rFlag -= 1color[rFlag], clolr[wFlag] = color[wFlag], color[rFlag]rFlag -= 1

76.最小覆盖子串

题目

给你一个字符串S,一个字符串T,请在字符串S里面找出:包含T所有字符的最小子串

实例

输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"

说明

如果S中不存在这样的子串,返回''

如果S中存在这样的子串,保证他是唯一答案

思路

滑动窗口

用i, j表示滑动窗口的左边界和右边界,通过改变i, j来扩展和收缩滑动窗口,可以想象成一个窗口在字符串上游走,当这个窗口包含的元素满足条件,即包含字符串T的所有元素,记录下这个滑动窗口的长度j - i + 1,这些长度中最小的值就是要求的结果

  • 步骤1:

    不断增加j,使滑动窗口增大,知道窗口包含了T的所有元素

  • 步骤2:

    不断增加i,使滑动窗口缩小,因为是要求最小字串,所以将不必要的元素排除在外,使长度缩小,直到碰到一个必须包含的元素

  • 步骤3:

    让i增加一个位置,这个时候原本的窗口不满足条件,继续执行步骤1,寻找新的满足条件的窗口,如此反复,知道j超出了字符串S的范围

class Solution:def minWindow(self, s, t):need = collections.defaultdict(int)for c in t:need[c] += 1needCnt = len(t)i = 0res = (0, float('inf'))for j, c in enumerate(s):if need[c] > 0:needCnt -= 1need[c] -= 1# 步骤1,滑动窗口包含了所有T元素if needCnt == 0:# 步骤2增加i,排除多余元素while True:c = s[i]if need[c] == 0:breakneed[c] += 1i += 1if j - i < res[1] - res[0]:res = (i, j)# 步骤3,i增加一个位置,寻找新的满足条件滑动窗口need[s[i]] += 1needCnt += 1i += 1return '' if res[1] > len(s) else s[res[0] : res[1]+1]

77.组合

题目

给定两个整数n和k,返回1…n中所有可能的k个数的组合

实例

输入: n = 4, k = 2
输出:
[[2,4],[3,4],[2,3],[1,2],[1,3],[1,4],
]

绿色的部分是不能产生结果的分枝

class Solution:def combine(self, n, k):if n <= 0 or k <= 0 or k > n :return []res = []self.__dfs(1, k, n, [], res)return resdef __dfs(self, start, k, n, pre, res):if len(pre) == k:res.append(pre[:])return for i in range(start, n-(k-len(pre))+2):pre.append(i)self.__dfs(i+1, k, n, pre, res)pre.pop()

78.子集

题目

给定一组不含重复元素的整数数组nums,返回该数组所有可能的子集(幂集)

说明

解集不能包含重复的子集

实例

输入: nums = [1,2,3]
输出:
[[3],[1],[2],[1,2,3],[1,3],[2,3],[1,2],[]
]
# 方法1:递归
class Solution:def subsets(self, nums):res = []n = len(nums)def helper(i, tmp):res.append(tmp)for j in range(i, n):helper(j + 1, tmp + [nums[j]])helper(0, [])return res
# 方法2:内置函数
# product 笛卡尔积(有放回抽样排列)
# permutations 排列(不放回抽样排列)
# combinations 组合,没有重复(不放回抽样组合)
# combinations_with_replacement 组合,有重复(有放回抽样组合)
class Solution:def subsets(self, nums):res = [[],]for i in range(1, len(nums) + 1):for tup in itertools.combinations(nums, i):res.append(list(tup))return res

79.单词搜索

题目

给定一个二维网格和一个单词,找出该单词是否存在于网格中

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是哪些水平相邻或垂直相邻的单元格,同一个单元格内的字母不允许被重复使用

实例

board =
[['A','B','C','E'],['S','F','C','S'],['A','D','E','E']
]给定 word = "ABCCED", 返回 true
给定 word = "SEE", 返回 true
给定 word = "ABCB", 返回 false
class Solution:def exist(self, board, word):if not board:return Falsefor i in range(len(board)):for j in range(len(board[0])):if self.dfs(board, i, j, word):return Truereturn Falsedef dfs(self, board, i, j, word):if len(word) == 0:return Trueif i < 0 or i >= len(board) or j < 0 or j >= len(board[0]) or word[0] != board[i][j]:return Falsetmp = board[i][j]board[i][j] = '0'res = self.dfs(board, i+1, j, word[1:]) or self.dfs(board, i-1, j, word[1:]) or self.dfs(board, i, j+1, word[1:]) or self.dfs(board, i, j-1, word[1:])board[i][j] = tmpreturn res

80.删除排序数组中的重复项 II

题目

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度

不要使用额外的数组空间,你必须在原地修改输入数组,并在使用O(1)额外空间的条件下完成

实例

给定 nums = [1,1,1,2,2,3],函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3 。你不需要考虑数组中超出新长度后面的元素
给定 nums = [0,0,1,1,1,1,2,3,3],函数应返回新长度 length = 7, 并且原数组的前五个元素被修改为 0, 0, 1, 1, 2, 3, 3 。你不需要考虑数组中超出新长度后面的元素
class Solution:def removeDuplicates(self, nums):if not nums:return Nonei = 0# 添加一个标识为flag,如果flag = True则跳过,如果flag = False则移动flag = Falsefor j in range(1, len(nums)):if nums[j] != nums[i]:i += 1nums[i] = nums[j]flag = Falseelse:if not flag:i += 1nums[i] = nums[j]flag = Truereturn i+1

81.搜索旋转排序数组 II

题目

假设按照升序排序的数组在预先位置的某个点上进行了旋转

例如(数组[0, 0, 1, 2, 2, 5, 6]可能变为[2, 5, 6, 0, 0, 1, 2]

编写一个函数来判断给定的目标值是否存在于数组中,若存在,返回true,否则返回false

实例

输入: nums = [2,5,6,0,0,1,2], target = 0
输出: true
输入: nums = [2,5,6,0,0,1,2], target = 3
输出: false

思路

二分法

1.初始化 l = 0 和右指针r = n - 1

2.循环条件 l <= r

  • mid = (l + r) // 2,若nums[mid] == target,返回true
  • 若nums[mid] == nums[l] == nums[r],将左右指针同时向里移一位,l += 1, r -= 1
  • 若nums[mid] >= nums[l] 说明此时mid在左子列中:
    • 若此时nums[l] <= target < nums[mid],说明target在左子列中,则此时令r = mid - 1,否则令l = mid + 1
  • 否则,说明mid在右子列中:
    • 若nums[mid] < target <= nums[r]说明target在右子列中,则此时令l = mid + 1,否则令r = mid - 1

3.返回False

class solution:def search(self, nums, target):l = 0r = len(nums) - 1while l<=r:mid = (l+r) // 2if nums[mid] == target:return True# l和mid重复,l加一if nums[mid] == nums[l]:  l += 1# mid和r重复,r减一elif nums[mid] == nums[r]: r -= 1# l到mid是有序的,判断target是否在其中elif nums[mid] > nums[l]: # target在其中,选择l到mid这段if nums[l] <= target < nums[mid]:  r = mid - 1# target不在其中,扔掉l到mid这段else:  l = mid + 1# mid到r是有序的,判断target是否在其中elif nums[mid] < nums[r]:  if nums[mid] < target <= nums[r]:l = mid + 1else:r = mid - 1 return False

82.删除排序链表中的重复元素 II

题目

给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中没有出现的数字

实例

输入: 1->2->3->3->4->4->5
输出: 1->2->5
输入: 1->1->1->2->3
输出: 2->3

思路

快慢指针,用快指针跳过哪些有重复的数字,慢指针负责和快指针拼接

class Solution:def deletteDuplicates(self, head):if head == None or head.next == None:return headdummy = ListNode(-1)dummy.next = headslow = dummyfast = dummy.nextwhile fast:if fast.next and fast.next.val == fast.val:tmp = fast.val# 移动快指针的标准:跳过重复数字while fast and tmp == fast.val:fast = fast.nextelse:slow.next = fastslow = fastfast = fast.nextslow.next = fastreturn dummy.next

83.删除排序链表中的重复元素

题目

给定一个排序链表,删除所有重复元素,使得每个元素出现一次

实例

输入: 1->1->2
输出: 1->2
输入: 1->1->2->3->3
输出: 1->2->3
class Solution:def deleteDuplicates(self, head):if head == None or head.next == None:return headdummy_head = ListNode(None)dummy_head.next = headpre = dummy_headcur = headwhile cur:# 在pre存在的情况下,如果当前值和上一个值相等,就跳过当前值,将上一个值的指针直接指向当前值得下一个if pre and cur.val == pre.val:pre.next = cur.next# 将当前值的next指针置为空cur.next = None# 依然保证当前值在pre的下一个位置cur = pre.nextcontinuepre = curcur = cur.nextreturn dummy_head.next
# 递归解法:
'''递归函数返回的不重复子链的头结点,在回溯过程中,比较当前节点和子链头结点的val是否相同,若相同则保留当前节点(删除子链头结点)
'''
class Solution:def deleteDuplicates(self, head):if head is None or head.next is None:return headchild = self.deleteDuplicates(head.next)if child and head.val == child.val:head.next = child.nextchild.next = Nonereturn head

84.柱状图中最大的矩形

题目

给定n个非负整数,用来表示柱状图中各个柱子的高度,每个柱子彼此相邻,宽为1,求在该柱状图中,能够勾勒出来的矩形的最大面积

实例

输入: [2,1,5,6,2,3]
输出: 10

思路

要想找以第i根柱子为最矮柱子所能延伸的最大面积,是以i为中心,向左找第一个小于heights[i]的位置left_i;向右找第一个小于heights[i]的位置right_i,即最大面积为heights[i] * (right_i - left_i - 1)

当找i左边第一个小于heights[i]如果heights[i-1] >= heights[i]其实就是和heights[i-1]左边第一个小于heights[i-1]一样

单调栈:

从左到右遍历柱子,对于每一个柱子,我们想找到第一个高度小于它的柱子,那么我们就可以使用一个单调递增栈来实现,如果柱子大于栈顶的柱子,那么说明不是我们要找的柱子,就入栈,继续遍历,如果比栈顶小,那么我们就找到了第一个小于栈顶的柱子

对于栈顶元素,其右边第一个小于它的就是当前遍历到的柱子,左边第一个小于它的就是栈中下一个要被弹出的元素,因此以当前栈顶为最小柱子的面积为当前栈顶的柱子高度 * (当前遍历到的柱子索引 - 1 - 栈中下一个要被弹出的元素索引 - 1 + 1)

class Solution:def largestRectangleArea(self, heights):stack = []# 防止空栈的情况heights = [0] + heights + [0]res = 0for i in range(len(heights)):# 构建单调栈while stack and heights[stack[-1]] > heights[i]:tmp = stack.pop()res = max(res, (i - stack[-1] - 1) * heights[tmp])stack.append(i)return res

补充

单调栈

设栈顶元素为b,栈顶第二个元素为a,自然有a < b(因为堆栈越往上越大)

这时候,若c出现,且c小于b,那么b的左右第一个比b小的两个元素就找到了,分别是a和c,b在中间最大

这时可以处理b,并重新整理堆栈,使其保持递增

若c大于b,那c入栈,继续循环,最后清理栈

# 单调栈的结构
for i in list:while i is not empyt and stack[-1] > i : # 先调整位置stack.pop()# 当前元素一定会入栈,不同的只是需不需要pop来调整位置stack.append(i)

问题在于:以B点位高的矩形的最大宽度为从a到c,其中a, c分别为B左边和右边第一个小于B的元素

单调栈的特点在于:

当遇见大数的时候,压入堆栈,等待之后处理

当遇见小数c的时候,意味着大数b的右边界c已经确定了,这时候开始pop,而以被pop出来的值(b)为高度的矩形的左右边界需要被确定

其右边界就是当前的小数,即c,左边界是堆栈的下一层元素,因为下一层的元素一定比当前小,且是第一小的元素,这时a确定

则以被pop出来的数为高度的矩形是(c - a - 1)* pop(),这里pop() == b

这里需要注意的是:

1.栈底要垫上 -1,表示栈底

2.循环结束,要清理堆栈,此时所有栈中继续存放的元素的右边界c都是结尾len(height) - 1

85.最大矩形

题目

给定一个仅包含0和1的二维二进制矩阵,找出只包含1的最大矩形,并返回其面积

实例

输入:
[["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]
]
输出: 6

思路

可以转换为上一题的思路:栈

只需要遍历每行的高度,用上一题的方法求出最大矩形

class Solution:def maximalRectangle(self, matrix):if not matrix or not matrix[0]:return 0row = len(matrix)col = len(matrix[0])heights = [0] * (col + 2)res = 0for i in range(row):stack = []for j in range(col):if matrix[i][j] == '1':heights[j+1] += 1else:heights[j+1] = 0for j in range(col + 2):while stack and heights[stack[-1]] > heights[j]:temp = stack.pop()res = max(res, (j - stack[-1] - 1) * heights[temp])stack.append(j)return res

86.分隔链表

题目

给定一个链表和一个特定值x,对链表进行分隔,使得所有小于x的节点都在大于或等于x的节点之前,应当保留两个分区中每个节点的初始相对位置

实例

输入: head = 1->4->3->2->5->2, x = 3
输出: 1->2->2->4->3->5
class Solution:def partition(self, head, x):# before, after是用来创建两个链表的两个指针before = before_head = ListNode(0)# before_head, after_head用于保存两个链表的头部after = after_head = ListNode(0)while head:# 如果原始链表节点小于给定的x,将它分配给before链表if head.val < x:before.next = headbefore = before.nextelse: # 如果原始链表节点大于或等于给定的x,将它分配给after链表after.next = headafter = after.nexthead = head.next# after链表的最后一个节点也是经过修改的链表的结束节点after.next = None# 一旦所有的节点都被正确分配到两个链表中,将它们组合返回before.next = after_head.nextreturn before_head.next

87.扰乱字符串

题目

给定一个字符串s1,我们可以把它递归的分割成两个非空子字符串,从而将其表示为二叉树

 great/    \gr    eat/ \    /  \
g   r  e   at/ \a   t

上图是s1 = great的一种可能的表示形式

在扰乱这个字符串的过程中,我们可以挑选任何一个非叶结点,然后交换它的两个子节点

例如,挑选非叶结点gr,交换它的两个子节点,将会产生扰乱字符串rgeat

 rgeat/    \rg    eat/ \    /  \
r   g  e   at/ \a   t

rgeat称作great的一个扰乱字符串

同样,如果继续交换节点eatat的子节点,将会产生另一个新的扰乱字符串rgtae

 rgtae/    \rg    tae/ \    /  \
r   g  ta  e/ \t   a

rgtae称作great的一个扰乱字符串

给出两个长度相等的字符串s1和s2,判断s2是否是s1的扰乱字符串

实例

输入: s1 = "great", s2 = "rgeat"
输出: true
输入: s1 = "abcde", s2 = "caebd"
输出: false

思路

递归

S和T如果是扰动的话,那么必然存在一个再S上的长度l1,将S分成S1和S2两段,同样T上也有一个长度l2,把T分为T1和T2

1.如果S1和T1是扰动的,且S2和T2是扰动的,即字符串未交换

2.如果S1和T2是扰动的,且S2和T1是扰动的,即字符串交换了

例如:rgeat和great,rgeat可分成rg和eat两段,great可分成gr和eat两段,rg和gr是扰动的,eat和eat也是扰动的

class Solution:def isScramble(self, s1, s2):if len(s1) != len(s2):  return Falseif s1 == s2:  return Trueif sorted(s1) != sorted(s2):  return Falsefor i in range(1, len(s1)):S1, S2 = s1[:i], s1[i:]T1, T2 = s2[:i], s2[i:]if self.isScramble(S1, T1) and self.isScramble(S2, T2):  return TrueT1, T2 = s2[:-i],s2[-i:]  # S1、S2不变,更新T1、T2if self.isScramble(S1, T2) and self.isScramble(S2, T1):  return Truereturn False

88.合并两个有序数组

题目

给你两个有序整数数组,nums1和nums2,请你将nums2合并到nums1中,使nums1称为一个有序数组

说明

  • 初始化nums1和nums2的元素量分别为m和n
  • 可以假设nums1有足够的空间来保存nums2的元素

实例

输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6],       n = 3输出: [1,2,2,3,5,6]
class Solution:def merge(self, nums1,m, nums2, n):end = m + n - 1end_1 = m - 1end_2 = n - 1while end_1 >= 0 and end_2 >= 0:if nums1[end_1] >= nums2[end_2]:nums1[end] = nums1[end_1]end_1 -= 1end -= 1else:nums1[end] = nums2[end_2]end_2 -= 1end -= 1nums1[:end_2+1] = nums2[:end_2+1]

89.格雷编码(未解决)

题目

格雷编码是一个二进制数字系统,在该系统中,两个连续的数值仅有一个位数的差异

给定一个代表编码总位数的非负整数n,打印其格雷编码序列,即使有多个不同答案,你也只需要返回其中的一种

格雷编码序列必须以0开头

实例

输入: 2
输出: [0,1,3,2]
解释:
00 - 0
01 - 1
11 - 3
10 - 2对于给定的 n,其格雷编码序列并不唯一。
例如,[0,2,3,1] 也是一个有效的格雷编码序列。00 - 0
10 - 2
11 - 3
01 - 1
输入: 0
输出: [0]
解释: 我们定义格雷编码序列必须以 0 开头。给定编码总位数为 n 的格雷编码序列,其长度为 2n。当 n = 0 时,长度为 20 = 1。因此,当 n = 0 时,其格雷编码序列为 [0]。

90.子集 II

题目

给定一个可能包含重复元素的整数数组nums,返回该数组所有可能的子集(幂集)

说明

解集不能包含重复的子集

实例

输入: [1,2,2]
输出:
[[2],[1],[1,2,2],[2,2],[1,2],[]
]
# 递归
class Solution:def subsetsWithDup(self, nums):res = []n = len(nums)nums.sort()def helper(idx, tmp):res.append(tmp)for i in range(idx, n):if i > idx and nums[i] == nums[i-1]:continuehelper(i+1, tmp+[nums[i]])helper(0, [])return res# 迭代
class Solution:def subsetsWithDup(self, nums):if not nums:return []nums.sort()res = [[]]cur = []for i in range(len(nums)):if i > 0 and nums[i-1] == nums[i]:cur = [tmp + [nums[i]] for tmp in cur]else:cur = [tmp + [nums[i]] for tmp in res]res += cur return res

一天一道LeetCode(61-90)相关推荐

  1. 每日一道leetcode(python)48. 旋转图像

    每日一道leetcode(python)48. 旋转图像 2021-07-27 给定一个 n × n 的二维矩阵 matrix 表示一个图像.请你将图像顺时针旋转 90 度. 你必须在 原地 旋转图像 ...

  2. leetcode17. 电话号码的字母组合--每天刷一道leetcode算法系列!

    作者:reed,一个热爱技术的斜杠青年,程序员面试联合创始人 前文回顾: leetcode1. 两数之和--每天刷一道leetcode系列! leetcode2. 两数相加--每天刷一道leetcod ...

  3. leetcode最小面积_每日一道 LeetCode (51):盛最多水的容器

    ❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...

  4. atoi函数_每日一道 LeetCode (50):字符串转换整数 (atoi)

    ❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...

  5. 去掉数组最后一个元素_leetcode 34. 在排序数组中查找元素的第一个和最后一个位置每天刷一道leetcode算法系列!...

    作者:reed,一个热爱技术的斜杠青年,程序员面试联合创始人 前文回顾: leetcode1. 两数之和--每天刷一道leetcode系列! leetcode2. 两数相加--每天刷一道leetcod ...

  6. 二叉树层次遍历c语言_每日一道 LeetCode (23):二叉树的层次遍历 II

    ❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...

  7. c++两个数组对比去掉重复的元素_每日一道 LeetCode (8):删除排序数组中的重复项和移除元素...

    ❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...

  8. 【python】一道LeetCode搞懂递归算法!#131分割回文串 #以及刷LeetCode的一点点小心得 [数据结构与算法基础]

    题目:给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串.返回 s 所有可能的分割方案. # 示例 输入: "aab" 输出: [["aa",&q ...

  9. 每日一道 LeetCode (16):求 x 的平方根

    每天 3 分钟,走上算法的逆袭之路. 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub: https://github.com/meteor1993/LeetCode Gitee ...

最新文章

  1. Clean-Code: 注释
  2. 广义互相关的公式,这一文都搜集全了
  3. 使用JavaScript让网页title动起来
  4. WPF converter(包含传递复杂参数)
  5. mysql数据库挂科_面试命中率 90% 的点 :MySQL 锁
  6. flex4 s:Datagrid s:typicalItem
  7. 复数矩阵分解的拆解思路(矩阵求逆/特征值分解)
  8. 单片机c语言三种经典程序结构,单片机C语言程序的结构和设计精选.docx
  9. Ripro子主题-ziyuan-zhankr资源主题 蓝色简约版
  10. java 90 训练营 二期下载_90天java进阶营二期 主流java技术与热门开源项目视频教程...
  11. c# 与 c++ 界面同框终极技巧
  12. weak_ptr概述,weak_ptr常用操作、尺寸
  13. python之条件判断、循环和字符串格式化
  14. Log4j2 - java.lang.NoSuchMethodError: com.lmax.disruptor.dsl.Disruptor
  15. 30 秒速成好莱坞黑客 -- 在 Linux 终端中伪造好莱坞黑客屏幕
  16. mysql之获取自增长的ID
  17. ARTS打卡计划第二周-Algorithm
  18. ThreeJS 跨域
  19. Tips--解决Deepin20系统安装完毕无WiFi问题
  20. 他一生只做一件事,专注150万农场鸡的鸡蛋销售

热门文章

  1. ios10 NZT10 准备中 预习下iOS10.0-10.2越狱图文教程
  2. pytorch训练模型常见错误(图像)
  3. switch语句用法详解
  4. JAVA毕业设计家教到家平台计算机源码+lw文档+系统+调试部署+数据库
  5. piaget读法_这些名表的发音 你都读对了吗?(内含音频)
  6. vue3 watch 和watchEffect()
  7. ant 是什么???
  8. VirtualBox设置Ubuntu虚拟机网络通信
  9. 【数字信号】基于DTMF双音多频电话拨号仿真含Matlab源码
  10. Advanced-C.07.文件