考虑的基本数据结构
第一类: 查找有无–set
元素’a’是否存在,通常用set:集合
set只存储键,而不需要对应其相应的值。
set中的键不允许重复
第二类: 查找对应关系(键值对应)–dict
元素’a’出现了几次:dict–>字典
dict中的键不允许重复
第三类: 改变映射关系–map
通过将原有序列的关系映射统一表示为其他
算法应用
LeetCode 349 Intersection Of Two Arrays 1
题目描述
给定两个数组nums,求两个数组的公共元素。
如nums1 = [1,2,2,1],nums2 = [2,2]
结果为[2]
结果中每个元素只能出现一次
出现的顺序可以是任意的
分析实现
由于每个元素只出现一次,因此不需要关注每个元素出现的次数,用set的数据结构就可以了。记录元
素的有和无。
把nums1记录为set,判断nums2的元素是否在set中,是的话,就放在一个公共的set中,最后公共的
set就是我们要的结果。
代码如下
class Solution:
def intersection(self, nums1: List[int], numList[int]) -> List[int]:
nums1 = set(nums1)
return set([i for i in nums2 if i in nums1])
也可以通过set的内置方法来实现,直接求set的交集:
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
set1 = set(nums1)
set2 = set(nums2)
return set2 & set1
LeetCode 350 Intersection Of Two Arrays 2
题目描述
给定两个数组nums,求两个数组的交集。
如nums1=[1,2,2,1],nums=[2,2
结果为[2,2]
出现的顺序可以是任意的
分析实现
元素出现的次数有用,那么对于存储次数就是有意义的,所以选择数据结构时,就应该选择dict的结
构,通过字典的比较来判断;
记录每个元素的同时要记录这个元素的频次。
记录num1的字典,遍历nums2,比较nums1的字典的nums的key是否大于零,从而进行判断。
代码如下:
class Solution:
def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
from collections import Counter
nums1_dict = Counter(nums1)
res = []
for num in nums2:
if nums1_dict[num] > 0:
# 说明找到了一个元素即在num1也在nums2
res.append(num)
nums1_dict[num] -= 1
return res
LeetCode 202 Happy number
题目描述
编写一个算法来判断一个数是不是“快乐数”。
一个“快乐数”定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复
这个过程直到这个数变为 1,也可能是无限循环但始终变不到 1。如果可以变为 1,那么这个数就是快乐数。
示例:
输入: 19
输出: true
解释:
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1
分析实现
这道题目思路很明显,当n不等于1时就循环,每次循环时,将其最后一位到第一位的数依次平方求和,
比较求和是否为1。
难点在于,什么时候跳出循环?
开始笔者的思路是,循环个100次,还没得出结果就false,但是小学在算无限循环小数时有一个特征,
就是当除的数中,和之前历史的得到的数有重合时,这时就是无限循环小数。
那么这里也可以按此判断,因为只需要判断有或无,不需要记录次数,故用set的数据结构。每次对求
和的数进行append,当新一次求和的值存在于set中时,就return false.
代码如下:
class Solution:
def isHappy(self, n: int) -> bool:
already = set()
while n != 1:
sum = 0
while n > 0:
# 取n的最后一位数
tmp = n % 10
sum += tmp ** 2
# 将n的最后一位截掉
n //= 10
# 如果求的和在过程中出现过
if sum in already:
return False
else:
already.add(sum)
n = sum
return True