哈希表的应用
242. 有效的字母异位词
给定两个字符串 s
和 t
,编写一个函数来判断 t
是否是 s
的字母异位词。
注意: 若 s
和 t
**中每个字符出现的次数都相同,则称 s
和 t
**互为字母异位词。
示例 1:
输入: s = "anagram", t = "nagaram"
输出: true
示例 2:
输入: s = "rat", t = "car"
输出: false
提示:
1 <= s.length, t.length <= 5 * 104
s
和t
仅包含小写字母
进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?
解题思路:
这个题用字典来实现比较简单
- 将字符串 s 遍历 ,将其中的每一个字符作为key 出现的次数作为value 放到字典中
- 将字符串 t 遍历 , 将其中的每一个字符作为key 去前面的字典中查找 ,如果有找到 则 value - 1 ,当value == 0 的时候 将这个key 从字典中移除
- 最后检查 字典 中 是否还存在 key 如果存在 则不是 异位 词 ,如果不存在 则是 异位词
实现代码:
func isAnagram(_ s: String, _ t: String) -> Bool {
// 首先判断 字符串的长度是否一致
guard s.count == t.count else {return false}
// 创建一个 Map
var map = [Character:Int]()
// 遍历第一个字符串 并将其放到 字典Map 中
for c in s {
if map[c] == nil {
map[c] = 1
} else {
map[c]! += 1
}
}
// 遍历第二个字符串 如果Map中不存在 直接返回 false
// 如果Map 中个数 == 1 表面就一个 ,那么将这个key 移除
// 如果Map 中个数 > 1 ,Value -= 1
for c in t {
if map[c] == nil {
return false
} else {
if map[c] == 1 {
map.removeValue(forKey: c)
} else {
map[c]! -= 1
}
}
}
// 判断 map 是否为 empty
return map.isEmpty ? true : false
}
349. 两个数组的交集
给定两个数组 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
解题思路
这个题用字典来实现比较简单 先遍历第一个数组 将其中的元素都放到字典中 、不需要统计它的个数 遍历第二个数组,如果字典中存在,则将字典中的value+=1 遍历这个字典,如果字典中的 key 对应的value 大于0 则表示这个是相交的,将它放到数组中返回即可
实现代码
func intersection(_ nums1: [Int], _ nums2: [Int]) -> [Int] {
// 创建Map
var map = [Int:Int]()
// 创建 res 用来存储结果
var res = [Int]()
// 遍历nums1 将里面的数 添加到Map里面
for num in nums1 {
if map[num] == nil {
map[num] = 0
}
}
// 遍历nums2 ,如果 Map 里面已经存在了 则将 num 放到结果数组里面 同时 移除Map 里面的这个key
for num in nums2 {
if map[num] != nil {
res.append(num)
map.removeValue(forKey: num)
}
}
return res
}
202. 快乐数
编写一个算法来判断一个数 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 <= 231 - 1
解题思路
算法分为两部分,我们需要设计和编写代码。
给一个数字 nnn,它的下一个数字是什么? 按照一系列的数字来判断我们是否进入了一个循环。 第 1 部分我们按照题目的要求做数位分离,求平方和。
第 2 部分可以使用哈希集合完成。每次生成链中的下一个数字时,我们都会检查它是否已经在哈希集合中。
如果它不在哈希集合中,我们应该添加它。 如果它在哈希集合中,这意味着我们处于一个循环中,因此应该返回 false
实现代码
// 将n 这个数的每一位的 平方 求和的 方法
func getSum (_ n:Int) -> Int {
var sum = 0
var num = n
while (num != 0) {
sum += (num % 10) * (num % 10)
num /= 10
}
return sum
}
func isHappy(_ n: Int) -> Bool {
// 用来保存这个和是否出现过
var map = [Int:Int]()
var sum = n
while true {
sum = getSum(sum)
if sum == 1 {
return true
}
// 出现过 会出现死循环 直接返回false
if map[sum] != nil {
return false
}
// 记录到 哈希表中
map[sum] = 0
}
}
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
- 只会存在一个有效答案
进阶: 你可以想出一个时间复杂度小于 O(n2)
的算法吗?
解题思路
使用 map 来实现 首先遍历一次数组 将数组 的值作为key 将它在数组中的位置作为value 存储在Map 中
遍历数组 ,看Map 中是否存在 target - value 这样的值 ,如果存在 说明存在 这样的两个数 满足两数之和
注意 这里 这里选中的数不能是 遍历 的数本身
实现代码
func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
// 创建Map 用来存储数组中的 num 以及 它所在的位置
var map = [Int:Int]()
for i in 0..<nums.count {
map[nums[i]] = i
}
// 遍历数组 ,看Map 中是否存在 target - value 这样的值 ,如果存在 说明存在 这样的两个数 满足两数之和
for i in 0..<nums.count {
if map[target-nums[i]] != nil && i != map[target-nums[i]] {
return [i, map[target-nums[i]]!]
}
}
return [Int]()
}