一、有效的字母异同词
1.1 题目
给定两个字符串 s
和 t
,编写一个函数来判断 t
是否是 s
的字母异位词。
注意:若 s
和 t
中每个字符出现的次数都相同,则称 s
和 t
互为字母异位词。
示例 1:
输入: s = "anagram", t = "nagaram" 输出: true
示例 2:
输入: s = "rat", t = "car" 输出: false
提示: s
和 t
仅包含小写字母
1.2 题目链接
1.3 解题思路和想法
解题思路:借用哈希数组记录字符串中字符的情况,一个用增加数组值的方式记录,另一个用减少数组值的方式记录。若最终存在数组值不为0的情况,则表明二者的字母构成不同。
想法:
(1)最初想用字典来存储字符串的构成,卡了一下判断的条件(对python不是很熟悉)。
(2)感觉上述解题思路中因为题目限制了数值的大小----->用数组构造哈希会很简单,并且利用差值来判断的方式很巧妙。
(3)这道题如果使用库函数的话,或许有更简单的方式,但我以后并不会以python为主要编程语言,只是近期在学习机器学习而已,所以此处并未写出这类解法。
1.4 代码
1.4.1 数组--->哈希
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
# 用哈希表记录字符串的字母情况,对应关系:'x' 的下标---> 'x' - 'a',用数组的值存储字母的情况
words = [0] * 26
# c++中可直接用 i-'a',python需用 ord(i)-ord('a')
for i in s:
index = ord(i)-ord('a')
words[index] += 1
# 若在 s 和 t 中同时出现,则在统计 t 时-1,便于后续统计二者差距
for i in t:
index = ord(i)-ord('a')
words[index] -= 1
for i in range(26):
if words[i] != 0:
return False
return True
1.4.2 字典--->哈希
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
# 用字典构造两个哈希表
hash_s = dict()
hash_t = dict()
# 初始化最终结果为True
flag = True
# 通过遍历,用哈希表记录字符串内部构成
for i in s:
if not hash_s.get(i):
hash_s[i] = 1
else:
hash_s[i] += 1
for j in t:
if not hash_t.get(j):
hash_t[j] = 1
else:
hash_t[j] += 1
# 通过遍历,判断s中的,t是否有
for key in hash_s:
if not hash_t.get(key) or hash_t[key] != hash_s[key]:
return False
# 通过遍历,判断t中的,s是否有
for key in hash_t:
if not hash_s.get(key) or hash_t[key] != hash_s[key]:
return False
return True
二、两个数组的交集
2.1 题目
给定两个数组 nums1
和 nums2
,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。
示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2] 输出:[2]
示例 2:
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4] 输出:[9,4] 解释:[4,9] 也是可通过的
提示:
1 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 1000
2.2 题目链接
2.3 解题思路和想法
解题思路:
用数组/字典构建哈希表,若元素同时存在于两个哈希表中,则追加至结果中。
想法:
(1)首先想过用数组来实现哈希,且题目限制了数值的大小,但数值为1000,不是首选但简单。
(2)比较自然的会想到用字典来实现哈希。(为避免重复统计,及时更新原哈希表)
2.4 代码
2.4.1 数组--->哈希表
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
# 用数组构建两个哈希表
words1 = [0] * 1001
words2 = [0] * 1001
# 用来存储最终结果
res = []
length1 = len(nums1)
length2 = len(nums2)
# 用遍历记录两个数组的元素情况
for i in range(length1):
words1[nums1[i]] += 1
for j in range(length2):
words2[nums2[j]] += 1
# 判断元素是否同时出现在两个数组中
for k in range(1001):
if words1[k] and words2[k]:
res.append(k)
return res
2.4.2 字典--->哈希表
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
# 用字典构建存储列表内部情况的哈希表,用列表存储最终结果
hash = dict()
res = []
# 通过遍历的方式,用哈希表记录 nums1 中的构成
for i in nums1:
if not hash.get(i):
hash[i] = 1
# 在遍历 nums2 的过程中,判断 nums1 中是否也存在对应元素。若存在,则追加至res中,并更新哈希表(避免重复统计)
for j in nums2:
if hash.get(j):
res.append(j)
hash[j] = 0
return res
三、快乐数
3.1 题目
编写一个算法来判断一个数 n
是不是快乐数。
「快乐数」 定义为:
- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
- 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
- 如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n
是 快乐数 就返回 true
;不是,则返回 false
。
示例 1:
输入:n = 19 输出:true 解释: 12 + 92 = 82 82 + 22 = 68 62 + 82 = 100 12 + 02 + 02 = 1
示例 2:
输入:n = 2 输出:false
提示:
1 <= n <= 2^31 - 1
3.2 题目链接
3.3 解题思路和想法
解题思路:利用该数变换过程中的规律,只要变换过程中出现重复的数字且不为1,则不为快乐数。用字典构造哈希,用来快速判定当前数字是否已存在于哈希表中。
想法:刚看到题目的时候有点懵,心想这是数学题?没关注到题目给的提示-------“重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1”。
心得:当遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法了!!!
3.4 代码
class Solution:
# 算出当前数的各数位的平方和
def new(self,n:int) -> int:
sum = 0
while n > 0:
m = n % 10
sum += m ** 2
n = n // 10
return sum
def isHappy(self, n: int) -> bool:
# 如果int = 9999999999999,各位数的平方和为 1053 ,表明数不会越来越大
# 结合题中描述,如果不是快乐数,过程中数字会出现循环这一现象------>判断是否出现数字再现且数字不为1的情况
# 当遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法了。
# 初始化结果是True,只要后续出现数字重复且不为1的情况,则修改 flag
flag = True
# 用字典构建哈希
hash = dict()
# 目前的数字
cur = n
# 判断新生成的数是否重复且不为1
while cur != 1 :
if not hash.get(cur):
hash[cur] = 1
# 及时更新cur
cur = self.new(cur)
else:
flag = False
break
return flag
四、两数之和
4.1 题目
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9 输出:[0,1] 解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6 输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6 输出:[0,1]
提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
- 只会存在一个有效答案
4.2 题目链接
4.3 解题思路和想法
思解题路:在一堆数中快速判断某数是否存在----> 哈希法。用字典构造哈希表(以值为key,以索引为value),结合题中所给条件:(1)数不重复(2)每种输出只对应一个答案(3)下标为一对;通过一次遍历,先判断 target-x 是否存在于哈希表中(存在则终止循环,输出结果),否则将该数存入哈希表中。
想法:思考的过程比较顺畅,只是最初没想到只用一次遍历(没想着利用数是一对),并且在判断条件中 hash.get(target - value) 可能为零的情况下卡顿了一下。
4.4 代码
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
# 快速判断元素是否出现集合中 --> 哈希法
# 用字典构建哈希表
hash = dict()
# 初始化目的列表
res = []
# 先通过遍历,将所有数字加入到哈希表中(题设:数组中无重复数),并同时查找符合条件的下标
# (下标为一对,第一个没搜到,另一个若满足一定会被搜到,所以可以共用一趟遍历)
# 在得到当前数 x 的情况下,在哈希表中查找 target-x 是否存在
for index,value in enumerate(nums):
# 不能直接写 if hash.get(target - value): 因为可能获取的值的下标就是0
if target - value in hash:
res.append(index)
res.append(hash.get(target - value))
break
else:
# 应先判断,若不满足条件再加入,否则 当 target=6 ,value=3 时,会误搜索到当前数3的index
hash[value] = index
return res