C++哈希表的应用

问题1描述

给定一个长度为 n 的整数数组 nums,数组中的数的范围是 [1, 100]。请返回 nums 中出现一次的数的和。

问题1方法

1.可以用长度为101个的哈希表,下标i的位置对应存储数组nums中下标i出现的次数
给定
nums = [1, 2, 1, 3, 4]

  • 数字 1 出现了 2 次。
  • 数字 2 出现了 1 次。
  • 数字 3 出现了 1 次。
  • 数字 4 出现了 1 次。
    则在哈希表中
  • 下标为1的位置存储2
  • 下标为2的位置存储1
  • 下标为3的位置存储1
  • 下标为4的位置存储1
    hash:[0,2,1,1,1]

2.遍历完nums数组后,找到hash表中值为1的下标

问题1代码

int sumOFUnique(int* nums,int n){
	int hash[101];
	int i,sum=0;
	memset(hash,0,sizeof(hash));
	//初始化hash表中的数全为0
	for(i=0;i<n;++i){
		++hash[nums[i]];
	}
	for(i=0;i<n;=+i){
		if(hash[nums[i]==1){
			sum+=nums[i];
		}
	}
	return sum;
]

问题2描述

给定一个长度为 2n 的整数数组 nums,数组中的数的范围是 [1, 500]。判断是否可以将它们划分成 n 个数对,满足以下条件:

  1. 每个数只属于一个数对。
  2. 同一数对中的元素相等。

示例

输入: nums = [1, 2, 2, 1]

输出: True (可以划分成两对:(1, 1) 和 (2, 2))

算法步骤

  1. 初始化一个空的哈希表 countMap 用于存储对应下标的数字出现的次数。

  2. 遍历数组 nums,对于每个元素 num

    • 如果 countMap 中没有 num,则添加 numcountMap 并设置其计数为 1。
    • 如果 countMap 中已有 num,则将其计数加 1。
  3. 再次遍历 countMap,检查每个数字的计数:

    • 如果任何数字的计数不是偶数,则返回 False,因为这意味着无法将所有数字配对。
    • 如果所有数字的计数都是偶数,则返回 True
  4. 如果所有数字的计数都是偶数,继续检查是否可以将它们配对:

    • 初始化一个布尔数组 visited,长度为 501(因为数组中的数的范围是 [1, 500]),所有元素初始值为 false
    • 遍历数组 nums,对于每个元素 num
      • 如果 visited[num]true,则表示 num 已经配对,继续检查下一个元素。
      • 如果 visited[num]false,则将 visited[num] 设置为 true 并尝试寻找配对:
        • 从当前索引 i 开始,向后遍历数组,寻找下一个相同的 num
        • 如果找到,则将 visited[num] 对应的两个位置都设置为 true,表示这两个 num 已经配对。
        • 如果在数组末尾之前没有找到配对的 num,则返回 False
  5. 如果所有元素都成功配对,返回 True

代码

bool divideArray(int* nums,int numsSize){
	int i,hash[501]memset(hash,0,sizeof(hash));
	for(i=0;i<numsSize,++i){
		++hash[nums[i]];
		//哈希表对应下标的数字出现一次+1for(i=1;i<=500;++i){
		if(hash[i]&1){
				return false;//如果发现其中有奇数次说明肯定不能配对成功,返回false
	}
	return true;
}

在编程中,& 是按位与(bitwise AND)操作符。当你对两个数进行按位与操作时,结果的每一位都是由对应的两位决定的,如果对应的两位都是1,那么结果位就是1,否则就是0。

对于表达式 hash[i] & 1

  • 如果 hash[i] 的二进制表示的最低位(即个位)是1,那么 hash[i] & 1 的结果就是1。
  • 如果 hash[i] 的最低位是0,那么 hash[i] & 1 的结果就是0。

在整数中,如果一个数的最低位是1,那么这个数就是奇数;如果最低位是0,那么这个数就是偶数。因此,hash[i] & 1 可以用来判断 hash[i] 是否为奇数:

  • 如果 hash[i] & 1 等于1,那么 hash[i] 是奇数。
  • 如果 hash[i] & 1 等于0,那么 hash[i] 是偶数。

这种按位操作通常用于优化,因为它比除以2并取余数(% 2)的操作要快,尤其是在处理大量数据时。

复杂度分析

  • 时间复杂度:O(n),其中 n 是数组 nums 的长度。我们只遍历了数组两次。
  • 空间复杂度:O(1),除了输入数组外,我们只使用了固定大小的额外空间。

注意事项

  • 确保在寻找配对时,不要重复使用已经配对的元素。
  • 在实际编程实现中,需要考虑数组索引的边界条件,避免越界错误。

问题3描述

给定一个仅由小写英文字母组成的字符串,判断它是否是全字母句。全字母句定义为字符串中包含英文字母表中的每一个字母至少一次。

示例

输入: sentence = "adcbacbf"

输出: False (因为字符串中缺少字母 ‘e’, ‘g’, ‘h’, ‘i’, ‘j’, ‘k’, ‘l’, ‘m’, ‘n’, ‘o’, ‘p’, ‘q’, ‘r’, ‘s’, ‘t’, ‘u’, ‘v’, ‘w’, ‘x’, ‘y’, ‘z’ 中的一些)

算法步骤

因为字母-》ASCII码值(字母可以转换为ASCII码值且<=256)

  1. 创建一个长度为26的布尔数组 letterFound,用于标记26个英文字母是否都出现过,初始值全部为 false
  2. 遍历字符串 sentence 中的每个字符 char
    • 计算 index = char - 'a',得到字符在字母表中的索引。
    • letterFound[index] 设置为 true,表示该字母已经出现过。
  3. 再次遍历 letterFound 数组:
    • 如果发现任何元素为 false,则说明有字母未在 sentence 中出现,返回 False
    • 如果所有元素都为 true,则说明 sentence 是全字母句,返回 True

代码

bool checkIfPangram(char *sentence){
	int i,hash[256];
	memset(hash,0,sizeof(hash));
	for(i=0;sentence[i];++i){
		++hash[sentence[i]];
	}//对每个字符进行计数,一直到句子结束,将字符转为ASCII码值存入hash表中
	for(i='a';i<='z';++i){
	//遍历每个小写字母
		if(!hash[i]){//如果哈希表中 其中一个字母转为ASCII码值的下标处=0,说明这个字母没有出现过
		return false;
	}
	}
	return true;//否则返回true
}
			
}

复杂度分析

  • 时间复杂度:O(n),其中 n 是字符串 sentence 的长度。我们只遍历了字符串两次。
  • 空间复杂度:O(1),我们使用了一个固定大小的数组来存储字母的出现情况。

注意事项

  • 确保字符的比较是基于字母表的索引,而不是字符的ASCII值。
  • 在实际编程实现中,注意字符 ‘a’ 的ASCII值是97,而不是0,因此在计算索引时要减去 ‘a’ 的ASCII值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值