主要方法:二分查找 | 滑动窗口 (滑动窗口不会)
就写了几个数组的题,感觉数组没必要单独开一篇文章,因为数组这一类包含了二分查找,回溯,贪心甚至二叉树。
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
dic = {}
for i in range(len(nums)):
another_num = target - nums[i]
if another_num in dic:
return [dic[another_num], i]
else:
dic[nums[i]] = i
4. 寻找两个正序数组的中位数 (困难)
class Solution(object):
def findMedianSortedArrays(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
nums1.extend(nums2)
nums1.sort()
# 判断合并后列表的长度是奇数还是偶数,然后根据中位数计算规则计算出中位数
length = len(nums1)
if length % 2 == 0:
return (nums1[int(length/2 - 1)] + nums1[int(length/2)]) / 2.0
else:
return nums1[int((length+1)/2 - 1)]
11. 盛最多水的容器 (中等)
class Solution(object):
def maxArea(self, height):
"""
:type height: List[int]
:rtype: int
"""
left = 0
right = len(height)-1
if not height or len(height) == 1 :
return 0
if height[left] < height[right]:
res = (right-left)*height[left]
else:
res = (right-left)*height[right]
while left < right:
if height[left] < height[right]:
if res > (right-left)*height[left]:
res = res
else:
res = (right-left)*height[left]
left += 1
else :
if res > (right-left)*height[right]:
res = res
else:
res = (right-left)*height[right]
right -=1
return res
15. 三数之和 (中等)
class Solution(object):
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
nums = sorted(nums)
res = []
for i in range(len(nums)):
if nums[i] > 0:
break
if i > 0 and nums[i] == nums[i-1]:
continue
left = i+1
right = len(nums)-1
while left < right:
if nums[i] + nums[left] + nums[right] > 0:
right -=1
elif nums[i] + nums[left] + nums[right] < 0:
left += 1
else:
res.append([nums[i], nums[left], nums[right]])
while left < right and nums[left] == nums[left+1]:
left += 1
while left < right and nums[right] == nums[right-1]:
right -= 1
left += 1
right -= 1
return res
16. 最接近的三数之和 (中等 自己写的)
class Solution(object):
def threeSumClosest(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
nums.sort()
mins = 2**32
res = 0
for i in range(len(nums)):
left = i+1
right = len(nums) - 1
while left < right:
if nums[i] + nums[left] + nums[right] > target:
if nums[i] + nums[left] + nums[right] - target < mins:
res = nums[i] + nums[left] + nums[right]
mins = nums[i] + nums[left] + nums[right] - target
right -= 1
elif nums[i] + nums[left] + nums[right] < target:
if target - (nums[i] + nums[left] + nums[right]) < mins:
res = nums[i] + nums[left] + nums[right]
mins = target - (nums[i] + nums[left] + nums[right])
left += 1
else:
return target
return res
class Solution(object):
def fourSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[List[int]]
"""
nums = sorted(nums)
res = []
for i in range(len(nums)):
if i > 0 and nums[i] == nums[i-1]:
continue
for j in range(i+1, len(nums)):
if j > i+ 1 and nums[j] == nums[j-1]:
continue
left = j+1
right = len(nums)-1
while left < right:
if nums[left] + nums[right] +nums[i]+nums[j]>target:
right -= 1
elif nums[left] + nums[right] +nums[i]+nums[j]<target:
left += 1
else:
res.append([nums[i], nums[j], nums[left], nums[right]])
while left < right and nums[left] == nums[left+1]:
left += 1
while left < right and nums[right] == nums[right-1]:
right -= 1
left += 1
right -= 1
return res
26. 删除有序数组中的重复项 (简单)
class Solution(object):
def removeDuplicates(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
i = 0
while i < len(nums)-1:
if nums[i+1] == nums[i]:
del nums[i+1]
else:
i+=1
return len(nums)
27. 移除元素 (简单)
class Solution(object):
def removeElement(self, nums, val):
"""
:type nums: List[int]
:type val: int
:rtype: int
"""
i = 0
while i < len(nums):
if nums[i] == val:
del nums[i]
else:
i+=1
return len(nums)
31. 下一个排列 (不会)
class Solution(object):
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
n = len(nums)
left, right = 0, n-1
while left<right:
mid = (left+right)//2
if nums[mid] == target:
return mid
if nums[left] <= nums[mid]: #说明mid在旋转的前半部分
if nums[left] <= target <= nums[mid]:
right = mid
else:
left = mid + 1
else: #left 大于 mid 说明mid已经在旋转的后半部分
if nums[mid] <= target <= nums[right]: #如果target在旋转的后半部分的mid和right之间
left = mid + 1
else:
right = mid
if nums and nums[left]==target:
return left
else:
return -1
34. 在排序数组中查找元素的第一个和最后一个位置 (中等 自己写的 就是注意细节 要改来改去)
class Solution(object):
def searchRange(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
start = -1
end = -1
left = 0
right = len(nums) - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] == target:
start = mid
end = mid
break
elif nums[mid] > target:
right = mid-1
else:
left = mid+1
if start != -1:
while start > 0 and nums[start-1] == target:
start -= 1
while end < len(nums)-1 and nums[end+1] == target:
end += 1
return [start, end]
35. 搜索插入位置 (简单)
class Solution(object):
def searchInsert(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
left = 0
right = len(nums) - 1
while left <= right:
mid = (left+right) // 2
if nums[mid] == target:
return mid
elif nums[mid] > target:
right = mid -1
else:
left = mid + 1
return left
36. 有效的数独 (不会 再看)
https://segmentfault.com/a/1190000023277543
class Solution(object):
def isValidSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: bool
"""
# 定义哈希表存储数字出现在每行,每列,每个 3x3 的宫格的次数
# 题目中说明,给定的数独一定是 9x9 的
rows = [{} for _ in range(9)]
cols = [{} for _ in range(9)]
boxes = [{} for _ in range(9)]
for i in range(9):
for j in range(9):
# 题目中要验证是已经填入的数字,如果出现 '.' 表示留空,不作处理
if board[i][j] != '.':
# 取出数字,存入哈希表中(需要转换,给定的二维数组数字是字符串格式)
num = int(board[i][j])
rows[i][num] = rows[i].get(num, 0) + 1
cols[j][num] = cols[j].get(num, 0) + 1
# 代入枚举 3x3 宫格的公式
boxes[(i // 3) * 3 + j // 3][num] = boxes[(i // 3) * 3 + j // 3].get(num, 0) + 1
# 行,列,3x3 宫格,任意一个如果出现数字重复,则返回 False
if rows[i][num] > 1 or cols[j][num] > 1 or boxes[(i // 3) * 3 + j // 3][num] > 1:
return False
return True
37. 解数独 (困难 不会)
41. 缺失的第一个正数 (困难题,看到困难我就怕了,确实是我想不起来的巧妙的解法)
https://segmentfault.com/a/1190000023030256
class Solution(object):
def firstMissingPositive(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
length = len(nums)
for i in range(length):
# 这里判断元素是否落在 [1, n],判断是否落在正确的位置
# 注意:防止进入死循环,当元素刚好落在正确位置,直接跳过,判断下个元素
while 1 <= nums[i] <= length and nums[i] != nums[nums[i] - 1]:
# 交换
nums[nums[i] - 1], nums[i] = nums[i], nums[nums[i] - 1]
# 将数组的元素恢复到正确的位置后,
# 再次遍历,当某个元素不在正确的位置时,就是要找的第一个缺失的正数,直接返回
for i in range(length):
if nums[i] != i + 1:
return i + 1
# 如果元素都在正确位置,那么缺失的就是 n+1(length+1)
return length + 1
42. 接雨水 (困难) (困难在思路吧)
class Solution(object):
def trap(self, height):
"""
:type height: List[int]
:rtype: int
"""
max_h = 0
max_h_index = 0
res = 0
#找到最高的柱子以及位置
for i in range(len(height)):
if height[i] >= max_h:
max_h = height[i]
max_h_index = i
#从最高位置向左查找
tmp = height[0]
for i in range(max_h_index):
if height[i] <= tmp:
res += (tmp - height[i])
else:
tmp = height[i]
#从最高位置向右查找
tmp = height[-1]
for j in reversed(range(max_h_index+1, len(height))):
if height[j] <= tmp:
res += (tmp - height[j])
else:
tmp = height[j]
return res
45. 跳跃游戏 II (不懂)
class Solution(object):
def jump(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if len(nums) == 1:
return 0
ans = 0
curDistance = 0
nextDistance = 0
for i in range(len(nums)):
nextDistance = max(i + nums[i], nextDistance)
if i == curDistance:
if curDistance != len(nums) - 1:
ans += 1
curDistance = nextDistance
if nextDistance >= len(nums) - 1:
break
return ans