Python算法题集_和为K的子数组

本文为Python算法题集之一的代码示例

题目560:和为K的子数组

说明:给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数

子数组是数组中元素的连续非空序列。

示例 1:

输入:nums = [1,1,1], k = 2
输出:2

示例 2:

输入:nums = [1,2,3], k = 3
输出:2

提示:

  • 1 <= nums.length <= 2 * 104
  • -1000 <= nums[i] <= 1000
  • -107 <= k <= 107

- 问题分析

  1. 本题为求子数组和为K,子数组为非空的连续元素

  2. 主要的计算为两个,1是元素求和,而是比较和与K

  3. 基本的遍历为双层循环,从第一个元素开始,计算从此元素开始有多少次和为K,所以基本的时间算法复杂度为(On2)

- 优化思路

  1. 优化的思路,一是减少计算次数,二是减少检索次数和提升检索效率

  2. 标准的优化思路,前缀和【从第1个元素累加到第n个元素的和,称为第n个前缀和】,只要出现2个前缀和的差=k,则这两个下标之间的数组即满足要求

  3. 进一步优化,第n个元素前缀和为isum_n,则1至n-1如果有x个前缀和为k-isum_n,则第n个元素可以在1至n-1之间形成x个和为k的子数组

  4. 以上优化都是考虑前缀和差,因此对于nums只有一个元素的情况要单独进行处理


  1. 标准版【双循环】,毫无疑问,直接超时

    注意:

    import CheckFuncPerf as cfp
    
    def subarraySum_base(nums, k):
        result=0
        for iIdx in range(len(nums)):
            iSum = nums[iIdx]
            if iSum == k:
                result += 1
            for jIdx in range(iIdx+1, len(nums)):
                iSum += nums[jIdx]
                if iSum == k:
                    result += 1
        return result
    
    testcase_big1 = open(r'testcase/hot10_big1.txt', mode='r', encoding='utf-8').read().replace('[', '').replace(']', '')
    testcase_big1 = testcase_big1.split(',')
    nums = [int(x) for x in testcase_big1]
    k = 714
    
    result = cfp.getTimeMemoryStr(subarraySum_base, nums, k)
    print(result['msg'], '执行结果 = {}'.format(result['result']))
    # 运行结果
    函数 subarraySum_base 的运行时间为 10591.62 ms;内存使用量为 4.00 KB 执行结果 = 40
    
  2. 优化版【提前计算前缀和,直接计算前缀和之差】,有想法,然并卵,超时依旧

    import CheckFuncPerf as cfp
    
    def subarraySum_ext1(nums, k):
        if len(nums)==1:
            if nums[0] == k:
                return 1
            else:
                return 0
        isumpref=[0] * len(nums)
        iSum = 0
        for iIdx in range(len(nums)):
            iSum += nums[iIdx]
            isumpref[iIdx] = iSum
        result=0
        for iIdx in range(len(nums)):
            if iIdx==0 and nums[iIdx] == k:
                result += 1
            if isumpref[iIdx] == k:
                result += 1
            for jIdx in range(iIdx+1, len(nums)):
                if isumpref[jIdx]-isumpref[iIdx] == k:
                    result += 1
        return result
    
    testcase_big1 = open(r'testcase/hot10_big1.txt', mode='r', encoding='utf-8').read().replace('[', '').replace(']', '')
    testcase_big1 = testcase_big1.split(',')
    nums = [int(x) for x in testcase_big1]
    k = 714
    
    result = cfp.getTimeMemoryStr(subarraySum_ext1, nums, k)
    print(result['msg'], '执行结果 = {}'.format(result['result']))
    # 运行结果
    函数 subarraySum_ext1 的运行时间为 10508.87 ms;内存使用量为 732.00 KB 执行结果 = 40
    
  3. 优化改进版【单层循环,将到第n个元素的所有前缀和的计数存入字典】,优化所见略同,仅超越68%在这里插入图片描述

    import CheckFuncPerf as cfp
    
    def subarraySum_ext2(nums, k):
        dictsumpref = {}
        isum, iresult = 0, 0
        for num in nums:
            isum += num
            if isum == k:
                iresult += 1
            if isum - k in dictsumpref:
                iresult += dictsumpref[isum - k]
            dictsumpref[isum] = dictsumpref.get(isum, 0) + 1
        return iresult
    
    testcase_big1 = open(r'testcase/hot10_big1.txt', mode='r', encoding='utf-8').read().replace('[', '').replace(']', '')
    testcase_big1 = testcase_big1.split(',')
    nums = [int(x) for x in testcase_big1]
    k = 714
    
    result = cfp.getTimeMemoryStr(subarraySum_ext2, nums, k)
    print(result['msg'], '执行结果 = {}'.format(result['result']))
    # 运行结果
    函数 subarraySum_ext2 的运行时间为 3.99 ms;内存使用量为 160.00 KB 执行结果 = 40
    

    一日练,一日功,一日不练十日空

    may the odds be ever in your favor ~

  • 18
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
求二维数组的最大数组的和,可以使用动态规划算法。 具体思路是,先将二维数组每一行作为一个一维数组,对每一行进行求最大数组和,得到一个一维数组。然后对这个一维数组再次进行求最大数组和,得到最终的最大数组和。 以下是使用 Python 实现的代码: ```python def max_subarray_sum(arr): """ 求一维数组的最大数组和 """ max_sum = arr[0] cur_sum = arr[0] for i in range(1, len(arr)): cur_sum = max(cur_sum + arr[i], arr[i]) max_sum = max(max_sum, cur_sum) return max_sum def max_submatrix_sum(matrix): """ 求二维数组的最大数组和 """ rows = len(matrix) cols = len(matrix[0]) max_sum = float('-inf') for i in range(rows): # 将每一行作为一个一维数组,求最大数组和 temp = [0] * cols for j in range(i, rows): for k in range(cols): temp[k] += matrix[j][k] # 对一维数组求最大数组和 cur_sum = max_subarray_sum(temp) max_sum = max(max_sum, cur_sum) return max_sum ``` 其中,`max_subarray_sum()` 函数用来求一维数组的最大数组和,`max_submatrix_sum()` 函数用来求二维数组的最大数组和。 我们可以先将每一行作为一个一维数组,对每一行进行求最大数组和,得到一个一维数组。然后对这个一维数组再次进行求最大数组和,得到最终的最大数组和。 接下来,我们可以使用以下代码测试一下: ```python matrix = [ [1, -2, 3, 0], [-1, 5, -2, 2], [3, 0, 0, -1] ] print(max_submatrix_sum(matrix)) # 输出 8 ``` 输出结果为 8,符合预期。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长孤秋落

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值