leetcode刷题笔记-数组3

存在重复元素

给定一个整数数组,判断是否存在重复元素。
如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。

这里的解答用到了投机取巧的一种方法,使用set函数:

class Solution:
    def containsDuplicate(self, nums: List[int]) -> bool:
        n = len(nums)
        c = len(set(nums))
        if n>c:
            return True
        else:
            return False

介绍:
set() 函数创建一个无序不重复元素集,可进行关系测试,删除重复数据,还可以计算交集、差集、并集等。
我使用了append,insert等方法,但不知道为什么一直说超时,难道这样的时间复杂度是O(n2)?

下面说说传统方法,即哈希表的python实现:

class Solution:
    def containsDuplicate(self, nums: List[int]) -> bool:
        dic = {}
        for i in nums:
            if dic.get(i):
                return True
            dic[i]=1
        return False

这里可以看到,实际我们就是使用了字典,字典正是使用哈希表实现的。
我们这里使用了get()方法:
介绍:Python 字典 get() 函数返回指定键的值,如果值不在字典中返回默认值。
返回:返回指定键的值,如果值不在字典中返回默认值 None。

存在重复元素 II

给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k。

这里仍然是使用哈希表,也就是字典完成题目,但是我们这次改变键值对的配置方法,将数字设置成key,而将数字对应的数组下标设置为value。然后:

  1. 每次检查新的数字是否存在于这个字典中,若存在,则将当前的数组下标与字典中相应的key对应的value相减,结果为cha。
  2. 比较cha与k的大小,如果大于,就更新这个key的value,如果小于则直接返回True。

下面粘贴代码:

class Solution:
    def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool:
        n =len(nums)
        dic={}
        for i in range(n):
            if nums[i] not in dic:
                dic[nums[i]]=i
                continue
            if nums[i] in dic:
                cha=i-dic[nums[i]]
                if cha<=k:
                    return True
                if cha>k:
                    dic[nums[i]]=i
        return False

这里发现一个神奇的用法,就是if nums[i] not in dic,原来字典也可以使用not in这类语句。

快乐数

一个“快乐数”定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是无限循环但始终变不到 1。如果可以变为 1,那么这个数就是快乐数。

这个做法使用的是hashset,首先定义一个函数用于更新n,然后每次更新n都检查n是否在已经分配的一个集合中,如果在,就把n加进集合中,最后检查n是否为1。

class Solution:
    def isHappy(self, n: int) -> bool:
        def getnext(n):
            total_sum=0
            while n>0:
                n,yu =divmod(n,10)
                total_sum += yu**2
            return total_sum
        
        seen = set()
        while n !=1 and n not in seen:
            seen.add(n)
            n=getnext(n)

        return n == 1 

这里学到一个nb的写法用于计算一个数所有数字的平方和,那就是:

sum([int(i)**2 for i in str(n)])

合并两个有序数组

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

这个题目我初始想到的就是利用sort和del,但是这样资源消耗比较多,下面是代码:

class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        """
        Do not return anything, modify nums1 in-place instead.
        """
        for i in range(n):
            nums1.insert(m,nums2[i])
            
        del nums1[m+n:]
        nums1.sort()
        

感觉这样太投机取巧并且太简单,于是参考了一下官方的双指针法,利用数组本来排好序的特性,创建一个新的数组在后面添加元素:

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: void Do not return anything, modify nums1 in-place instead.
        """
        # Make a copy of nums1.
        nums1_copy = nums1[:m] 
        nums1[:] = []

        # Two get pointers for nums1_copy and nums2.
        p1 = 0 
        p2 = 0
        
        # Compare elements from nums1_copy and nums2
        # and add the smallest one into nums1.
        while p1 < m and p2 < n: 
            if nums1_copy[p1] < nums2[p2]: 
                nums1.append(nums1_copy[p1])
                p1 += 1
            else:
                nums1.append(nums2[p2])
                p2 += 1

        # if there are still elements to add
        if p1 < m: 
            nums1[p1 + p2:] = nums1_copy[p1:]
        if p2 < n:
            nums1[p1 + p2:] = nums2[p2:]

但这里有两行很让人迷惑,即:

nums1_copy = nums1[:m]
nums1[:] = []

这里学习到了一个python的语言特性,关于数组的复制,下面的例子说明了nums1和nums1[:]在被赋值时的区别,也正是为什么官方这么进行赋值的原因:

# 对象在内存中的地址与id 一一对应,可以使用 id() 查看并判断是否是同一个对象

nums1 = [1,2,4,0,0] 
print(id(nums1)) # 140125129895880

A = [1,2,3,4,5]
print(id(A))     # 140125129856640

nums1[:] = A
print(id(nums1))) # 140125129895880,  仍是原 list 对象, 只不过这一 list 对象的值发生了改变

# 若不执行 nums1[:] = A, 而执行
nums1 = A
print(id(nums1))  # 140125129856640, 不再是之前的那个 list 对象

你可能感兴趣的:(leetcode)