栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【算法】剑指 Offer 专项突击版 Day4数组部分

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【算法】剑指 Offer 专项突击版 Day4数组部分

【算法】剑指 Offer 专项突击版 Day4数组部分

题目地址:https://leetcode-cn.com/study-plan/lcof/?progress=wgzvtig

目标:要点总结,分享思路
注:在合理的条件下仅采用理解起来最简单,用起来实用的代码实现

文章目录

【算法】剑指 Offer 专项突击版 Day4数组部分I 【中等】010. 和为 k 的子数组II 【中等】011. 0 和 1 个数相同的子数组II 【简单】012. 左右两边子数组的和相等II 【中等】013. 二维子矩阵的和


I 【中等】010. 和为 k 的子数组


难度:普通,要理解一下就好,笔者最开始对于题解给出的前缀和有点懵

要点:

思路:先按照暴力求解方法去理解题目,这道题可以构造前缀和数组presum[],这样presum[j]-presum[i]==k的双重循环就可以求解了,时间复杂度 O ( n 2 ) O(n^2) O(n2)优化思路1:连续子数组,可不可以用滑动窗口解决,尝试后不行,因为有负数。这样在滑动窗口中无法确定到底是改滑动左指针还是右指针使其满足窗口之和优化思路2:前缀和数组用哈希表存储,边构造边寻找

引用于刷穿剑指offer-Day07-数组III-010.和为k的子数组 前缀和的思路讲解)

个人解释(通俗解释,看懂上面的请跳过):在众多题解中这篇最简洁清晰,但个人还是不理解这里的哈希表是怎么存储到前缀和数组i和j的差值的。详细解释如下

class Solution:
    def subarraySum(self, nums: List[int], target: int) -> int:
        presum = 0 # 前缀和
        dic = {0:1}   # dic[key]:value,代表前缀和key出现的次数
        ans = 0    
        for num in nums:
            presum += num
            # presum - target 表示以起始点到当前num为终点的前缀和比target多出的距离
            # 如果在前面点中找到刚好等于这段距离的前缀,那么就找到了路径解
            ans += dic.get(presum-target,0) 
            # 
            dic[presum] = dic.get(presum,0) + 1 
        return ans 
II 【中等】011. 0 和 1 个数相同的子数组


难度:有上一题作为基础,该题转换思路后简单

要点:

思路:数组中仅有0和1,不做任何更改滑动窗口也无法使用,因为右指针右移多个0和左指针右移少个0的效果是相同的,无法确定指针移动方向即滑窗。那为什么不直接使用前缀和算法?(笔者当时自问自答的时候懵了) 同样若直接使用前缀和会出现该怎么确定前缀和等于多少时条件成立重点:将0换成-1就可以使用前缀和了,这样只要前缀和为0就满足条件了,题目转换为前缀和为0的最长子数组。那更改后能用滑动窗口了吗,不能,即使全部改为正数,满足滑窗滑动要求,但是滑窗内的数字之和为多少才能满足条件呢?

class Solution:
    def findMaxLength(self, nums: List[int]) -> int:
        ans = 0
        dic = {0:-1} # 当前缀和等于0时,说明已经满足要求,直接i+1即可
        presum = 0
        for i,num in enumerate(nums):
            if not num:num=-1 # 0转-1
            presum += num     
            # 这里用else才对哈希表赋值可以保证仅更新最早的点,这样得到的长度最大
            # 同时这道题如果变种为求子数组长度最小在这里调整无条件字典赋值即可
            if presum in dic: 
                ans = max(ans,i-dic.get(presum))
            else:
                dic[presum] = i
        return ans
II 【简单】012. 左右两边子数组的和相等


难度:简单,前缀和问题

要点:

思路:引自官方题解

class Solution:
    def pivotIndex(self, nums: List[int]) -> int:
        sums   = sum(nums)
        presum = 0
        for i,num in enumerate(nums):
            leftSum  = presum
            rightSum = sums-leftSum-num
            if leftSum == rightSum:
                return i
            presum += num
        return -1
II 【中等】013. 二维子矩阵的和


难度:

要点:

思路:引用于
图解前缀和,思路简明,注释全
因此本题就变成了如何求二维矩阵的前缀和矩阵(个人理解有点模板题的味儿)

# Your NumMatrix object will be instantiated and called as such:
# obj = NumMatrix(matrix)
# param_1 = obj.sumRegion(row1,col1,row2,col2)

class NumMatrix:

    def __init__(self, matrix: List[List[int]]):
        rows,cols = len(matrix),len(matrix[0]) if matrix else 0
        sums = [[0] * (cols+1) for _ in range(rows+1)]
        for i in range(rows):     # y轴向下
            for j in range(cols): # x轴向右 
            	# 求二维矩阵的前缀和
                sums[i+1][j+1] = sums[i][j+1] + sums[i+1][j] - sums[i][j] + matrix[i][j]
        self.sums = sums

    def sumRegion(self, row1: int, col1: int, row2: int, col2: int) -> int:
        _sums = self.sums

        return _sums[row2 + 1][col2 + 1] - _sums[row1][col2 + 1] - _sums[row2 + 1][col1] + _sums[row1][col1]
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/743592.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号