学习网址:https://datawhalechina.github.io/leetcode-notes/#/ch03/index.md
'''
你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false 。
示例 1:
输入:nums = [1,2,3,1]
输出:true
示例 2:
输入:nums = [1,2,3,4]
输出:false
示例 3:
输入:nums = [1,1,1,3,3,4,3,2,4,2]
输出:true
'''
class Solution(object):
def containsDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
# 将数组转换为集合
num_set = set(nums)
# 比较集合的大小和原数组的大小
return len(num_set) < len(nums)
'''
给你一个整数数组 nums 和一个整数 k ,判断数组中是否存在两个 不同的索引 i 和 j ,满足 nums[i] == nums[j] 且 abs(i - j) <= k 。如果存在,返回 true ;否则,返回 false 。
示例 1:
输入:nums = [1,2,3,1], k = 3
输出:true
示例 2:
输入:nums = [1,0,1,1], k = 1
输出:true
示例 3:
输入:nums = [1,2,3,1,2,3], k = 2
输出:false
'''
class Solution(object):
def containsNearbyDuplicate(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: bool
"""
# 创建一个空的哈希表(字典),用于存储元素和它们的索引
num_indices = {}
# 遍历数组中的每个元素
for i, num in enumerate(nums):
# 检查元素是否已经在哈希表中
if num in num_indices and i - num_indices[num] <= k:
# 如果找到重复的元素,并且索引差小于等于k,返回True
return True
# 如果元素不在哈希表中,或者索引差大于k,更新哈希表中的索引
num_indices[num] = i
# 如果遍历完整个数组都没有找到满足条件的元素对,返回False
return False
'''
请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)
注意:
一个有效的数独(部分已被填充)不一定是可解的。
只需要根据以上规则,验证已经填入的数字是否有效即可。
空白格用 '.' 表示。
'''
class Solution(object):
def isValidSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: bool
"""
# 创建一个集合,用于存储每一行中出现的数字
rows = [set() for _ in range(9)]
# 创建一个集合,用于存储每一列中出现的数字
cols = [set() for _ in range(9)]
# 创建一个集合,用于存储每一个3x3九宫格中出现的数字
boxes = [[set() for _ in range(3)] for _ in range(3)]
# 遍历数独的每一个元素
for i in range(9):
for j in range(9):
num = board[i][j]
# 如果当前位置是空白格,则跳过
if num == '.':
continue
# 将数字转换为整数类型以便进行比较和存储
num = int(num)
# 计算当前数字所在的3x3九宫格的索引
box_i = i // 3
box_j = j // 3
# 检查行中是否有重复的数字
if num in rows[i]:
return False
rows[i].add(num)
# 检查列中是否有重复的数字
if num in cols[j]:
return False
cols[j].add(num)
# 检查3x3九宫格中是否有重复的数字
if num in boxes[box_i][box_j]:
return False
boxes[box_i][box_j].add(num)
# 如果没有发现重复的数字,则数独有效
return True
'''
给定两个数组 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
'''
class Solution(object):
def intersection(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: List[int]
"""
# 将数组nums1里的每一个数值映射到一个哈希表上
num_set = set(nums1)
# 初始化一个空集合,用于存储交集结果
intersection_set = set()
# 查询数值nums2里的数值是否在哈希表上,如果有则将该数值添加到交集集合中
for num in nums2:
if num in num_set:
intersection_set.add(num)
# 输出set转换为列表
return list(intersection_set)
'''给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。
示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]
示例 2:
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]
提示:
1 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 1000
'''
class Solution(object):
def intersect(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: List[int]
"""
# 对nums1和nums2进行排序
nums1.sort()
nums2.sort()
# 新的空列表用于存储交集
intersection = []
# 初始化两个列表的索引
i, j = 0, 0
# 使用双指针方法遍历两个列表
while i < len(nums1) and j < len(nums2):
if nums1[i] == nums2[j]:
# 如果找到相等的元素,则添加到交集列表中,并移动两个指针
intersection.append(nums1[i])
i += 1
j += 1
elif nums1[i] < nums2[j]:
# 如果nums1当前元素小于nums2当前元素,移动nums1的指针
i += 1
else:
# 如果nums1当前元素大于nums2当前元素,移动nums2的指针
j += 1
# 返回交集列表
return intersection
'''
不使用任何内建的哈希表库设计一个哈希映射(HashMap)。
实现 MyHashMap 类:
MyHashMap() 用空映射初始化对象
void put(int key, int value) 向 HashMap 插入一个键值对 (key, value) 。如果 key 已经存在于映射中,则更新其对应的值 value 。
int get(int key) 返回特定的 key 所映射的 value ;如果映射中不包含 key 的映射,返回 -1 。
void remove(key) 如果映射中存在 key 的映射,则移除 key 和它所对应的 value 。
示例:
输入:
["MyHashMap", "put", "put", "get", "get", "put", "get", "remove", "get"]
[[], [1, 1], [2, 2], [1], [3], [2, 1], [2], [2], [2]]
输出:
[null, null, null, 1, -1, null, 1, null, -1]
解释:
MyHashMap myHashMap = new MyHashMap();
myHashMap.put(1, 1); // myHashMap 现在为 [[1,1]]
myHashMap.put(2, 2); // myHashMap 现在为 [[1,1], [2,2]]
myHashMap.get(1); // 返回 1 ,myHashMap 现在为 [[1,1], [2,2]]
myHashMap.get(3); // 返回 -1(未找到),myHashMap 现在为 [[1,1], [2,2]]
myHashMap.put(2, 1); // myHashMap 现在为 [[1,1], [2,1]](更新已有的值)
myHashMap.get(2); // 返回 1 ,myHashMap 现在为 [[1,1], [2,1]]
myHashMap.remove(2); // 删除键为 2 的数据,myHashMap 现在为 [[1,1]]
myHashMap.get(2); // 返回 -1(未找到),myHashMap 现在为 [[1,1]]
提示:
0 <= key, value <= 106
最多调用 104 次 put、get 和 remove 方法
'''
class MyHashMap:
# 初始化哈希映射类
def __init__(self):
self.buckets = 1009 # 设置桶的数量为质数以减少哈希冲突
self.table = [[] for _ in range(self.buckets)] # 创建一个列表的列表作为哈希表,每个桶是一个空列表
# 哈希函数,将键转换为桶的索引
def hash(self, key):
return key % self.buckets # 使用取模运算符计算键的哈希值
# 插入键值对到哈希映射中
def put(self, key, value):
hashkey = self.hash(key) # 计算键的哈希值
for item in self.table[hashkey]: # 在对应的桶中查找是否存在相同的键
if item[0] == key: # 如果找到相同的键,更新其值
item[1] = value
return
self.table[hashkey].append([key, value]) # 如果没有找到相同的键,将键值对添加到桶中
# 从哈希映射中获取指定键的值
def get(self, key):
hashkey = self.hash(key) # 计算键的哈希值
for item in self.table[hashkey]: # 在对应的桶中查找指定的键
if item[0] == key: # 如果找到指定的键,返回其值
return item[1]
return -1 # 如果没有找到指定的键,返回-1表示不存在
# 从哈希映射中移除指定的键及其对应的值
def remove(self, key):
hashkey = self.hash(key) # 计算键的哈希值
for i, item in enumerate(self.table[hashkey]): # 在对应的桶中查找指定的键
if item[0] == key: # 如果找到指定的键,从桶中移除该键值对
self.table[hashkey].pop(i)
return
学习了哈希表和哈希函数是什么:
哈希表的两个核心问题是:「哈希函数的构建」 和 「哈希冲突的解决方法」。
- 常用的哈希函数方法有:直接定址法、除留余数法、平方取中法、基数转换法、数字分析法、折叠法、随机数法、乘积法、点积法等。
- 常用的哈希冲突的解决方法有两种:开放地址法和链地址法。