242. 有效的字母异位词
nums = [0]*26
:
这行代码创建了一个包含26个0的列表,这个列表通常用于计数或者作为某种映射的基础,比如统计字符串中每个字母出现的次数(假设只考虑小写字母a-z)。
ord()
Python 中的一个内置函数,用于获取单个字符(Unicode 字符)的整数表示(即字符的 Unicode 码点)。这个函数非常有用,因为它允许你将字符与其在计算机内部存储的数值表示形式相互转换。
ord(c):c
是一个长度为 1 的字符串,即一个字符
# 获取字符 'A' 的 Unicode 码点
print(ord('A')) # 输出: 65
# 获取数字字符 '5' 的 Unicode 码点
print(ord('5')) # 输出: 53
# 尝试获取多字符字符串的 Unicode 码点,将抛出 TypeError
# print(ord('AB')) # TypeError: ord() expected a character, but string of length 2 found
# 尝试获取非字符字符串(如空字符串)的 Unicode 码点,也将抛出 TypeError
# print(ord('')) # TypeError: ord() expected a character, but string of length 0 found
注意事项
ord()
函数仅适用于单个字符的字符串。- 字符的 Unicode 码点可以用来在程序中进行各种操作,比如字符编码转换、字符比较等。
- 当你需要将一个整数转换回对应的字符时,可以使用内置的
chr()
函数。
python 代码:
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
nums = [0]*26
for i in s:
nums[ord(i)-ord('a')] += 1
for i in t:
nums[ord(i)-ord('a')] -= 1
for i in nums:
if i != 0:
return False
return True
349. 两个数组的交集
当数组中的数值没有小于1000这个限制的时候,这道题倾向于用set来求解。加了这个限制之后,这道题目用数组来求解,用哈希表的结构是比较合适的。当我们遇到哈希表的题目的时候,要判断什么时候用数组?什么时候用set?什么时候用map?
这里我们默认他没有加上数组的限制。也就是其中的Int可能非常大。可能是上千或上亿。当这里面的数值非常大的时候,我们想用数组来做映射就不合适了。因为数组下标放不了那么大的数。同时也非常浪费储存空间。
这道题为什么会想到用哈希表来解决?哈希表适合用于解决什么样的题目?哈希表最擅长于解决,给你一个集合,判断元素是否有在这个集合里出现过。类似这种场景第一个要想到用哈希表。具体用数组还是用set还是用map?要具体分析。如果这个数值很大的话就不适合用数组。还有一种情况是数值可能不是很大,但是分布的很分散。如0,100万,如果用数组来做映射的话,要用100万那么大的数组,但实际运用的只有三个。这种情况下用set也是比较合适的。
本题是求两个数组的交集。可以将其中一个数组转化为哈希表。然后再去遍历第二个数组,检查元素是否在哈希表里面出现过。如果出现过,我们就将它放在result集合里面,并且这个集合是去重的。
在c加加里面有三个set结构:
以下是几个与集合相关的常用C++ STL(标准模板库)容器:
-
std::set
std::set
是一个基于红黑树(一种自平衡二叉查找树)实现的集合容器。它存储的元素是唯一的,且按照一定的顺序(默认情况下是升序,但可以通过自定义比较函数来改变)进行存储。std::set
主要提供了插入、删除和查找元素的操作,这些操作在平均和最坏情况下都具有对数时间复杂度。 -
std::multiset
与
std::set
类似,std::multiset
也是基于红黑树实现的,但它允许存储重复的元素。这意味着同一个值可以在std::multiset
中出现多次。std::multiset
提供的接口和操作与std::set
类似,但考虑到它允许重复元素,其行为在某些方面会有所不同(比如插入重复元素时,会成功添加而不是失败)。 -
std::unordered_set
与
std::set
和std::multiset
不同,std::unordered_set
是基于哈希表实现的,因此它不保证元素的顺序。然而,由于哈希表的性质,它在平均情况下的插入、删除和查找操作都具有常数时间复杂度(尽管在最坏情况下可能会退化到线性时间复杂度,但这通常不会发生)。std::unordered_set
同样要求存储的元素是唯一的。
需要注意的是,虽然这里没有直接提到“三个set结构”的固定术语,但std::set
、std::multiset
和std::unordered_set
是C++ STL中与集合操作最相关的三种数据结构。它们各自的特点和用途使得开发者可以根据具体需求选择最适合的数据结构。
std::set
、std::multiset底层实现都是红黑树。std::unordered_set底层实现是哈希值的方式。是哈希值直接映射,可以理解为是一个可以无限存储的数组。这里选择unordered_set,因为他做映射的时候效率是最高的。做取值操作的时候效率也是最高的。因为另外两个底层是树,取值的时候还有一个查找的操作。
set解决:
unordered_set = result
因为unordered_set 可以进行去重操作,从这里也可以看出来,我们在解题的时候选择一个合适的数据结构非常重要。
unordered_set = number_set(nums1)
这里直接将nums1进行初始化。将nums1转化为unordered_set ;接下来这里对nums2进行一个查询操作。
for(i = 0;i<nums2.size;i++){
遍历的过程首先是判断这个元素在unordered_set 里面有没有出现过。
if (number_set.find(nums2[i] != number_set.end()){
在这段C++代码中,number_set.find(nums2[i]) 返回一个迭代器,指向找到的元素(如果找到的话),或者如果没有找到,则返回 end() 迭代器。然后,我们通过比较这个迭代器是否不等于 end() 迭代器来检查元素是否存在。
result.insert(nums2[i])
}
return vector(result)
数组解决:
我们定义一个数组,比给定的范围大一点就行了。
int hash[1005] = {0}
unordered_set = result
还是刚才的处理逻辑,首先将nums1处理成哈希表的结构。
for(i = 0;i<nums1.size;i++){
hash[nums1[i]] = 1;
哈希数组下标所对应的值赋值为一,这样我们这个哈希数组就记录了nums1数组中的所有元素。所有出现过的元素在我数组的下标所对应的值都是一。这样就将数组nums1中所有元素进行记录了。
}
接下来是判断nums2
for(i = 0;i<nums2.size;i++){
if (hash[nums2[i] == 1]){
如果这个值等于一,说明他在哈希表里出现过。
result.insert[num2[i];
这样就将nums1出现过的元素,在num2中间储存起来了。并且进行了去重的操作
}
}
return vector(result)
其实这道题用数组来做效率会更高一些,因为用set的话每往里面添加一个值,进行一个insert的操作,要对值进行一个哈希运算。然后转变成他内部存储的值,然后还要去新开辟一个内存空间。用数组的话直接用下标进行哈映射是最快的。
Python代码(set方法):
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
return list(set(nums1) & set(nums2))
#使用 & 操作符或 intersection() 方法可以取交集
set1 = {1, 2, 3}
set2 = {2, 3, 4}
# 使用 & 操作符
intersection = set1 & set2 # {2, 3}
# 使用 intersection() 方法
intersection_method = set1.intersection(set2) # {2, 3}
Python里面set的操作:
1. 交集(Intersection)
- 使用
&
操作符或intersection()
方法: -
set1 = {1, 2, 3} set2 = {2, 3, 4} # 使用 & 操作符 intersection = set1 & set2 # {2, 3} # 使用 intersection() 方法 intersection_method = set1.intersection(set2) # {2, 3}
2. 并集(Union)
- 使用
|
操作符或union()
方法: -
union = set1 | set2 # {1, 2, 3, 4} union_method = set1.union(set2) # {1, 2, 3, 4}
3. 差集(Difference)
- 使用
-
操作符或difference()
方法: -
difference = set1 - set2 # {1} difference_method = set1.difference(set2) # {1}
4. 对称差集(Symmetric Difference)
- 使用
^
操作符或symmetric_difference()
方法: -
symmetric_difference = set1 ^ set2 # {1, 4} symmetric_difference_method = set1.symmetric_difference(set2) # {1, 4}
5. 添加元素
- 使用
add()
方法: -
my_set.add(4) # 现在 my_set 是 {1, 2, 3, 4}
6. 移除元素
- 使用
remove()
方法(如果元素不存在会抛出异常):my_set.remove(2) # 现在 my_set 是 {1, 3, 4}
- 使用
discard()
方法(如果元素不存在不会抛出异常):my_set.discard(5) # my_set 仍然是 {1, 3, 4}
- 使用
pop()
方法(移除并返回集合中的一个元素,如果集合为空则抛出异常):removed_element = my_set.pop() # 移除并返回集合中的一个元素
7. 判断元素是否存在
- 使用
in
关键字:if 3 in my_set: print("3 exists in the set")
8. 集合的长度
- 使用
len()
函数:print(len(my_set)) # 输出集合中元素的数量
9. 转换为列表
- 使用
list()
函数:list_from_set = list(my_set) # 将集合转换为列表
Python (字典和集合):
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
table = {}
for num in nums1:
table[num] = table.get(num,0) + 1
res= set()
for num in nums2:
if num in table:
res.add(num)
del table[num]
return list(res)
del table[num]:
在Python中,del table[num]
这行代码的作用是删除字典(如果table
是一个字典)或者列表(如果table
是一个列表)中索引或键为num
的元素。不过,重要的是要理解这两种数据结构之间的差异以及如何使用它们。
如果table
是一个列表(List)
在列表中,num
应该是一个整数索引,它指定了要删除的元素的位置。例如:
table = [1, 2, 3, 4, 5]
num = 2
del table[num] # 删除索引为2的元素,即数字3
print(table) # 输出: [1, 2, 4, 5]
如果table
是一个字典(Dictionary)
在字典中,num
应该是一个字符串或不可变类型(如整数、浮点数等,但在实际使用中字符串作为键更为常见),它指定了要删除的键值对的键。例如:
table = {'a': 1, 'b': 2, 'c': 3}
num = 'b'
del table[num] # 删除键为'b'的键值对
print(table) # 输出: {'a': 1, 'c': 3}
注意点
-
如果
num
的索引或键在table
中不存在,使用del table[num]
将会抛出一个KeyError
(对于字典)或IndexError
(对于列表)异常。 -
在处理列表或字典时,如果不确定索引或键是否存在,可以先使用
in
关键字进行检查,例如:if num in table: del table[num] else: print(f"The key {num} does not exist in the table.")
-
字典的键是唯一的,而列表的索引是基于位置的,这意呀着你可以有重复的列表项,但每个列表项的索引都是唯一的。在字典中,你不能有重复的键。
python(数组方法):
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
count1 = [0]*1001
count2 = [0]*1001
res = []
for i in range(len(nums1)):
count1[nums1[i]] += 1
for i in range(len(nums2)):
count2[nums2[i]] += 1
for i in range(1001):
if count1[i]*count2[i] > 0:
res.append(i)
return res