题号217
方法一:
对数组进行排序,然后遍历数组,遇到等于前一个元素的就返回,定义一个pre记录前一个元素的值
class Solution:
def containsDuplicate(self, nums: List[int]) -> bool:
if len(nums) == 0 :
return False
nums.sort()
pre= nums[0]
for i in range (1,len(nums)):
if pre== nums[i]:
return True
else:
pre = nums[i]
return False
方法二:
看到重复元素就可以想到hash表的键值对,建立一个空的字典,然后遍历数组,把数组中的元素依次记入,用数组的值作key,元素出现的次数作为value
class Solution:
def containsDuplicate(self, nums: List[int]) -> bool:
dict = {} #简历空字典
for num in nums: #遍历数组中的值
if num not in dict: #如果该值在字典中不存在
dict[num]=1 #存储该值和他次数的键值对
else: #如果存在
dict[num] = dict.get(num)+1 #更新值为次数+1
for value in dict.values(): #遍历字典中的value
if value>1: #遇到值大于1的输出
return True
return False
题号49
题号560
涉及连续子数组问题时通常采用前缀和的思路。建立一个字典,key是前缀和,value是出现次数,查找和为K时直接找前缀和-K就可以得到结果
假如有数组[3,4,7,2,-3,1,4,2,1],计算它们的前缀和结果如第二行所示
根据它们的前缀和生成的dict内容如蓝框和箭头所示(绿箭头:当重复遇到前缀和为14的时候给键14的值加了一)
若K=7,sum-K的意思是:先把数组后面连续和为7的子数组[4,2,1]给抠掉了。然后在剩下的前部分数组中找sum-k这个值的组合,对应到这个例子的字典里是两个14,说明前面的数组中还有两个连续子数组的和为k。如果你不相信,我们就验证一下,[3,4],[7,2,-3,1]是不是都是k=7的连续子数组?
所以这个题的原理就是计算整个数组的前缀和
每个前缀和通过一个字典统计它们得到结果的次数
给一个K值后,先所有和减掉K,相当于划去倒数部分满足K的连续数组
查询剩余部分数组的前缀和满足sum-k的,就是前部分满足条件的数组个数
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
dict = {0:1}
sum = 0
count = 0
for i in range (len(nums)):
sum+=nums[i]
find = sum - k
if find in dict:
count+=dict[find]
if sum in dict:
dict[sum]+=1
else:
dict[sum] =1
return count
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
dict = {} #创建一个空字典
sum = 0 #前缀和初始为0
count = 0 #统计和为K的子数组出现次数
for i in range (len(nums)):
sum+=nums[i] #计算前缀和
find = sum - k #通过前缀和与K的差值找和为K的连续数组
if sum==k: #特殊情况,当sum=k时,find=0,字典中次数最低为1,就会找不到这个数组
count+=1
if find in dict: #如果在字典中
count+=dict[find] #前缀和为find的前面数中有对应数值和连续子数组
#sum-k还减掉了后半段和为K的数组,所以要count+
if sum in dict:
dict[sum]+=1
else:
dict[sum] =1
return count
关于前缀和:
sum[i ] = sum[i-1] + a[i]如果想查询区间,就可以两个端点的查询:区间[l,r]的和就等于sum[r] - sum[l-1]
比如查询区间[2,4],sum[4] - sum[2-1] = 15-6=0,左区间-1是为了把左端点也算进去,不信你手动算一下不减1左端点就也被减掉了,算的反而是[3,4]区间的值。