打算把LeetCode上面的题都实现一遍,每日两题
LeetCode目录
- 1. 两数之和
- 2. 两数相加
- 11. 盛最多水的容器
- 15.三数之和
- 33.搜索旋转排序数组
- 34. 在排序数组中查找元素的第一个和最后一个位置
- 35.搜索插入位置
- 53.最大子数组和
- 64. 最小路径和
- 70.爬楼梯
- 74.搜索二维矩阵
- 82. 删除排序链表中的重复元素 II
- 88. 合并两个有序数组
- 153. 寻找旋转排序数组中的最小值
- 162. 寻找峰值
- 167. 两数之和 II - 输入有序数组
- 189.轮转数组
- 217.存在重复元素
- 278.第一个错误的版本
- 283. 移动零
- 344. 反转字符串
- 557. 反转字符串中的单词 III
- 704. 二分查找
- 844. 比较含退格的字符串
- 977. 有序数组的平方
- 986. 区间列表的交集
- 剑指 Offer 05. 替换空格
- 剑指 Offer 06. 从尾到头打印链表
- 剑指 Offer 09.用两个栈实现队列
- 剑指 Offer 24. 反转链表
- 剑指 Offer 30.包含min函数的栈
1. 两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那两个整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案
示例
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
输入:nums = [3,2,4], target = 6
输出:[1,2]
输入:nums = [3,3], target = 6
输出:[0,1]
思路
巧用字典结构
代码
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
dist={}
for d,ind in enumerate(nums):
dist[ind] = d
for i, j in enumerate(nums):
f = dist.get(target - j)
if f is not None and f != i:
return [i, f]
2. 两数相加
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
思路
代码
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
re = ListNode(0)
r=re
carry=0
while(l1 or l2):
x= l1.val if l1 else 0
y= l2.val if l2 else 0
s=carry+x+y
carry=s//10
r.next=ListNode(s%10)
r=r.next
if(l1!=None):l1=l1.next
if(l2!=None):l2=l2.next
if(carry>0):
r.next=ListNode(1)
return re.next
11. 盛最多水的容器
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。
示例 1:
输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例 2:
输入:height = [1,1]
输出:1
思路
使用双指针 注意!我们每次只要移动高度小的一边,因为移动小的那一边可能会增大,但是移动大的一边一定会减小
代码
class Solution:
def maxArea(self, height: List[int]) -> int:
i = 0
j = len(height) - 1
res = 0
while(i < j):
if(height[i] < height[j]):
res = max(res,height[i]*(j-i))
i += 1
else:
res = max(res,height[j]*(j-i))
j -= 1
return res
15.三数之和
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
示例 2:
输入:nums = []
输出:[]
示例 3:
输入:nums = [0]
输出:[]
思路
可以使用双指针,先排序(时间复杂度nlogn),然后令L = i+1 ,R = n - 1,我们遍历i,如果值大了我们就R–,小了就L++
代码
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
n=len(nums)
res=[]
if(not nums or n<3):
return []
nums.sort()
res=[]
for i in range(n):
if(nums[i]>0):
return res
if(i>0 and nums[i]==nums[i-1]):
continue
L=i+1
R=n-1
while(L<R):
if(nums[i]+nums[L]+nums[R]==0):
res.append([nums[i],nums[L],nums[R]])
while(L<R and nums[L]==nums[L+1]):
L=L+1
while(L<R and nums[R]==nums[R-1]):
R=R-1
L=L+1
R=R-1
elif(nums[i]+nums[L]+nums[R]>0):
R=R-1
else:
L=L+1
return res
33.搜索旋转排序数组
整数数组 nums 按升序排列,数组中的值 互不相同 。
在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。
给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。
示例 1:
输入:nums = [4,5,6,7,0,1,2], target = 0
输出:4
示例 2:
输入:nums = [4,5,6,7,0,1,2], target = 3
输出:-1
示例 3:
输入:nums = [1], target = 0
输出:-1
思路
二分查找题,先用二分查找找到k,然后找到目标值
代码
class Solution:
def search(self, nums: List[int], target: int) -> int:
if(len(nums) == 0):
return -1
n = len(nums)
r = n-1
l = 0
# find k
while(l<r):
m = int(l + (r -l)/2)
if(nums[m] < nums[r]):
r = m
else:
l = m+1
k = l
l = 0
r = k-1
while(l<r):
m = int(l + (r -l)/2)
if(nums[m] >= target):
r = m
else:
l = m+1
if(nums[l]==target):
return l
l = k
r = n -1
while(l<r):
m = int(l + (r -l)/2)
if(nums[m] >= target):
r = m
else:
l = m+1
if(nums[l]==target):
return l
else:
return -1
34. 在排序数组中查找元素的第一个和最后一个位置
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
进阶:
你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?
示例 1:
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]
示例 2:
输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]
示例 3:
输入:nums = [], target = 0
输出:[-1,-1]
思路
两分查找,先找开始的位置,在找结束的位置。
代码
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
res = [-1,-1]
if(len(nums) == 0):
return res
n = len(nums)
l = 0
r = n-1
while(l < r):
m = int(l + (r - l)/2)
if(nums[m] >= target):
r = m
else:
l = m+1
if(nums[l] != target):
return res
res[0] = l
r = n
while(l < r):
m = int(l + (r - l)/2)
if(nums[m] <= target):
l = m+1
else:
r = m
res[1] = l-1
return res
35.搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
示例 1:
输入: nums = [1,3,5,6], target = 5
输出: 2
示例 2:
输入: nums = [1,3,5,6], target = 2
输出: 1
示例 3:
输入: nums = [1,3,5,6], target = 7
输出: 4
示例 4:
输入: nums = [1,3,5,6], target = 0
输出: 0
示例 5:
输入: nums = [1], target = 0
输出: 0
思路
代码
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
left = 0
right = len(nums) - 1
while(left <= right):
mid = int(left + (right - left )/ 2)
if nums[mid] < target:
left = mid + 1
else:
right = mid - 1
return left
53.最大子数组和
给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2:
输入:nums = [1]
输出:1
示例 3:
输入:nums = [5,4,-1,7,8]
输出:23
思路
可以使用动态规划的方法,如下代码,f_n表示前n个之和最大值
代码
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
res = -10000
f_n = -1
for i in range(len(nums)):
f_n = max(nums[i],f_n + nums[i])
res = max(f_n,res)
return res
64. 最小路径和
给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
思路
代码
class Solution:
def minPathSum(self, grid: List[List[int]]) -> int:
m = len(grid)
n = len(grid[0])
if(m<=0 or n<=0):
return 0
dp = []
for i in range(m):
dp.append([])
for j in range(n):
dp[i].append(0)
dp[0][0] = grid[0][0]
for i in range(1,m):
dp[i][0] = grid[i][0] + dp[i-1][0]
for i in range(1,n):
dp[0][i] = grid[0][i] + dp[0][i-1]
for i in range(1,m):
for j in range(1,n):
dp[i][j] = min(dp[i-1][j],dp[i][j-1]) + grid[i][j]
return dp[m-1][n-1]
70.爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
示例 1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶
示例 2:
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶
思路
代码
class Solution:
def climbStairs(self, n: int) -> int:
A = []
if(n<=2):
return n
A.append(0)
A.append(1)
A.append(2)
for i in range(3,n+1):
A.append(A[i-1] + A[i-2])
return int(A[i])
74.搜索二维矩阵
编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:
每行中的整数从左到右按升序排列。
每行的第一个整数大于前一行的最后一个整数。
思路
将二维排序成一维来做,继续用二分查找
代码
class Solution(object):
def searchMatrix(self, matrix, target):
"""
:type matrix: List[List[int]]
:type target: int
:rtype: bool
"""
n = len(matrix)
m = len(matrix[0])
l = 0
r = n*m-1
while(l<r):
mid = int(l + (r - l)/2)
mid1 = mid/m
mid2 = mid%m
if(matrix[mid1][mid2] >= target):
r = mid
else:
l = mid + 1
ma1 = l/m
ma2 = l%m
if(matrix[ma1][ma2] == target):
return True
else:
return False
82. 删除排序链表中的重复元素 II
给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。
思路
很容易的题,主要是第一个值的话怎么删,我们可以新建一个next 为列表的头head
代码
class Solution:
def deleteDuplicates(self, head: ListNode) -> ListNode:
if(not head):
return head
tem = ListNode(0,head)
cur = tem
while(cur.next and cur.next.next):
if(cur.next.val == cur.next.next.val):
x = cur.next.val
while(cur.next and cur.next.val == x):
cur.next = cur.next.next
else:
cur = cur.next
return tem.next
88. 合并两个有序数组
给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
示例 1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
示例 2:
输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
解释:需要合并 [1] 和 [] 。
合并结果是 [1] 。
示例 3:
输入:nums1 = [0], m = 0, nums2 = [1], n = 1
输出:[1]
解释:需要合并的数组是 [] 和 [1] 。
合并结果是 [1] 。
注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。
思路
我们巧用nums1的结构,把从大到小排序放进去
代码
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
p1, p2 = m - 1, n - 1
tail = len(nums1) - 1
while p2 >= 0:
if p1 < 0 or nums1[p1] <= nums2[p2]:
nums1[tail] = nums2[p2]
p2 -= 1
tail -= 1
else:
nums1[tail] = nums1[p1]
p1 -= 1
tail -= 1
153. 寻找旋转排序数组中的最小值
已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:
若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]
注意,数组 [a[0], a[1], a[2], …, a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], …, a[n-2]] 。
给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。
你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。
示例 1:
输入:nums = [3,4,5,1,2]
输出:1
解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。
示例 2:
输入:nums = [4,5,6,7,0,1,2]
输出:0
解释:原数组为 [0,1,2,4,5,6,7] ,旋转 4 次得到输入数组。
示例 3:
输入:nums = [11,13,15,17]
输出:11
解释:原数组为 [11,13,15,17] ,旋转 4 次得到输入数组。
思路
查找旋转次数就好了
代码
class Solution:
def findMin(self, nums: List[int]) -> int:
if(len(nums) == 0):
return -1
n = len(nums)
r = n-1
l = 0
# find k
while(l<r):
m = int(l + (r -l)/2)
if(nums[m] < nums[r]):
r = m
else:
l = m+1
return nums[l]
162. 寻找峰值
峰值元素是指其值严格大于左右相邻值的元素。
给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。
你可以假设 nums[-1] = nums[n] = -∞ 。
你必须实现时间复杂度为 O(log n) 的算法来解决此问题。
示例 1:
输入:nums = [1,2,3,1]
输出:2
解释:3 是峰值元素,你的函数应该返回其索引 2。
示例 2:
输入:nums = [1,2,1,3,5,6,4]
输出:1 或 5
解释:你的函数可以返回索引 1,其峰值元素为 2;
或者返回索引 5, 其峰值元素为 6。
思路
二分法,只需要判断nums[m] > nums[m+1],因为大的值一定有解
代码
class Solution:
def findPeakElement(self, nums: List[int]) -> int:
n = len(nums)
l = 0
r = n - 1
while(l < r):
mid = int(l + (r - l)/2)
if(nums[mid] > nums[mid + 1]):
r = mid
else:
l = mid + 1
return l
167. 两数之和 II - 输入有序数组
给定一个已按照 非递减顺序排列 的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。
函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 1 开始计数 ,所以答案数组应当满足 1 <= answer[0] < answer[1] <= numbers.length 。
你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。
示例 1:
输入:numbers = [2,7,11,15], target = 9
输出:[1,2]
解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。
示例 2:
输入:numbers = [2,3,4], target = 6
输出:[1,3]
示例 3:
输入:numbers = [-1,0], target = -1
输出:[1,2]
思路
代码
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
l = 0
r = len(numbers)-1
while(l<r):
if(numbers[l]+numbers[r]>target):
r= r - 1
elif(numbers[l]+numbers[r]<target):
l= l + 1
else:
return [l+1,r+1]
return [l+1,r+1]
189.轮转数组
给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
示例 1:
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]
示例 2:
输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释:
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]
思路
代码
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
nums[: ] = nums[-k % len(nums) :] + nums[: -k % len(nums)]
217.存在重复元素
给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false 。
示例 1:
输入:nums = [1,2,3,1]
输出:true
示例 2:
输入:nums = [1,2,3,4]
输出:false
示例 3:
输入:nums = [1,1,1,3,3,4,3,2,4,2]
输出:true
思路
利用集合的唯一性来做。(暴力穷举算法复杂度太大了
O
(
n
2
)
O(n^2)
O(n2))
代码
class Solution:
def containsDuplicate(self, nums: List[int]) -> bool:
numsset = set(nums)
if(len(nums) == len(numsset)):
return False
else:
return True
278.第一个错误的版本
你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。
假设你有 n 个版本 [1, 2, …, n],你想找出导致之后所有版本出错的第一个错误的版本。
你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
示例 1:
输入:n = 5, bad = 4
输出:4
解释:
调用 isBadVersion(3) -> false
调用 isBadVersion(5) -> true
调用 isBadVersion(4) -> true
所以,4 是第一个错误的版本。
示例 2:
输入:n = 1, bad = 1
输出:1
思路
代码
class Solution:
def firstBadVersion(self, n):
"""
:type n: int
:rtype: int
"""
left = 1
right = n
while(left<right):
mid = int(left + (right - left)/2)
if(isBadVersion(mid)):
right = mid
else:
left = mid + 1
return left
283. 移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
示例:
输入: [0,1,0,3,12]
输出: [1,3,12,0,0]
思路
代码
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
nums.sort(key=bool, reverse=True)
344. 反转字符串
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
示例 1:
输入:s = ["h","e","l","l","o"]
输出:["o","l","l","e","h"]
示例 2:
输入:s = ["H","a","n","n","a","h"]
输出:["h","a","n","n","a","H"]
思路
代码
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
r = len(s)
l = r
for i in range(int(r/2)):
l = l - 1
tmp = s[i]
s[i] = s[l]
s[l] = tmp
return s
一行实现
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
s.reverse()
557. 反转字符串中的单词 III
给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。
示例:
输入:"Let's take LeetCode contest"
输出:"s'teL ekat edoCteeL tsetnoc"
思路
代码
一行代码
class Solution:
def reverseWords(self, s: str) -> str:
return ' '.join([w[::-1] for w in s.split()])
704. 二分查找
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
示例 1:
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
示例 2:
输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1
思路
代码
class Solution:
def search(self, nums: List[int], target: int) -> int:
right = len(nums)-1
left = 0
while(left <= right):
mid = int(left + (right - left)/2)
if(target < nums[mid]):
right = mid - 1
elif(target > nums[mid]):
left = mid + 1
else:
return mid
return -1
844. 比较含退格的字符串
给定 s 和 t 两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true 。# 代表退格字符。
注意:如果对空文本输入退格字符,文本继续为空。
示例 1:
输入:s = "ab#c", t = "ad#c"
输出:true
解释:s 和 t 都会变成 "ac"。
示例 2:
输入:s = "ab##", t = "c#d#"
输出:true
解释:s 和 t 都会变成 ""。
示例 3:
输入:s = "a#c", t = "b"
输出:false
解释:s 会变成 "c",但 t 仍然是 "b"。
思路
如果暴力的话肯定不行的,要占用新的内存,且要比较。我们可以使用双指针,从后往前读,比较每一个字符。有不符号返回flase
代码
class Solution:
def backspaceCompare(self, s: str, t: str) -> bool:
i = len(s) - 1
j = len(t) - 1
skipi = 0
skipj = 0
while(i >= 0 or j >= 0):
while(i >= 0):
if(s[i] == '#'):
skipi += 1
i -= 1
elif(skipi > 0):
skipi -= 1
i -= 1
else:
break
while(j >= 0):
if(t[j] == '#'):
skipj += 1
j -= 1
elif(skipj > 0):
skipj -= 1
j -= 1
else:
break
if(i >= 0 and j >= 0):
if(s[i] != t[j]):
return False
elif(i >= 0 or j >= 0):
return False
i -= 1
j -= 1
return True
977. 有序数组的平方
给你一个按 非递减顺序 排序的整数数组 nums,返回每个数字的平方 组成的新数组,要求也按非递减顺序排序。
示例 1:
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
示例 2:
输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]
提示:
1 <= nums.length <= 104
-104 <= nums[i] <= 104
nums 已按 非递减顺序 排序
进阶:
请你设计时间复杂度为 O(n) 的算法解决本问题
思路
代码
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
B = sorted([num*num for num in nums])
return B
986. 区间列表的交集
给定两个由一些 闭区间 组成的列表,firstList 和 secondList ,其中 firstList[i] = [starti, endi] 而 secondList[j] = [startj, endj] 。每个区间列表都是成对 不相交 的,并且 已经排序 。
返回这 两个区间列表的交集 。
形式上,闭区间 [a, b](其中 a <= b)表示实数 x 的集合,而 a <= x <= b 。
两个闭区间的 交集 是一组实数,要么为空集,要么为闭区间。例如,[1, 3] 和 [2, 4] 的交集为 [2, 3] 。
示例 1:
输入:firstList = [[0,2],[5,10],[13,23],[24,25]], secondList = [[1,5],[8,12],[15,24],[25,26]]
输出:[[1,2],[5,5],[8,10],[15,23],[24,24],[25,25]]
示例 2:
输入:firstList = [[1,3],[5,9]], secondList = []
输出:[]
示例 3:
输入:firstList = [], secondList = [[4,8],[10,12]]
输出:[]
示例 4:
输入:firstList = [[1,7]], secondList = [[3,10]]
输出:[[3,7]]
思路
使用双指针,一个指向其中一个数组,对每一个内部数组进行比较。
代码
class Solution:
def intervalIntersection(self, firstList: List[List[int]], secondList: List[List[int]]) -> List[List[int]]:
res = []
i = 0
j = 0
while(i < len(firstList) and j<len(secondList)):
start = max(firstList[i][0],secondList[j][0])
end = min(firstList[i][1],secondList[j][1])
if(start <= end):
res.append([start,end])
if(firstList[i][1]<secondList[j][1]):
i += 1
else:
j += 1
return res
剑指 Offer 05. 替换空格
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
示例 1:
输入:s = "We are happy."
输出:"We%20are%20happy."
思路
代码
class Solution:
def replaceSpace(self, s: str) -> str:
return s.replace(" ","%20")
剑指 Offer 06. 从尾到头打印链表
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
示例 1:
输入:head = [1,3,2]
输出:[2,3,1]
思路
代码
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def reversePrint(self, head: ListNode) -> List[int]:
A = []
while(head):
A.append(head.val)
head = head.next
return A[::-1]
剑指 Offer 09.用两个栈实现队列
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
思路
代码
class CQueue:
def __init__(self):
self.s1 = []
self.s2 = []
def appendTail(self, value: int) -> None:
self.s1.append(value)
def deleteHead(self) -> int:
if(len(self.s1)==0 and len(self.s2) == 0):
return -1
if(len(self.s1)!=0 and len(self.s2) == 0):
while(len(self.s1)!=0):
self.s2.append(self.s1.pop())
return self.s2.pop()
if(len(self.s2) != 0):
return self.s2.pop()
return -1
剑指 Offer 24. 反转链表
定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
思路
代码
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
preNode = None
currNode = head
while(currNode):
nextNode = currNode.next
currNode.next = preNode
preNode = currNode
currNode = nextNode
return preNode
剑指 Offer 30.包含min函数的栈
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
思路
代码
class MinStack:
def __init__(self):
"""
initialize your data structure here.
"""
self.MS = []
self.Min = inf
def push(self, x: int) -> None:
self.MS.append(self.Min)
if(x<self.Min):
self.Min = x
self.MS.append(x)
def pop(self) -> None:
self.MS.pop(-1)
self.Min = self.MS.pop(-1)
def top(self) -> int:
return self.MS[-1]
def min(self) -> int:
return self.Min
# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(x)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.min()