代码随想录算法训练营第二天 | 209.长度最小的子数组、 59.螺旋矩阵II、区间和、 开发商购买土地

209.长度最小的子数组

双指针维护滑动窗口的起始和终止位置,实际是一个左闭右闭区间,新元素进入窗口查看窗口的累计和,如果超过了target,把起始位置的元素一个一个踢掉看看是否能得到更小的窗口,while循环条件每次成立,记录一下结果看看是否更小。

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        slow = 0
        res = float('inf')
        total = 0
        for fast in range(len(nums)):
            total += nums[fast]
            while total >= target:
                res = min(res, fast - slow + 1)
                total -= nums[slow]
                slow += 1
        return 0 if res == float('inf') else res

 59.螺旋矩阵II

这题我记得一刷的时候花了好几个小时想了一个比较巧妙的方法,但是现在已经想不起来了... 还是老老实实模拟螺旋吧。

主要思路就是一层一层剥洋葱,用layer去表示当前到多少层了, 然后每层再四个循环填数即可。

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        res = [[0 for _ in range(n)] for j in range(n)]
        cnt = 1

        for layer in range((n + 1) // 2):
            for ptr in range(layer, n - layer):
                res[layer][ptr] = cnt
                cnt += 1
            for ptr in range(layer + 1, n - layer):
                res[ptr][n - layer - 1] = cnt
                cnt += 1
            for ptr in range(n - layer - 2, layer - 1, -1):
                res[n - layer - 1][ptr] = cnt
                cnt += 1
            for ptr in range(n - layer - 2, layer, -1):
                res[ptr][layer] = cnt
                cnt += 1
        return res

这里和Carl的方法有一点出入,Carl建议我们注意左闭右开还是左闭右闭,但是其实第一个循环直接填完整行可以省去判断奇偶的逻辑。

区间和(第九期模拟笔试)

这题也是比较直观的,使用前缀和的差值表示区间和。

这里忘记了acm模式写法,加深记忆。

import sys

def rangeSum(nums, a, b):
    return nums[b + 1] - nums[a]
    
def prefixSum(nums, n):
    res = [0]
    for i in range(n):
        res.append(nums[i] + res[i])
    return res
    
if __name__ == "__main__":
    n = int(sys.stdin.readline())
    nums = []
    for i in range(n):
        nums.append(int(sys.stdin.readline()))
    prefix = prefixSum(nums, n)
    
    for line in sys.stdin:
        a, b = map(int, line.strip().split())
        print(rangeSum(prefix, a, b))

 开发商购买土地

压缩成列和数组或者行和数组,使用sweep line扫描一遍,找最佳分割线。

acm格式还是不熟...

import sys

def minDiff(n, m, grid):
    total_sum = sum(sum(row) for row in grid)
    
    left_sum, right_sum = 0, total_sum
    min_diff = float('inf')
    for col in range(m):
        col_sum = sum(grid[row][col] for row in range(n))
        left_sum += col_sum
        right_sum -= col_sum
        min_diff = min(min_diff, abs(left_sum - right_sum))
    
    top_sum, bottom_sum = 0, total_sum
    for row in range(n):
        row_sum = sum(grid[row])
        top_sum += row_sum
        bottom_sum -= row_sum
        min_diff = min(min_diff, abs(top_sum - bottom_sum))
    
    return min_diff

if __name__ == "__main__":
    input = sys.stdin.read
    data = input().split()
    
    n, m = int(data[0]), int(data[1])
    grid = []
    index = 2
    for _ in range(n):
        grid.append(list(map(int, data[index:index + m])))
        index += m
    
    print(minDiff(n, m, grid))

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值