剑指Offer and Leetcode刷题总结之一:数组

目录

 

一. 利用交换,值交换到对应的index上

剑指03:数组中重复的数字(找到任意一个重复数即可)

Leetcode41:缺失的第一个正数

Leetcode442:数组中重复的数据

Leetcode448:找到所有数组中消失的数字

剑指04:二维数组中的查找

剑指29:顺时针打印矩阵

剑指53-I:在排序数组中查找数字

剑指53-II:0到n-1中缺失的数字

Leetcode61:扑克牌中的顺子

剑指66:构建乘积数组

Leetcode73:矩阵置零(参考题解)

Leetcode88:合并两个有序数组

Leetcode215:数组中的第K个最大元素(TopK问题;至少三种解法)!重点!

Leetcode349:两个数组的交集||Hashmap

Leetcode350:两个数组的交集II||双指针

Leetcode560:和为K的子数组(参考题解)


一. 利用交换,值交换到对应的index上

剑指03:数组中重复的数字(找到任意一个重复数即可)

-->进阶版:Leetcode442:数组中重复的数据(找到所有的重复数)

-->微调版:Leetcode448:找到所有数组中消失的数字(重复数占领的index就是消失的数)

题目:找出数组中重复的数字。在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

示例:Input:[2, 3, 1, 0, 2, 5, 3];Output:2 or 3

基本思路:1. 暴力 2.hashmap 3.交换

class Solution03(object):
    """
    在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
    """
    
    """
    方法1:暴力解法
    最差时间复杂度为O(n*n); 最好时间复杂度O(1)
    空间复杂度为O(1);
    """
    def findRepeatNums(self, nums):
        for i in range(len(nums)):
            for j in range(i + 1, len(nums)):
                if nums[i] == nums[j]:
                    return nums[i]
    
    """
    方法2.1:利用hashmap思想,构造字典(!巨坑!不必先构造一遍字典再来查找, 因为字典中的key是不会重复的, 构造字典的时候遇到重复的element时, 执行dict[value] = key, 会将原来相同value所对应的key给替换掉; )
    所以可以边构造字典边判断;
    最好时间复杂度为O(1), 最差时间复杂度为O(n), 平均复杂度也为O(n); search时间复杂度为O(1)
    最好空间复杂度为O(1), 最差空间复杂度为O(n), 平均空间复杂度为O(n)
    """
    def findRepeatNums_02(self, nums):
        dict = {}
        for key, value in enumerate(nums):
            if dict.get(value) is not None:
                return nums[dict.get(value)]
            else:
                dict[value] = key
    
    """
    方法2.2:依然利用hashmap但是更加简洁的版本
    不用care列表下标; 只需要care它的值;
    """
    def findRepeatNums_03(self, nums):
        dict = {}
        for i in nums:
            if i in dict:
                return i
            else:
                dict[i] = 0 #这里可以赋任意值, 目的是存入i即可;
        return -1
    
    """
    方法3:排序再遍历
    时间复杂度为O(nlogn): 排序阶段复杂度为O(nlogn), 遍历阶段时间复杂度为O(n)
    空间复杂度为O(1)
    """
    def findRepeatNums_04(self, nums):
        nums.sort()
        pre = nums[0]
        for i in range(1, len(nums)):
            if pre == nums[i]:
                return pre
            else: # pre != nums[i]
                pre = nums[i]
        return -1
    
    """
    方法4.1:交换--时间和空间复杂度最优
    注意题目中关键信息:nums中的数字都在 0~n-1 的范围内,也就是说可以将nums中的element一一放入跟它的值相等的下标位置; 
    归位过程中,发现待归位elements与被归位上的element相等则返回, otherwise交换;
    时间复杂度为:O(n)
    空间复杂度为:O(1)
    """
    def findRepeateNums_05(self, nums):
        for i in range(len(nums)):
            element = nums[i]
            if i != nums[i] and nums[element] == nums[i]:
                return nums[i]
            else:
                nums[i], nums[element] = nums[element], nums[i]
        return -1
    """
    方法4.2:交换
    找到第一个i != nums[i]即为重复元素;
    """
    def findRepeatNumber(self, nums):
        if not nums: return None
        for i in range(len(nums)):
            while nums[i] != nums[nums[i]]:
                self.swap(nums, i, nums[i])
                # nums[i], nums[nums[i]] = nums[nums[i]], nums[i] # i固定不变,将i位置上的元素不断送到对应的位置上去。一直换到i位置满足i=nums[i]为止;
        for i in range(len(nums)):
            if i != nums[i]:
                return nums[i]

    def swap(self, nums, i, j):
        tmp = nums[i]
        nums[i] = nums[j]
        nums[j] = tmp

