#include
#include
#include
int main()
{
int char_map[129] = { 0 }; //存放每个字符的个数
std::string str = "abcaba"; //字符串
for (int i = 0; i < str.length(); i++) //str.length() = 6
{
char_map[str[i]]++; // char_map['a']++; 97 char_map[97]++ = 1
}
for (int i = 0; i < 128; i++)
{
if(char_map[i] != 0)
printf("[%c][%d]:%d次\n", i,i,char_map[i]);
}
return 0;
}
[a][97]:3次
[b][98]:2次
[c][99]:1次
#include
#include
#include
int main()
{
int ran_dom[] = { 1,2,66,999,10,1,1,7,4,2,888 };
int hash[1000] = { 0 };
for (int i = 0; i < sizeof(ran_dom) / sizeof(int); i++)
{
hash[ran_dom[i]]++;
}
for (int i = 0; i < 1000; i++)
{
for (int j = 0; j < hash[i]; j++)
{
printf("%d\n", i);
}
}
return 0;
}
1
1
1
2
2
4
7
10
66
888
999
#include
#include
#include
#include
using namespace std;
// 定义链表节点结构
struct ListNode {
int val;
ListNode* next;
ListNode(int x) :val(x), next(NULL)
{
}
};
// 哈希函数,用于计算键值对应的哈希桶索引
int hash_func(int key, int table_len)
{
return key % table_len; // 整数哈希,取余
}
// 插入操作,将节点插入到哈希表中
void insert(ListNode* hash_table[], ListNode* node, int table_len)
{
int hash_key = hash_func(node->val, table_len); // 计算哈希桶索引
node->next = hash_table[hash_key]; // 将节点插入到链表的头部
hash_table[hash_key] = node; // 更新哈希桶的头指针
}
// 查找操作,判断给定的值是否在哈希表中
bool search(ListNode* hash_table[], int value, int table_len)
{
int hash_key = hash_func(value, table_len); // 计算哈希桶索引
ListNode* head = hash_table[hash_key]; // 获取链表头指针
while (head)
{
if (head->val == value) // 如果找到匹配的值,返回true
{
return true;
}
head = head->next; // 继续遍历链表中的下一个节点
}
return false; // 如果遍历完链表仍然没有找到匹配的值,返回false
}
int main()
{
const int TABLE_LEN = 11; // 哈希表的长度
ListNode* hash_table[TABLE_LEN] = { 0 }; // 定义哈希表,初始化为空指针
std::vector hash_node_vec; // 定义存储节点指针的向量
int test[8] = { 1,1,4,9,20,30,150,500 }; // 测试用例数组
// 将测试用例数组中的值构建成节点,并存储到向量中
for (int i = 0; i < 8; i++)
{
hash_node_vec.push_back(new ListNode(test[i]));
}
// 将节点插入到哈希表中
for (int i = 0; i < hash_node_vec.size(); i++)
{
insert(hash_table, hash_node_vec[i], TABLE_LEN);
}
printf("Hash Table:\n");
// 打印哈希表中的链表
for (int i = 0; i < TABLE_LEN; i++)
{
printf("[%d]:", i);
ListNode* head = hash_table[i]; // 获取当前哈希桶的头指针
while (head)
{
printf("->%d", head->val); // 打印节点的值
head = head->next; // 继续遍历链表中的下一个节点
}
printf("\n");
}
printf("\n");
printf("Test search:\n");
// 在哈希表中进行查找操作
for (int i = 0; i < 10; i++)
{
if (search(hash_table, i, TABLE_LEN))
{
printf("%d is in the hash table.\n", i);
}
else
{
printf("%d is not in the hash table.\n", i);
}
}
return 0;
}
Hash Table:
[0]:
[1]:->1->1
[2]:
[3]:
[4]:->4
[5]:->500
[6]:
[7]:->150
[8]:->30
[9]:->20->9
[10]:Test search:
0 is not in the hash table.
1 is in the hash table.
2 is not in the hash table.
3 is not in the hash table.
4 is in the hash table.
5 is not in the hash table.
6 is not in the hash table.
7 is not in the hash table.
8 is not in the hash table.
9 is in the hash table.
给你一个整数数组 nums
。数组中唯一元素是那些只出现 恰好一次 的元素。
请你返回 nums
中唯一元素的 和 。
class Solution {
public:
int sumOfUnique(vector& nums) {
vector hash(101,0);
int sum = 0;
for(int i=0; i
class Solution {
public:
int sumOfUnique(vector &nums) {
unordered_map cnt; // 创建无序哈希表 cnt,用于记录每个数字出现的次数
for (int num : nums) {
++cnt[num]; // 遍历 nums,将每个数字作为键,将其出现次数加 1 存储在 cnt 中
}
int ans = 0; // 初始化答案为 0
for (auto &[num, c] : cnt) { // 遍历 cnt 中的每个键值对
if (c == 1) { // 如果数字的出现次数为 1,说明是唯一元素
ans += num; // 将该唯一元素的值累加到答案中
}
}
return ans; // 返回答案
}
};
for (int num : nums)for (auto &[num, c] : cnt)
这两句是使用 C++11 引入的范围遍历(Range-based For Loop)语法。
1. `for (int num : nums)`:
- 这是一种简化的循环语法,用于遍历容器 `nums` 中的元素。
- `int num` 是一个声明,用于定义一个循环变量 `num`,它会依次取 `nums` 容器中的每个元素的值。
- 在循环体内部,可以使用变量 `num` 来访问当前遍历到的元素的值。
- 这种语法可以替代传统的使用索引的循环方式,使代码更简洁易读。2. `for (auto &[num, c] : cnt)`:
- 这也是 C++11 引入的范围遍历语法,用于遍历容器 `cnt` 中的键值对。
- `auto &[num, c]` 是一个声明,使用了自动类型推导(auto)来推导变量的类型。
- `&[num, c]` 是一个引用绑定(reference binding),将键值对的键绑定到 `num`,将键值对的值绑定到 `c`。
- 在循环体内部,可以使用变量 `num` 来访问当前遍历到的键,使用变量 `c` 来访问当前遍历到的值。
- 这种语法可以方便地同时访问键和值,使代码更简洁易读。这些语法的引入是为了使 C++ 代码更加简洁、易读和高效。它们在 C++11 中引入,并成为了 C++ 的常见用法。使用范围遍历可以减少手动迭代和索引管理的工作,提高代码的可读性和简洁性。
`unordered_map` 和 `map`
`unordered_map` 和 `map` 是 C++ 标准库中两种不同的关联容器,它们用于实现键值对的存储和检索。它们的主要区别在于底层实现和特性上。
1. 底层实现:
- `unordered_map` 使用哈希表(散列表)作为底层数据结构,以实现快速的插入、查找和删除操作。由于使用哈希表,其元素的存储顺序是不确定的。
- `map` 使用红黑树作为底层数据结构,以实现有序的键值对存储和高效的插入、查找和删除操作。红黑树保持元素按照键的升序排序。2. 时间复杂度:
- `unordered_map` 的插入、删除和查找操作的平均时间复杂度为 O(1),最坏情况下的时间复杂度为 O(n),其中 n 是元素的数量。
- `map` 的插入、删除和查找操作的平均时间复杂度为 O(log n),其中 n 是元素的数量。3. 元素顺序:
- `unordered_map` 不保持元素的顺序,元素在哈希表中根据键的哈希值分布。
- `map` 保持元素按照键的升序排序,因此可以迭代得到有序的键值对。4. 内存占用:
- `unordered_map` 基于哈希表,相对于 `map` 需要更多的额外内存来存储哈希表的索引结构。
- `map` 基于红黑树,相对于 `unordered_map` 可能更节省内存。根据使用场景的不同,我们可以选择合适的关联容器。如果需要快速的插入、删除和查找操作,并且不关心元素的顺序,则可以使用 `unordered_map`。如果需要有序的键值对集合,或者需要按照键的升序遍历元素,则可以使用 `map`。
需要注意的是,`unordered_map` 和 `map` 提供的接口和用法大致相同,包括插入、删除、查找等操作,因此可以根据实际需求选择适合的容器来实现相关功能。
给你一个整数数组 nums
,它包含 2 * n
个整数。
你需要将 nums
划分成 n
个数对,满足:
如果可以将 nums
划分成 n
个数对,请你返回 true
,否则返回 false
。
class Solution {
public:
bool divideArray(vector& nums) {
unordered_map cnt;
for(int num:nums)
{
cnt[num]++;
}
/*
for(const auto & kvp :cnt)
{
if(kvp.second & 1)
*/
for(auto &[num,c] :cnt)
{
if(c&1)
{
return false;
}
}
return true;
}
};
全字母句 指包含英语字母表中每个字母至少一次的句子。
给你一个仅由小写英文字母组成的字符串 sentence
,请你判断 sentence
是否为 全字母句 。
如果是,返回 true
;否则,返回 false
。
class Solution {
public:
bool checkIfPangram(string sentence) {
vector exist(26);
for(auto i:sentence)
{
exist[i-'a'] = true;
}
for(auto i:exist)
{
if(!i)
{
return false;
}
}
return true;
}
};
class Solution {
public:
bool checkIfPangram(string sentence) {
unordered_map cnt;
for(char num : sentence)
{
cnt[num]++;
}
for(int i='a'; i<='z';i++)
{
if(cnt[i]==0)
{
return false;
}
}
return true;
}
};
在您提供的代码中,
cnt
是一个unordered_map
类型的容器,用于记录每个字符出现的次数。在这段代码中,
cnt
的大小是根据实际字符范围来确定的。它是一个无序哈希表,以字符的 ASCII 值作为键,出现次数作为值。由于题目限定了字符范围是小写字母 'a' 到 'z',因此cnt
的大小是 26。在遍历
sentence
字符串时,将每个字符作为键,将对应位置的哈希表值加 1。由于cnt
的大小足够容纳 'a' 到 'z' 的字符,不会发生越界现象。在第二个循环中,遍历从 'a' 到 'z' 的字符,检查每个字符的出现次数。如果某个字符的出现次数为 0,说明该字符在
sentence
中没有出现,返回false
。因此,根据题目要求,这段代码可以正确判断给定的句子是否是一个 pangram(包含所有字母)。
代码
测试用例
测试用例
执行结果
给你一个整数数组 nums
。
如果一组数字 (i,j)
满足 nums[i]
== nums[j]
且 i
< j
,就可以认为这是一组 好数对 。
返回好数对的数目。
示例 1:
输入:nums = [1,2,3,1,1,3] 输出:4 解释:有 4 组好数对,分别是 (0,3), (0,4), (3,4), (2,5) ,下标从 0 开始
示例 2:
输入:nums = [1,1,1,1] 输出:6 解释:数组中的每组数字都是好数对
示例 3:
输入:nums = [1,2,3] 输出:0
提示:
1 <= nums.length <= 100
1 <= nums[i] <= 100
class Solution {
public:
int numIdenticalPairs(vector& nums) {
int j, ans = 0; // 定义变量 j 和 ans,初始化 ans 为 0
int hash[101]; // 定义大小为 101 的 hash 数组,用于记录每个数字出现的次数
memset(hash, 0, sizeof(hash)); // 使用 memset 将 hash 数组初始化为 0
for (j = 0; j < nums.size(); ++j) { // 遍历 nums 数组
ans += hash[nums[j]]; // 累加 hash[nums[j]] 的值到 ans
++hash[nums[j]]; // 将 nums[j] 对应位置的值加 1
}
return ans; // 返回最终的结果 ans
}
};
这段代码的思路如下:
- 定义变量
j
和ans
,并初始化ans
为 0,用于记录最终结果。- 定义大小为 101 的
hash
数组,用于记录每个数字出现的次数。这里假设数字的范围在 0 到 100 之间。- 使用
memset
函数将hash
数组初始化为 0,确保所有计数器的初始值为 0。- 遍历
nums
数组,使用变量j
作为循环变量。- 在循环体内,首先将
hash[nums[j]]
的值累加到ans
中。因为对于当前数字nums[j]
,它能够与之前出现过的相同数字形成的符合条件的数对数量为hash[nums[j]]
。- 然后,将
nums[j]
对应位置的计数器加 1,表示该数字出现了一次。- 循环结束后,返回最终的结果
ans
,即符合条件的数对的数量。这段代码的目的是计算给定数组中满足条件的数对数量,其中条件是两个数相等且索引不同。通过遍历数组并使用哈希表记录每个数字出现的次数,可以快速计算出符合条件的数对的数量。
class Solution {
public:
int numIdenticalPairs(vector& nums) {
int ans=0;
int counter[101] = {0};
for(int n:nums)
{
ans += counter[n];
counter[n]++;
}
return ans;
}
};
给你一个整数数组 nums
和一个整数 k
,请你返回数对 (i, j)
的数目,满足 i < j
且 |nums[i] - nums[j]| == k
。
|x|
的值定义为:
x >= 0
,那么值为 x
。x < 0
,那么值为 -x
。示例 1:
输入:nums = [1,2,2,1], k = 1 输出:4 解释:差的绝对值为 1 的数对为:
示例 2:
输入:nums = [1,3], k = 3 输出:0 解释:没有任何数对差的绝对值为 3 。
示例 3:
输入:nums = [3,2,1,5,4], k = 2 输出:3 解释:差的绝对值为 2 的数对为:
提示:
1 <= nums.length <= 200
1 <= nums[i] <= 100
1 <= k <= 99
class Solution {
public:
int countKDifference(vector& nums, int k) {
int hash[101]; // 定义大小为 101 的 hash 数组,用于记录每个数字出现的次数
int ans = 0; // 初始化结果 ans 为 0
memset(hash, 0, sizeof(hash)); // 使用 memset 初始化 hash 数组为 0
for (int j = 0; j < nums.size(); ++j) { // 遍历 nums 数组
int x = nums[j] + k; // 计算与当前数字 nums[j] 相差 k 的值
if (x >= 1 && x <= 100) { // 判断 x 是否在有效范围内
ans += hash[x]; // 累加 hash[x] 的值到 ans
}
x = nums[j] - k; // 计算与当前数字 nums[j] 相差 k 的值
if (x >= 1 && x <= 100) { // 判断 x 是否在有效范围内
ans += hash[x]; // 累加 hash[x] 的值到 ans
}
++hash[nums[j]]; // 将 nums[j] 对应位置的值加 1
}
return ans; // 返回最终的结果 ans
}
};
这段代码的思路如下:
hash
数组,用于记录每个数字出现的次数。这里假设数字的范围在 1 到 100 之间。ans
为 0。memset
函数将 hash
数组初始化为 0,确保所有计数器的初始值为 0。nums
数组,使用变量 j
作为循环变量。x
,一个是 nums[j] + k
,另一个是 nums[j] - k
。这样可以找到与当前数字 nums[j]
相差 k
的两个目标值。x
,首先判断它是否在有效范围内(1 到 100),如果是,则将 hash[x]
的值累加到 ans
中。nums[j]
对应位置的计数器加 1。ans
,即满足条件的数对的数量。这段代码的目的是计算给定数组中差值为 k
的数对的数量。通过遍历数组并使用哈希表记录每个数字出现的次数,可以快速计算出满足条件的数对的数量。