LeetCode 数组题

LeetCode 数组题

268. 缺失数字

题目描述: 从一个包含 0到n 的 n-1 个数的序列nums中,找出缺失的那个数。要求线性时间复杂度,仅使用额外常数空间。

思路1: 生成一个长度加1,元素全为-1的数组a,将nums中的元素作为索引给a赋值,最后元素为-1的索引即为nums缺失的元素。但是这种做法应该不满足额外常数空间的要求。

Python代码:

class Solution(object):
    def missingNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        a = [-1] * (len(nums)+1)
        for i in range(len(nums)):
            a[nums[i]] = i
        
        for i in range(len(a)):
            if a[i] == -1:
                return i

思路2: 借鉴评论里的一种解题思路,巧妙地利用了“ 从0到n”这一条件与数组元素的和的关系。看来“找到”某个元素不一定非要挨个去找。

Python代码:

class Solution(object):
    def missingNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums)
        sum1 = n*(n+1) / 2
        sum2 = sum(nums)
        
        return sum1-sum2

283. 移动0

题目描述: 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

思路1: 把遇到的0元素与最近的非0元素互换位置。

Python代码:

class Solution(object):
    def moveZeroes(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        i, j = 0, 1
        
        while j < len(nums):
            if nums[j] != 0 and nums[i] == 0:
                nums[i], nums[j] = nums[j], nums[i]
            if nums[i] != 0:
                i += 1
            j += 1

思路2: 觉得思路1比较简单,于是找找有没有惊喜的解题方式,看到一种差不多,但是更简洁的解题方法。就是两个指针i,j,当指针i碰到非0元素就与j交换元素,然后i,j均向前移动一位;如果i遇到的是0元素,则i向前移动一位。
这样的做法保证的是,如果刚开始是非0元素,则i,j会同时移动且指向同一个元素,不会使非0元素的位置替换;如果刚开始就为0元素,则j指向了0元素,而i继续往前找到非0元素与j进行交换。所以在遍历过程中,要么i,j处在同一位置一起向前,要么i在前j在后,中间由0隔开且j指向0元素。因此交换i,j就可以完成非0元素前移,相应的0元素后移。
本来比较简明的方法,好像说得有点麻烦,多画画草稿更好理解。

Python代码:

class Solution(object):
    def moveZeroes(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        j = 0
        
        for i in range(len(nums)):
            if nums[i] != 0:
                nums[i], nums[j] = nums[j], nums[i]
                j += 1

414. 第三大的数

题目描述: 给定一个非空数组,返回此数组中第三大的数值。如果该数组的数值小于三个,则返回数组中最大的数。要求算法时间复杂度必须是O(n)。

思路1: 本来想通过遍历和判断在一个新的数组中insert()当前的数,但是时间复杂度度好像不满足O(n)。所以改为通过遍历和判断为3个变量赋值。

Python代码:

class Solution(object):
    def thirdMax(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n1 = n2 = n3 = -float('inf')
        for num in nums:
            if num > n1:
                n3 = n2
                n2 = n1
                n1 = num
            if n2 < num < n1:
                n3 = n2
                n2 = num
            if n3 < num < n2:
                n3 = num
        
        if n3 > -float('inf'):
            return n3
        else:
            return n1

思路2: 感觉思路1比较老实,寻找参考思路。

287. 寻找重复数组

题目描述: 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间,其中至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。

题目要求: 不能改变数组;只能使用O(1)的空间;时间复杂度小于O(n2)。

思路1: 利用快慢指针,参考博文
理解快慢指针。主要就是,把nums数组看做链表,如果快慢指针相遇则说明链表有环,因为如果没有环,慢指针是追不上快指针的。
根据自己的理解画了如下的图示,帮助理解。
步骤1:先将数组转换成列表
在这里插入图片描述
步骤2:移动快慢指针,慢指针一次前进一个结点,快指针一次前进两个结点,直到相遇。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
步骤3:看列表的话,快慢指针已经指向相同的位置和相同的元素,但是实际遍历数组时只是遍历到了同一个位置,并没有找到两个相同的元素。所以第二个循环要在环内以相同的速度移动快慢指针,直到找到相同元素(我也理解不了为什么这样就能找到,画草稿理解吧)。
Python代码:

class Solution(object):
    def findDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        slow = nums[0]
        fast = nums[nums[0]]

        while slow != fast:
            slow = nums[slow]
            fast = nums[nums[fast]]
        
        fast = 0
        while nums[slow] != nums[fast]:
            slow = nums[slow]
            fast = nums[fast]
        
        return nums[slow]

560. 和为k的子数组

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

思路1: 果真太太太菜,除了暴力解题想不出别的方法了。于是学习到的解题思路:利用前缀和和哈希表。

  • 前缀和: 从下标为0的数到当前位置的数的连续和. 比如[1, 2, 3]的前缀和是[1, 3, 6]; [-1, -1]的前缀和是[-1, -2].
  • 哈希表: 类似于python的字典

于是求到某一个位置的前缀和之后,可以通过两种方法判断到当前位置的连续子数组中有多少个的和为k了:(1) 当前前缀和是否为k;(2) 当前前缀和减去前面已求出的前缀和的值是否为k(表明中间的子数组和为k)

Python代码:

class Solution(object):
    def subarraySum(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
        count = 0
        hushMap = {}

        acc = 0
        for num in nums:
            acc += num
            if acc == k:
                count += 1

            if (acc-k) in hushMap:
                count += hushMap[acc-k]

            if acc in hushMap:
                hushMap[acc] += 1
            else:
                hushMap[acc] = 1

        return count
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值