Leetcode41:缺失的第一个正数

题目:给你一个未排序的整数数组,请你找出其中没有出现的最小的正整数。

示例:Input:[3, 4, -1, 1];Output:2

基本思路:index1, 2, 3, 4...对应着放数字1, 2, 3, 4...。再遍历一遍,不相等则返回该数字;

2个注意点

1. 交换的时候用while,因为交换一次的话,只能保证换过去的element是去到正确的位置,换过来的又是不对的element,所以持续交换,直到换到正确的对应的element或者是out of size的element为止<这里指的是负数>;

2. 元素交换这里要用swap,原来的直接交换行不通 

class Solution(object):
    def firstMissingPositive(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums: return 1
        size = len(nums)
        for i in range(size):
            while nums[i] > 0 and nums[i] <= size and nums[i] != nums[nums[i]-1]: # 用while而不用if,因为持续需要换,换回来的可能也不满足条件
                # nums[nums[i] - 1], nums[i] = nums[i], nums[nums[i] - 1]         # 只能用swap,而不能直接交换是因为赋值先后问题;
                self.swap(nums, i, nums[i]-1)
        for i in range(size):
            if i + 1 != nums[i]:
                return i + 1
        return size + 1          # 如果正好一一对应,则返回size + 1 (eg. [1, 2, 3])
        
    def swap(self, nums, i, j):
        tmp = nums[i]
        nums[i] = nums[j]
        nums[j] = tmp

Leetcode442:数组中重复的数据

题目:给定一个整数数组 a,其中1 ≤ a[i] ≤ n (n为数组长度), 其中有些元素出现两次而其他元素出现一次。找到所有出现两次的元素。你可以不用到任何额外空间并在O(n)时间复杂度内解决这个问题吗?

示例:[4,3,2,7,8,2,3,1] --> [2, 3]

基本思路:第一次遍历,对于每一个i,连续交换至无法交换为止;第二次遍历,不满足i+1 == num[i]即是重复元素

class Solution(object):
    def findDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        if not nums: return None
        size = len(nums)
        ans = []
        for i in range(size):
            while nums[i] != nums[nums[i] - 1]:
                self.swap(nums, i, nums[i] - 1)
        for i in range(size):
            if i + 1 != nums[i]:
                ans.append(nums[i])
        return ans

    def swap(self, nums, i, j):
        tmp = nums[i]
        nums[i] = nums[j]
        nums[j] = tmp

Leetcode448:找到所有数组中消失的数字

题目:给定一个范围在  1 ≤ a[i] ≤ n ( n = 数组大小 ) 的 整型数组,数组中的元素一些出现了两次,另一些只出现一次。找到所有在 [1, n] 范围之间没有出现在数组中的数字。您能在不使用额外空间且时间复杂度为O(n)的情况下完成这个任务吗? 你可以假定返回的数组不算在额外空间内。

基本思路:跟上一题完全一样,上一题输出重复元素,这一题输出被重复元素占掉位置的消失元素;

class Solution(object):
    def findDisappearedNumbers(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        size = len(nums)
        ans = []
        for i in range(size):
            while nums[i] != nums[nums[i] - 1]:
                self.swap(nums, i, nums[i] - 1)
        for i in range(size):
            if i + 1 != nums[i]:
                ans.append(i + 1)
        return ans

    def swap(self, nums, i, j):
        tmp = nums[i]
        nums[i] = nums[j]
        nums[j] = tmp

剑指04:二维数组中的查找

题目:在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

基本思路:因为是有序的,所以可以从右上角开始,复杂度降为O(m+n);

class Solution04(object):
    """
    在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
    """
    """
    方法1:暴力解法(遍历一遍)
    时间复杂度O(n*m)--最好O(1),最差O(n*m)
    空间复杂度O(1)
    """
    def findNumberIn2DArray(self, matrix, target):
        if len(matrix) == 0: return False
        n, m = len(matrix), len(matrix[0])
        for i in range(n):
            for j in range(m):
                if matrix[i][j] == target:
                    return True
        return False
    
    """
    方法2:引入标志数(题目的特殊性,由左到右,从上到下都是递增的,所有右上角位置以及左下角位置为特殊位置)
    时间复杂度O(m+n)
    空间复杂度O(1)
    """
    def findNumberIn2DArray_02(self, matrix, target):
        if len(matrix) == 0: return False
        n, m = len(matrix), len(matrix[0])
        for i in range(n):
            if m - 1 >= 0 and matrix[i][m-1] == target:   # 添加m - 1 >= 0是为了解决test [[]] 这种matrix时,index报错的情况;改进:用while loop 
                return True
            if m - 1 >= 0 and matrix[i][-1] > target:
                for j in range(m-1):
                    if matrix[i][j] == target: 
                        return True
        return False
    
    """
    方法2:while loop -- 方法2中添加 m - 1 >= 0是为了解决test case中 [[]] 这种matrix时,index报错的情况;改进:用while loop
    while loop一定会先设置好循环算子
    """
    def findNumberIn2DArray_03(self, matrix, target):
        i, j = 0, len(matrix[0]) - 1
        while(i <= len(matrix) - 1 and j >= 0):
            if matrix[i][j] > target:
                j -= 1
            elif matrix[i][j] < target:
                i += 1
            else:
                return True
        return False

剑指29:顺时针打印矩阵

class Solution29(object):
    """
    玩技巧题,知道有这一种技巧就可以了!
    """
    def spiralOrder(self, matrix):
        if not matrix: return []
        l, r, t, b = 0, len(matrix[0]) - 1, 0, len(matrix) - 1
        ans = []
        while True:
            for i in range(l, r + 1): # from left to right
                ans.append(matrix[t][i])
            t += 1
            if t > b: break
            for i in range(t, b + 1): # from top to bottom
                ans.append(matrix[i][r])
            r -= 1
            if r < l: break
            for i in range(r, l - 1, -1 ): # from right to left 
                ans.append(matrix[b][i])
            b -= 1
            if b < t: break
            for i in range(b, t - 1, -1): # from bottom to top
                ans.append(matrix[i][l])
            l += 1
            if l > r: break
        return ans

剑指53-I:在排序数组中查找数字

题目:统计一个数字在排序数组中出现的次数。

示例:nums[5, 7, 7, 8, 8, 10] target =8 --> output: 2

基本思路:1. 遍历即可;复杂度O(n);2. 二分法;复杂度O(logn) -- 先找到第一个target的位置,再往后遍历有几个target;

class Solution53(object):
    """
    方法1:暴力统计
    时间复杂度:O(n)
    空间复杂度:O(1)
    """
    def search(self, nums, target):
        ans = 0
        for i in range(len(nums)):
            if nums[i] == target:
                ans += 1
        return ans
    
    """
    方法2暴力改进版:因为是sorted list,搜索到该target之后, 就停止往后遍历了
    时间复杂度:最好O(1), 最坏O(n), 平均O(n)
    空间复杂度: O(1)
    """
    def search_02(self, nums, target):
        ans = 0
        for i in range(len(nums)):
            if nums[i] == target:
                j = i                                      # 因为是排序数组,找到跟target相等element之后就不用再往后遍历了
                while j < len(nums) and nums[j] == target: # 用j遍历之后几个==target的elements;
                    j += 1
                    ans += 1
                return ans
        return ans

    """
    方法3:先找到target值的位置,再继续往后遍历
    """
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        # 2020/05/28
        if not nums: return 0
        size = len(nums)
        lo, hi = 0, size - 1
        while lo < hi:
            mid = (lo + hi) >> 1
            if nums[mid] < target:
                lo = mid + 1
            else:
                hi = mid
        ans = 0
        if nums[lo] == target:
             ans = 1
             while lo + 1 < size and nums[lo + 1] == nums[lo]:
                 ans += 1
                 lo += 1
        return ans

剑指53-II:0到n-1中缺失的数字

题目:一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。

示例:[0, 1, 2, 3, 4, 5, 6, 7, 9] --> 8

基本思路:标准的二分法;需要考虑到[0, 1, 2]这种case,循环会在lo=size-1处跳出

class Solution53(object):
    """
    方法1:暴力法逐一比较
    时间复杂度:最好是O(1),最坏是O(n),平均是O(n)
    空间复杂度:O(1)
    """
    def missingNumber(self, nums):
        if nums == [0]: return 1
        i = 0
        while i <= len(nums) - 1:
            if nums[i] != i:
                return i
            else:
                i += 1
        return i 
    """
    方法2:二分法查找
    时间复杂度为O(logn)
    空间复杂度:O(1)
    """
    def missingNumber(self, nums):
        if not nums: return 0
        size = len(nums)
        lo, hi = 0, size - 1
        while lo < hi:
            mid = (lo + hi) >> 1
            if nums[mid] == mid:
                lo = mid + 1
            else:
                hi = mid
        if nums[lo] == lo: return lo + 1 # 考虑到[0, 1, 2]这种case,循环会在lo=size-1处跳出
        return lo

Leetcode61:扑克牌中的顺子

题目:从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。

示例输入: [0,0,1,2,5] 输出: True

基本思路:除了0之外(大小王)没有重复,且同时满足最大值-最小值<5即可;

class Solution:
    def isStraight(self, nums: List[int]) -> bool:
        nums.sort() # 排序
        joker = 0
        for i in range(4):
            if nums[i] == 0: 
                joker += 1
                continue
            if nums[i] == nums[i+1]: return False
        return nums[4] - nums[joker] < 5  # 最大值-最小值<5

剑指66:构建乘积数组

题目:给定一个数组 A[0,1,…,n-1],请构建一个数组 B[0,1,…,n-1],其中 B 中的元素 B[i]=A[0]×A[1]×…×A[i-1]×A[i+1]×…×A[n-1]。不能使用除法。

示例输入: [1,2,3,4,5] 输出: [120,60,40,30,24]

基本思路:动态规划,分别维护一个左边所有数字的积和右边所有数字的乘积;

class Solution:
    def constructArr(self, a: List[int]) -> List[int]:
        if not a: return []
        if len(a) == 1: return [1]
        size = len(a)
        left = [1 for _ in range(size)]
        right = [1 for _ in range(size)]
        left[0], right[-1] = 1, 1
        for i in range(1, size):
            left[i] = a[i-1] * left[i-1]
        for j in range(size-2, -1, -1):
            right[j] = a[j+1] * right[j+1]
        ans = []
        for i in range(size):
            ans.append(left[i] * right[i])
        return ans

Leetcode73:矩阵置零参考题解

题目:给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地算法

基本思路

Leetcode88:合并两个有序数组

题目:给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 使 nums1 成为一个有序数组。说明:初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。

示例:输入:nums1 = [1,2,3,0,0,0], m = 3;nums2 = [2,5,6], n = 3;输出: [1,2,2,3,5,6]

基本思路:3个指针;从后往前遍历,p1是m尾部,p2是n尾部,p是nums1最尾部;完成遍历之后,如果p2中依然有值,全部插到nums1的头部;

时间复杂度:O(m+n)

class Solution(object):
    def merge(self, nums1, m, nums2, n):
        """
        :type nums1: List[int]
        :type m: int
        :type nums2: List[int]
        :type n: int
        :rtype: None Do not return anything, modify nums1 in-place instead.
        """
        p1, p2 = m - 1, n - 1
        p = m + n - 1
        while p1 >= 0 and p2 >= 0:    # 从后往前遍历,p1是m尾部,p2是n尾部,p是nums1最尾部
            if nums1[p1] <= nums2[p2]:
                nums1[p] = nums2[p2]
                p -= 1
                p2 -= 1
            else:
                nums1[p1], nums1[p] = nums1[p], nums1[p1]
                p -= 1
                p1 -= 1
        if p2 >= 0:                  # 完成遍历之后,如果p2中依然有值,全部插到nums1的头部
            for i in range(p2+1):
                nums1[i] = nums2[i]

Leetcode215:数组中的第K个最大元素(TopK问题;至少三种解法)!重点!

基本思路:

1. 排序:时间复杂度O(nlogn) + 空间复杂度O(1)

2. 堆排序:时间复杂度O(n*logk) + 空间复杂度O(k)

3. partition思想:注意要随机选择pivot--利用randint(lo, hi),再交换lo and randint(lo, hi)的元素

时间复杂度O(n): 假设每次都可以均分 n + n/2 + n/4 + n/8 + ... + 1,最后结果为n*(1 + 1/2 + 1/4 + 1/8 +...),后者不会超过2; 

最差的情况O(n*n),每次都选到最小或者最大元素,n + n-1 + ....1

空间复杂度O(1)

堆排序参考:

堆排序Python实现 AND 【Kick Algorithm】十大排序算法及其Python实现 AND 白话经典算法系列之七 堆与堆排序(清楚明白)

class Solution(object):
    """
    方法1:排序
    时间复杂度为O(nlogn))
    空间复杂度为O(1)
    """
    def findKthLargest(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
        nums.sort()
        return nums[-k]

    """
    方法2.1:堆排序--小顶堆(自己实现版本)
    时间复杂度:O(nlogk):n个
    空间复杂度:O(k) -- k为题中的k,需要维护的堆的nodes数量
    """
    def findKthLargest(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
        def buildheap(nums):
            size = len(nums)
            for i in range(size//2 - 1, -1, -1):
                heapfy(nums, size, i)

        def heapfy(nums, size, i):
            left = 2 * i + 1  # left node
            right = 2 * i + 2 # right node
            tmp = i
            if left < size and nums[tmp] > nums[left]:
                tmp = left
            if right < size and nums[tmp] > nums[right]:
                tmp = right
            if i != tmp:
                nums[i], nums[tmp] = nums[tmp], nums[i]
                heapfy(nums, size, tmp)

        """
        引申:堆排序 -- 对数组中所有元素进行排序
        """
        def heapsort(nums):
            buildheap(nums)  # 小顶堆建堆完成
            size = len(nums)
            for i in range(size - 1, -1, -1):
                nums[i], nums[0] = nums[0], nums[i]
                heapfy(nums, i, 0)
            return nums
   
        kheap = nums[0:k]  # 取前k个元素
        size = len(nums)   
        buildheap(kheap)   # 维护一个小顶堆
        for i in range(k, size):     # 之后的元素逐个比较
            if nums[i] > kheap[0]:   # 如果大于堆顶元素,则进入堆,然后进行堆化操作
                kheap[0] = nums[i]
                heapfy(kheap, k, 0)
            else:
                continue
        return kheap[0]              # 最终堆顶元素即为所求的值


    """
    方法2.2:堆排序--内置函数,一步到位
    内置函数
    """
    def findKthLargest(self, nums, k):
        from heapq import heappush,heapreplace
        # 使用堆的nlargest(n,iter)返回前n个最大的数,倒序排练
        return nlargest(k,nums)[-1]3

    """
    方法2.3:堆排序--内置函数,借助heappu and heapreplace
    时间复杂度:O(nlogk) 遍历所有元素O(n),heapfy过程O(logk)
    空间复杂度:O(k) -- k为题中的k,需要维护的堆的nodes数量
    """
    def findKthLargest(self, nums, k):
        from heapq import heappush,heapreplace       
        # 使用小顶堆
        heap = []
        for i in range(len(nums)):
            if i < k:
                heappush(heap,nums[i]) # 元素为满时,建堆过程
            else:                      # 元素已满时,heapfy操作
                if nums[i] > heap[0]:
                    m = heapreplace(heap,nums[i])
        return heap[0]

    """
    方法3:partition方法
    时间复杂度O(n): 假设每次都可以均分 n + n/2 + n/4 + n/8 + ... + 1,最后结果为n*(1 + 1/2 + 1/4 + 1/8 +...),后者不会超过2; 
                   最差的情况O(n*n),每次都选到最小或者最大元素,n + n-1 + ....1
    空间复杂度O(1)
    """
    def findKthLargest(self, nums, k):
        from random import randint
        def partition(nums, lo, hi):
            i, j = lo, hi + 1     # 这里要注意,i, j表示首尾index,基于lo,hi来设置,而不能用0, len(nums),后续这都是要变的
            ind = randint(lo, hi) # !重点!为了防止复杂度退化到O(n*n),随机选一个pivot,再跟lo位置处的元素置换即可
            p = nums[ind]
            nums[ind], nums[lo] = nums[lo], nums[ind]
            while i + 1 < j:
                if nums[i+1] <= p:
                    nums[i+1], nums[i] = nums[i], nums[i+1]
                    i += 1
                else:
                    nums[i+1], nums[j-1] = nums[j-1], nums[i+1]
                    j -= 1
            return i

        k = len(nums) - k # 需要找到的index(eg.find the largest, then len(nums) - 1)
        lo = 0
        hi = len(nums) - 1
        while lo < hi:
            pivot = partition(nums, lo, hi)
            if pivot < k:
                lo = pivot + 1
            elif pivot > k:
                hi = pivot - 1
            else:
                break
        return nums[k]

Leetcode349:两个数组的交集||Hashmap

题目:给定两个数组,编写一个函数来计算它们的交集。说明:输出结果中的每个元素一定是唯一的;不考虑输出结果顺序;

示例:nums1 = [1, 2, 2, 1], nums2 = [2, 2] --> output: [2]

基本思路:两次遍历即可:第一次建dict,第二次查找(结果集不重复)

class Solution(object):
    """
    方法1:hashmap,对第一个数组建hashmap,O(m),遍历第二个数组查找O(n)
    时间复杂度O(m+n)
    """
    def intersection(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        dict = {}
        ans = []
        for i in nums1:
            dict[i] = ''
        for j in nums2:
            if dict.get(j) != None:
                ans.append(j)
        return list(set(ans))

Leetcode350:两个数组的交集II||双指针

题目:给定两个数组,编写一个函数来计算它们的交集。说明:输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。不考虑输出结果的顺序。

示例:nums1 = [4, 9, 5];nums2 = [9, 4, 9, 8, 4]

基本思路:先对两个数组排序,再对两个数组分别维护一个指针,遍历即可(可重复)

class Solution(object):
    def intersect(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        nums1.sort()
        nums2.sort()
        size1, size2 = len(nums1), len(nums2)
        i, j = 0, 0
        ans = []
        while i < size1 and j < size2:
            if nums1[i] == nums2[j]:
                ans.append(nums1[i])
                i += 1
                j += 1    
            elif nums1[i] > nums2[j]:
                j += 1
            else:
                i += 1
        return ans

Leetcode560:和为K的子数组参考题解

题目:给定一个整数数组和一个整数 k,你需要找到该数组中和为 的连续的子数组的个数。

示例输入:nums = [1,1,1], k = 2 输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。

基本思路:切忌用双指针;这里可能会有负数,且无序;

时间复杂度:O(n);空间复杂度:O(n);

class Solution(object):
    """
    方法:前缀和
    """
    def subarraySum(self, nums, k):
        hash = {0:1}
        sum = 0
        count = 0
        for i in range(len(nums)):
            sum += nums[i]
            if (sum -k ) in hash:
                count += hash[sum - k]
            if sum in hash:
                hash[sum] += 1
            else:
                hash[sum] = 1
        return count

    """
    错误方法(没考虑到有负数):双指针 -- 如果有负数,用双指针就是错的解法
    """
    def subarraySum(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
        if not nums: return 0
        i, j = 0, 0
        ans = [] # 如果需要输出具体有哪些可以用这个
        cnt = 0
        sum = nums[0]
        size = len(nums)
        while i < size and j < size:
            if sum == k:
                cnt += 1
                ans.append(nums[i:j+1])
                i += 1
                j += 1
                if j < size:
                    sum = sum + nums[j] - nums[i-1]
            elif sum < k:
                j += 1
                if j < size:
                    sum += nums[j]
            else:
                i += 1
                sum -= nums[i-1]
        return cnt

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值