leetcode每日一题3.1|刷题打卡

137 阅读3分钟

leetcode303. 区域和检索 - 数组不可变(easy)

题目描述:

给定一个整数数组  nums,求出数组从索引 i 到 j(i ≤ j)范围内元素的总和,包含 i、j 两点。

实现 NumArray 类:

  • NumArray(int[] nums) 使用数组 nums 初始化对象
  • int sumRange(int i, int j) 返回数组 nums 从索引 i 到 j(i ≤ j)范围内元素的总和,包含 i、j 两点(也就是 sum(nums[i], nums[i + 1], ... , nums[j]))

代码模版(swift)

class NumArray {

    init(_ nums: [Int]) {

    }
    
    func sumRange(_ i: Int, _ j: Int) -> Int {

    }
}

解法1(直接求和)

直观来看,我们可以维护一个数组存储输入的数组,每次计算范围和时遍历求和即可

class NumArray {
    var numArr: [Int]!  
    init(_ nums: [Int]) {
        numArr = nums
    }
    
    func sumRange(_ i: Int, _ j: Int) -> Int {
        var sum = 0
        for x in i...j {
            sum += numArr[x]
        }
        return sum
    }
}
  • 空间复杂度:O(1) 未使用额外的存储空间

  • 时间复杂度:初始化O(1),区间求和O(N*n),N表示求和次数,n表示数组长度,每次求和均需要一趟线性遍历

运行结果:

运行耗时2916ms,与其他swift代码相比明显耗时多了不少,考虑优化代码以降低时间复杂度

解法2(前缀和)

解法1直接求和为何执行时间长,分析时间复杂度后推知耗时操作在区间求和操作上,多次区间求和导致运行时间变长,是否可以考虑将耗时操作转移到代码初始化中?

思路:

用一个数组sumArr记录每个数字从0相加到对应到当前下标的和,比如sumArr[4]表示0-4的和,则指定i,j区间区间和为sumArr[j] - sumArr[i - 1],考虑到i - 1可能会小于0,可以创建一个长度为N+1的数组,用sumArr[j + 1] - sumArr[i]表示区间。代码如下

class NumArray {
    var sumArr: [Int]! //用于存储0——(当前下标-1)的和
    
    init(_ nums: [Int]) {
        sumArr = [Int](repeating: 0, count: nums.count + 1) //创建一个长度为N+1的数组
        guard nums.count > 0 else {
            return //空数组保护
        }
        for i in 1...nums.count {
            sumArr[i] = sumArr[i - 1] + nums[i - 1] //保存0——(i-1)的和
        }
    }
    
    func sumRange(_ i: Int, _ j: Int) -> Int {
         guard sumArr.count > 1 else {
            return 0 //空数组保护
        }
        return sumArr[j + 1] - sumArr[i]
    }
}
为何可以用sumArr[j + 1] - sumArr[i]表示区间和?sumArr[j + 1]表示nums从0——j的和, sumArr[i]表示nums从0——(i-1)的和,两者相减去除了0——(i-1)的和,剩下的就是区间i——j的和
  • 空间复杂度:O(n) 使用了数组长度空间保存数组和

  • 时间复杂度:初始化O(n),初始时需要遍历一趟存储前缀和,区间求和O(1)

执行结果:

可得这是一种更好的解题方法。

目前的算法题主要是看中时间复杂度,算法执行耗时越少越好。而如今大部分机器内存相当充裕,基本都会考虑用空间换取时间的方式来优化执行时间。

结语

这是本人第一次在掘金发布文章,响应掘金三月活动。本人从去年7月份开始算法刷题以来,每天刷一道每日一题。目前题数在300左右。希望各位希望提升技术的同僚共勉。

本文正在参与「掘金 2021 春招闯关活动」, 点击查看活动详情