代码随想录算法训练营第二天| 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II ,总结

977.有序数组的平方

题目链接:977.有序数组的平方
思路:双指针法

def two_pointer(nums: List[int]) -> List[int]:
    """双指针法"""
    new_nums = [0] * len(nums)

    hp = 0  # 头指针
    rp = len(nums) - 1 # 尾指针
    
    cnt = 0 # 元素计数
    while hp <= rp:

        hp_square = nums[hp] ** 2
        rp_square = nums[rp] ** 2
        if hp_square >= rp_square:
            new_nums[-cnt-1] = hp_square
            hp+=1
        else:
            new_nums[-cnt-1] = rp_square
            rp-=1
        cnt +=1
    return new_nums

209.长度最小的子数组

题目链接:209.长度最小的子数组
思路:暴力解法(时间复杂度O(n^2))

def brute_force(target: int, nums: List[int]) -> int:
    """暴力解法"""
    res = 10 ** 5 + 1

    for i in range(len(nums)):
        t_res = 0
        val = 0

        for j in range(i, len(nums)):
            t_res += 1
            val += nums[j]

            if val >= target:
                res = min(res, t_res)
                break

    if res == 10 ** 5 + 1:
        res = 0

    return res

思路:滑动窗口(时间复杂度O(n))

问:一开始没明白为什么复杂度是O(n)?
答:看滑动窗口,每个元素只进窗口一次,和出窗口一次,一个元素就被操作两次。

def slide_window(target: int, nums: List[int]) -> int:
    """滑动窗口"""
    
    res = 10 ** 5 + 1
    
    sums = 0
    i = 0
    for j, val in enumerate(nums):    
        sums += val

        while(sums >= target):
            res = min(res, j - i + 1)
            sums -= nums[i]
            i += 1
    
    if res == 10 ** 5 + 1:
        res = 0

    return res

59.螺旋矩阵II

题目链接:59.螺旋矩阵II
思路:将问题分解为多个圆圈的直走一步和旋转问题。

def rotate_90(base_vector: Tuple[int, int]):
	"""
	旋转90°
	"""
    x, y = base_vector
    return (y, -x)


def go_ahead(coordinate: Tuple[int, int], base_vector: Tuple[int, int]):
	"""
	直走1格
	"""
    co_x, co_y = coordinate
    base_x, base_y = base_vector
    return co_x + base_x, co_y + base_y

def one_layer_loop(res: List[List[int]], src: Tuple[int, int], border_length: int, start_num: int):
	"""
	循环一圈
	"""

    # 起始坐标
    i, j = src

    if border_length == 0:
        res[-j][i] = start_num

    else:
        # 一开始向右走
        base_vector = (1, 0)

        count = 0
        for num in range(start_num, start_num + (border_length + 1) ** 2 - (border_length - 1) ** 2):
            res[-j][i] = num

            if count == border_length:
                base_vector = rotate_90(base_vector)
                count = 0
            i, j = go_ahead((i, j), base_vector)
            count += 1
    return i, j

def generate_matrix(self, n: int) -> List[List[int]]:
	"""
	串起来
	"""
	res = []
	for i in range(n):
	    res.append([0] * n)
	
	i, j = 0, 0
	cnt = 1
	while n > 0:
	    i, j = one_layer_loop(res, (i, j), n - 1, cnt)
	    i += 1
	    j -= 1
	    cnt += (n ** 2 - (n - 2) ** 2)
	    n -= 2
	
	return res

总结

数组理论

数组,是一片连续的地址空间,删除元素只能依靠写入覆盖,而无法释放部分内存。

拓展问题:Python 中的 list 是基于顺序存储的线性表吗?是如何实现可存放多种数据类型、且可扩容的?

二分法

保持边界设置的方法一致,要么是“左闭右闭”要么是“左闭右开”。

双指针法

27. 移除元素 中,快指针用于读取,满指针用于写入;
977.有序数组的平方 中,两个指针分别朝不同的方向遍历;
209.长度最小的子数组 中,两个指针共同构成了滑动窗口;

不变量?

这个有点玄学,还没理解透。
704. 二分查找 中,不变量是边界设置方法;
977.有序数组的平方 中,不变量是朝着平方下降的方向;
59.螺旋矩阵II 中,不变量是前进一步和拐弯这些小步骤;
感觉,不变量是将问题分解后的产物。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值