给定一个整数数组,判断是否存在重复元素。
如果任何值在数组中出现至少两次,函数返回 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。
给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k。
这里仍然是使用哈希表,也就是字典完成题目,但是我们这次改变键值对的配置方法,将数字设置成key,而将数字对应的数组下标设置为value。然后:
下面粘贴代码:
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 对象