LC 209 长度最小的子数组
寻找满足条件的最小长度子数组,考虑使用滑动窗口。for循环控制窗口的右边界,j指针初始化为0,指向窗口左边界。窗口中元素和大于target时,减去nums[j],j += 1,实现窗口的移动。
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
res = float('inf')
sum , j , n = 0 , 0 , len(nums)
for i in range(n):
sum += nums[i] #计算窗口中元素的和,拿去跟target比较
while sum >= target:
sum -= nums[j]
res = min(res , i - j + 1)
j += 1
if j == 0 and sum < target: #若窗口取到整个数组,都没tartget大,就return 0
return 0
return res
要注意判断 sum和target的大小时,得用while而不是if,后者只能判断一次,无法处理[1,1,1,100]这种极端情况。
LC 59 螺旋矩阵
懵逼的一道题,直接看讲解了。。。
矩阵的表示方法(例如要生成一个m行 * n列,全为零的矩阵):[ [0] * n for _ in range(m) ].
本题模拟螺旋矩阵的方法就是一圈一圈的生成,总共需要转 n // 2圈,模拟这个转圈的过程,一层一层的往里面填充数字即可。注意每一行生成时要遵守同一个规则:左闭右开(也可其他区间形式,具体情况具体分析),这样才保证不会乱。
注意,因为是从外到内逐层处理,因此for循环开始的数是随着层数变的,因此一开始就用top,bottom等等变量定义好,方便后续层数变化做改变
class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
res = [[0] * n for i in range(n)]
top , bottom ,left , right = 0 , n-1 , 0 , n-1
insert = 1
while top <= bottom and left <= right:
#从左到右,处理上边界
for i in range( left , right):
res[top][i] = insert
insert += 1
#从上到下,处理右边界
for i in range(top , bottom):
res[i][right] = insert
insert += 1
#从右到左,处理下边界
for i in range(right , left , -1):
res[bottom][i] = insert
insert += 1
#从下到上,处理左边界
for i in range(bottom , top , -1):
res[i][left] = insert
insert += 1
top += 1
bottom -= 1
left += 1
right -= 1
#提交的时候发现奇数的情况最中心的元素没处理,单独加一行判断AC了
if n % 2 == 1:
res[n//2][n//2] = n**2
return res
卡玛58 区间和
要求一个数组A的[a,b]区间内元素和,可以先写一个数组Pre,存储数组A从头开始的累加和,即P3=A[0]+A[1] +A[2]+A[3],若要求数组子区间1-3的元素和,用P3-P0即可。
def func():
n = int(input())
a = [0] * n
for i in range(n):
a[i] = int(input())
pre = [0] * n
data = 0
for i in range(n):
data += a[i]
pre[i] = data
while True:
try:
ls = input().split(' ')
start = int(ls[0])
end = int(ls[1])
if start == 0:
sum = pre[end]
print(sum)
else:
sum = pre[end] - pre[start-1]
print(sum)
except:
break
func()
注意因为涉及到Pre[start-1]这种写法,要单独讨论一下区间左端点为0的情况,不然产生负数。
本题一开始用暴力法,发现超时了,原因是有长度特别长的数组,有m个子区间要求,总复杂度为O(m×n),而利用前缀和的思想,生成pre数组O(n),查询的复杂度仅为O(1),避免了超时。
卡玛44 开发商购买土地
思路:
先按题意生成土地价值矩阵,之后就有两种切分方式:横着或竖着。竖着切的话,我们可以构造一个前缀和数组,表示前i列土地价值之和。之后,假设A公司分到的是第一列土地,那么B公司的土地价值就是总价值减掉A的土地价值,要求两家公司价值差,那么就用土地总价值减掉两倍的A公司土地价值即可。
下为代码,写的有点繁琐,第一次写这种题,连矩阵怎么构造都花了半天时间,无语凝噎ing。。并且感觉这个题想到使用前缀和也不是很容易,反正我没想到。。。
def func():
data= input().split(' ')
m , n = int(data[1]) , int(data[0])
array = [[0]*m for _ in range(n)]
for i in range(n):
nums = input().split(' ')
for j in range(m):
array[i][j] = int(nums[j])
#横着切分
pre_row = [0] * n
sum = 0
for i in range(n):
for j in range(m):
sum += array[i][j]
pre_row[i] = sum
dif_row = float('inf')
for a in range(n):
dif_row = min(dif_row , abs(pre_row[n-1] - pre_row[a]*2))
#竖着切分
pre_column = [0] * m
sum_column = 0
for i in range(m):
for j in range(n):
sum_column += array[j][i]
pre_column[i] = sum_column
dif_column = float('inf')
for a in range(m):
dif_column = min(dif_column,abs(pre_column[m-1]-pre_column[a]*2))
print(min(dif_column,dif_row))
func()