1:最接近的三数之和
前提是一个排序数组
思路:固定一个(一次遍历),其他双指针。
最接近:与目标值之差
class Solution:
def threeSumclose(self,nums,target):
size=len(nums)
res=float("inf")
for i in range(size): #一次遍历
if i>0 and nums[i]==nums[i-1]: #防止重复
continue
#寻找
#双指针
left=i+1
right=size-1
while left<right:
cur=nums[i]+nums[left]+nums[right]
if cur==target:
return target
if abs(res-target)>abs(cur-target):#寻找最接近,更新结果
res=cur
#指针移动
if cur>target:
right-=1
else:
left+=1
return res
if __name__=='__main__':
nums=[1,2,3,4,5,6,10]
target=16
solution=Solution()
result=solution.threeSumclose(nums,target)
print(result)
2:盛水最多的容器
给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。
在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器,且 n 的值至少为 2。
图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。
在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
思路:
双指针,移动原则为当前左边界和有边界相比较,小的就移动。
class Solution(object):
def maxArea(self, height):
"""
:type height: List[int]
:rtype: int
"""
size=len(height)
left=0
right=size-1
res=0
while left<right:
cur=(right-left)*min(height[right],height[left])
if cur>res:
res=cur
if height[left]<height[right]:
left+=1
else:
right-=1
return res
3:求最大子数组之和
思路: 贪心算法:在每一步求解的步骤中,要求选择最佳操作(局部最优解)
并希望通过一系列的最优选择产生一个全局的最优解
贪心算满足条件:满足问题的约束条件;局部最优;一旦做出选择,后面步骤不可改变
class Solution:
def maxArraySum(self,nums):
max_res=0 #局部最优解
cur_res=0 #当前解
size=len(nums)
for i in range(size):
cur_res=cur_res+nums[i]#求解
if cur_res>=max_res:#局部最优
max_res=cur_res
if cur_res<0:#约束条件,做出选择不可改
cur_res=0
return max_res
4:移除元素
思路:双指针,将与target值相等的元素放在数组的末尾
需要两个指针分别从头扫描,从尾部扫描。
class Solution:
def removeElement(self,nums,val):
size=len(nums)
left=0
right=size-1
while left<right:
#移动
while left<right and nums[left]!=val: #一直移动left,直到找到val
left+=1
while left<right and nums[right]==val: #一直移动right,直到不是val,由于right所指元素是用来交换的
right-=1
#交换
nums[left],nums[right]=nums[right],nums[left]
#计算长度
res=0
for i in range(size):
if nums[i]==val:
return i
res+=1
return res
if __name__=='__main__':
nums=[4,4,34,21,123,4,1,2,123]
val=4
solution=Solution()
result=solution.removeElement(nums,val)
print(result)
5:寻找峰值
寻找峰值
峰值元素是指其值大于左右相邻值的元素。
给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。
数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。
你可以假设 nums[-1] = nums[n] = -∞。
示例 1:
输入: nums = [1,2,3,1]
输出: 2
解释: 3 是峰值元素,你的函数应该返回其索引 2。
示例 2:
输入: nums = [1,2,1,3,5,6,4]
输出: 1 或 5
解释: 你的函数可以返回索引 1,其峰值元
class Solution(object):
def findPeakElement(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
left = 0
right = len(nums) - 1
while left < right:
mid = left + (right - left) // 2
if nums[mid] < nums[mid + 1]:
left = mid + 1
else:
right = mid
return left
if __name__=='__main__':
nums=[1,2,3,1]
solution=Solution()
result=solution.findPeakElement(nums)
print(result)
6:旋转数组
旋转图像
给定一个 n × n 的二维矩阵表示一个图像。将图像顺时针旋转 90 度。
说明:
你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。
示例 1:
给定 matrix =
[
[1,2,3],
[4,5,6],
[7,8,9]
],
原地旋转输入矩阵,使其变为:
[
[7,4,1],
[8,5,2],
[9,6,3]
]
思路:
先对矩阵求转置,之后翻转每一列
#python中二维矩阵的转置用:两层循环,之后a[i][j],a[j][i]=a[j][i],a[i][j]
#翻转每一行,a.reverse(),返回a自己
class Solution(object):
def rotate(self, matrix):
"""
:type matrix: List[List[int]]
:rtype: None Do not return anything, modify matrix in-place instead.
"""
m=len(matrix) #行数
n=len(matrix[0]) #列数
#转置
for i in range(m):
for j in range(i,n): #注意,这里是从i开始
matrix[i][j],matrix[j][i]=matrix[j][i],matrix[i][j]
#翻转
for i in range(m):
matrix[i].reverse()
return matrix
if __name__=='__main__':
matrix=[
[1,2,3],
[4,5,6],
[7,8,9]
]
solution=Solution()
result=solution.rotate(matrix)
print(result)
7:
搜索旋转排序数字组II
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] )。
编写一个函数来判断给定的目标值是否存在于数组中。若存在返回 true,否则返回 false。
示例 1:
输入: nums = [2,5,6,0,0,1,2], target = 0
输出: true
示例 2:
输入: nums =
class Solution(object):
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: bool
"""
size=len(nums)
left=0
right=size-1
while left<=right:
mid=left+(right-left)//2
if nums[mid]==target:
return True
else:
if nums[left]<nums[mid]:#mid左边为正常
if nums[mid]>target>=nums[left]:
right=mid-1
else:
left=mid+1
else:
if nums[mid]<target<=nums[right]:
left=mid+1
else:
right=mid-1
return False
if __name__=='__main__':
nums = [2,5,6,0,0,1,2]
target=3
solution=Solution()
result=solution.search(nums,target)
print(result
8:搜索二维矩阵
class Solution(object):
def searchMatrix(self, matrix, target):
"""
:type matrix: List[List[int]]
:type target: int
:rtype: bool
"""
if not matrix:
return False
m=len(matrix)
n=len(matrix[0])
for i in range(m):
for j in range(n):
if matrix[i][j]<target:
pass
elif matrix[i][j]==target:
return True
else:
return False
9:数组合并
区间合并
给出一个区间的集合,请合并所有重叠的区间。
输入: [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6]
先按首位置进行排序;
接下来,如何判断两个区间是否重叠呢?比如 a = [1,3],b = [2,6]
当 a[1] >= b[0] 说明两个区间有重叠.
但是如何把这个区间找出来呢?
左边位置一定是确定,就是 a[0],而右边位置是 max(a[1], b[1])
所以,我们就能找出整个区间为:[1,4]
class Solution(object):
def merge(self, intervals):
"""
:type intervals: List[List[int]]
:rtype: List[List[int]]
"""
intervals=sorted(intervals)
size=len(intervals)
res=[intervals[0]]
i=1
while i<size:
if res[-1][1]>=intervals[i][0]:
temp=[res[-1][0],max(res[-1][1],intervals[i][1])]
res[-1]=temp
else:
res.append(intervals[i])
i+=1
return res
if __name__=='__main__':
intervals= [[1,3],[2,6],[8,10],[15,18]]
solution=Solution()
result=solution.merge(intervals)
print(result)
10:三数之和
思路:先排序(前提),再用左右指针法
class Solution:
def F1(self,a):
l=len(a)
if l<3:
return False
if l==3:
if sum(a)==0:
return a
else:
return 0
sorted(a) #数组排序,注意不很关键啊,要不左右之指针没法用啊
result=[]
for i in range(l-2):
if i > 0 and a[i] == a[i - 1]: #作用避免重复
continue
left=i+1 #左指针
right=l-1 #右指针
while left<right: #之所以用这个作为循环结束标志,保证了不重复的指针运动
if a[left]+a[right]==-a[i]:
result.append(([a[i],a[left],a[right]]))
left+=1
if a[left]+a[right]<-a[i]: #往大的方向走
left+=1
if a[left]+a[right]>-a[i]: #往小的方向走
right-=1
if left==i:
left+=1
return result
a=Solution()
print(a.F1([-5,-1,-2,-3,0,1,2,3,4]))
11.螺旋矩阵
给定一个正整数 n,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
示例:
输入: 3
输出:
[
[ 1, 2, 3 ],
[ 8, 9, 4 ],
[ 7, 6, 5 ]
]
思路:模拟旋转过程
确定上下左右四个边界
class Solution(object):
def generateMatrix(self, n):
"""
:type n: int
:rtype: List[List[int]]
"""
left=0
right=n-1
top=0
bottom=n-1
stop=n*n
matrix=[[0 for i in range(n)] for i in range(n)]
i=1
while i<=stop:
for k in range(left,right+1):
matrix[top][k]=i
i+=1
top+=1
for k in range(top,bottom+1):
matrix[k][right]=i
i+=1
right-=1
for k in range(right,left-1,-1):
matrix[bottom][k]=i
i+=1
bottom-=1
for k in range(bottom,top-1,-1):
matrix[k][left]=i
i+=1
left+=1
return matrix
if __name__=='__main__':
n=3
solution=Solution()
result=solution.generateMatrix(n)
print(result)
12:两个数组的交集
定两个数组,编写一个函数来计算它们的交集。
示例 1:
输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2,2]
示例 2:
输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出: [4,9]
class Solution(object):
def intersect(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: List[int]
"""
res=[]
i=0
size1=len(nums1)
size2=len(nums2)
if size1<size2:
num=nums1
numm=nums2
else:
num=nums2
numm=nums1
for i in range(len(num)):
if num[i] in numm :
res.append(num[i])
numm.pop(numm.index(num[i]))
return res
13:除自身以外的乘积
给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。
示例:
输入: [1,2,3,4]
输出: [24,12,8,6]
说明: 请不要使用除法,且在 O(n) 时间复杂度内完成此题。
思路:入手点,由于题目要求是O(n),所以可能是线性的一层循环遍历。
由于除自身,所以该位置上的乘积为该点左边的乘积*右边的乘积
"""
class Solution(object):
def productExceptSelf(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
size=len(nums)
#求解i位置上的左乘积
res_left=[1]
cur=1
for i in range(1,size):
cur=cur*nums[i-1]
res_left.append(cur)
#求解i位置上的右乘积
res_right=[1]
cur=1
for i in range(0,size-1)[::-1]:
cur=cur*nums[i+1]
res_right.append(cur)
res_right.reverse()
#左*右
res=[]
for i in range(size):
res.append(res_left[i]*res_right[i])
return res
if __name__=='__main__':
nums=[1,2,3,4]
solution=Solution()
result=solution.productExceptSelf(nums)
print(result)
14:找出目标元素在数组中的开始位置和结束位置
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
你的算法时间复杂度必须是 O(log n) 级别。
如果数组中不存在目标值,返回 [-1, -1]。
示例 1:
输入: nums = [5,7,7,8,8,10], target = 8
输出: [3,4]
示例 2:
输入: nums = [5,7,7,8,8,10], target = 6
输出: [-1,-1]
class Solution(object):
def searchRange(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
n=len(nums)
left=0
right=n
res=[]
if not nums:
return [-1,-1]
#二分查找
while left<=right: #注意等号
mid=left+(right-left)//2
k=mid
while k<n and nums[k]==target:#循环遍历右边数组,找出重复元素
res.append(k)
k+=1
if mid<n and nums[mid]>=target:
right=mid-1
else:
left=mid+1
if not res:
return [-1,-1]
return [min(res),max(res)]
if __name__=='__main__':
nums=[2,2]
target=3
solution=Solution()
result=solution.searchRange(nums,target)
print(result)
15:求众数
求众数
给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在众数。
示例 1:
输入: [3,2,3]
输出: 3
示例 2:
输入: [2,2,1,1,1,2,2]
class Solution(object):
def majorityElement(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
size=len(nums)
k=size//2
res=[]
dict1={}
for i in range(size):
if nums[i] not in dict1 or not dict1:
dict1[nums[i]]=1
else:
dict1[nums[i]]+=1
for i in dict1.keys():
if dict1[i]>k:
res.append(i)
return max(res)d
16:矩阵置0
矩阵置0
给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地算法。
示例 1:
输入:
[
[1,1,1],
[1,0,1],
[1,1,1]
]
输出:
[
[1,0,1],
[0,0,0],
[1,0,1]
]
class Solution(object):
def setZeroes(self, matrix):
"""
:type matrix: List[List[int]]
:rtype: None Do not return anything, modify matrix in-place instead.
"""
m=len(matrix)
n=len(matrix[0])
row=set()
col=set()
#找出0元素所在的行,列
for i in range(m):
for j in range(n):
if matrix[i][j]==0:
row.add(i)
col.add(j)
#元素置0
for i in range(m):
for j in range(n):
if i in row or j in col:
matrix[i][j]==0
return matrix
17:下个队列
#输入:nums = [1,2,3]
#输出:[1,3,2]
#思路 1: 先找num[i]: 从后往前升序,遇到降序的第一个元素 num[j]: 从后往前遇到的第一个比num[i]大的 两者交换 保证下一个队列大的在前面
# 2: 之后left = i + 1; right = len - 1; [left, right]这个降序序列做双指针反转吧,变为升序
class Solution:
def nextPermutation(self, nums: List[int]) -> None:
i = len(nums) - 2
while i >= 0 and nums[i] >= nums[i + 1]:
i -= 1
if i >= 0:
j = len(nums) - 1
while j >= 0 and nums[i] >= nums[j]:
j -= 1
nums[i], nums[j] = nums[j], nums[i]
left, right = i + 1, len(nums) - 1
while left < right:
nums[left], nums[right] = nums[right], nums[left]
left += 1
right -= 1
if __name__ == '__main__':
n = 3
solution = Solution()
print(solution.generateParenthesis(n))
18:搜索旋转排序数组
#序排列的整数数组 nums 在预先未知的某个点上进行了旋转(例如, [0,1,2,4,5,6,7] 经旋转后可能变为 [4,5,6,7,0,1,2] )。
#请你在数组中搜索 target ,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。
#示例 1:
# 输入:nums = [4,5,6,7,0,1,2], target = 0
# 输出:4
#思路:由于要求复杂度为log(n),因此需要用到二分法。二分法前提是排序数组。对于旋转之后额数组,各一半的排序,因此也可以用。
# mid = right + len //2 nums[0] 和 nums[mid]进行比较确定一定升序的范围 之后 target做比较 移动左右指针
class Solution:
def search(self, nums, target):
if not nums:
return -1
l, r = 0, len(nums) - 1
while l <= r:
mid = (l + r) // 2
if nums[mid] == target:
return mid
if nums[0] <= nums[mid]:
if nums[0] <= target < nums[mid]:
r = mid - 1
else:
l = mid + 1
else:
if nums[mid] < target <= nums[len(nums) - 1]:
l = mid + 1
else:
r = mid - 1
return -1
if __name__ == '__main__':
nums = [4,5,6,7,0,1,2]
target = 0
a = Solution()
c = a.search(nums, target)
print(c)
19:下一个更大元素
输入: [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数;
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。
思路:单调栈, 两次循环。 保证栈一定是个单调递减的, 这里栈中追加的是idx
class Solution:
def nextGreaterElements(self, nums: List[int]) -> List[int]:
stack, res = [], [-1] * len(nums)
for idx, num in enumerate(nums):
while stack and nums[stack[-1]] < num:
res[stack.pop()] = num
stack.append(idx)
for idx, num in enumerate(nums):
while stack and nums[stack[-1]] < num:
res[stack.pop()] = num
return res
20: 每日温度
请根据每日 气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。
例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。
提示:气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。
思路: 单调栈, 一次for+while循环,i - pre_index 为结果元素, 堆栈放的idx
class Solution(object):
def dailyTemperatures(self, T):
"""
:type T: List[int]
:rtype: List[int]
"""
l = len(T)
stack = []
result = [0 for i in range(l)]
for i in range(l):
while stack and T[i] > T[stack[-1]]:
pre_index = stack.pop()
result[pre_index] = i - pre_index
stack.append(i)
return result
if __name__ == '__main__':
nums = [73, 74, 75, 71, 69, 72, 76, 73]
a = Solution()
c = a.dailyTemperatures(nums)
print(c)