《算法零基础100讲》(第5讲) 计数法(c语言解题)

因为想锻炼一下自己的英语阅读能力,所以就把语言调成了英文,每道题都有链接看不太明白的可以点击链接看中文的题目。

1748. Sum of Unique Elements


1748.唯一元素和

在这里插入图片描述
Constraints:
1 <= nums.length <= 100
1 <= nums[i] <= 100

这道题是一道十分基础的计数题,并且数据范围也比较小,可以利用数组下标来记录每个数出现的次数。
代码如下:

int sumOfUnique(int* nums, int numsSize){
	//元素大小在1-100,所以我们定义一个长度为101的数组
    int arr[101];
    memset(arr, 0, sizeof(arr));//将数组元素进行初始化
    for(int i = 0; i < numsSize; i++){
        arr[nums[i]]++;
    }
    int cnt = 0;
    for(int i = 0; i < 101; i++){
        if(arr[i] == 1){
            cnt+=i;
        }
    }
    return cnt;
}

387. First Unique Character in a String


字符串中的第一个唯一字符

在这里插入图片描述在这里插入图片描述
这道题考的是对ASCII码表的使用,我们可以通过数组arr[26]来记录每个字符出现的次数。
代码如下:

int firstUniqChar(char * s){
    int arr[26];
    memset(arr, 0, sizeof(arr));
    int n = strlen(s);
	
    for(int i = 0; i < n; i++){
    	//将s[i] - 'a'就可以将字符s[i]转化为0-25的下标来表示
        arr[s[i] - 'a']++;
    }
    for(int i = 0; i < n; i++){
        if(arr[s[i] - 'a'] == 1){
            return i;
        }
    }
    return -1;
}

1941. Check if All Characters Have Equal Number of Occurrences


1941. 检查是否所有字符出现次数相同

在这里插入图片描述
Constraints:

1 <= s.length <= 1000
s consists of lowercase English letters.

这道题的做法和上道题差不多,也是用一个数组arr[26]来记录每个字符出现的次数,并且比较每个字符出现的次数是否相同,但是在计算的同时我们也要用一个变量记录更新某个字符出现的次数。

代码如下:

bool areOccurrencesEqual(char * s){
    int arr[26];
    memset(arr, 0, sizeof(arr));
    int len = strlen(s);
    //用来记录某个字符出现的次数
    int n = 0;
    for(int i = 0; i < len; i++){
        arr[s[i] - 'a']++;
        n = arr[s[i] - 'a'];
    }
    
    for(int i = 0; i < 26; i++){
        if(arr[i] == 0){
            continue;
        }
        else if(arr[i] != n){
            return false;
        }

    }
    return true;
}

448 Find All Numbers Disappeared in an Array


448.找到所有数组中消失的数

在这里插入图片描述
这道题可以用hash表的思路来记录nums数组中的数字因为数组元素的取值范围是[1,n],所以我们可以定义一个长度为n的数组来记录,这种解法的时间复杂度是O(n),空间复杂度也是O(n),但我们如何能够将空间复杂度降到O(1)呢?

这里我们可以考虑用nums本身来做hash表,我们可以将nums[i]+numsSize赋值给nums[nums[i] - 1],这样,每个出现过的数字所对应的下标的元素都会大于numsSize,最后在遍历nums数组,数据小于或等于numsSize所对应的下标+1就是该数组中所缺少的元素,但这样有会出现一个问题,因为nums中的元素是随机的,如果较大的数字出现在前面,就会将该数字所对应下标的较小数据给覆盖掉,这样就会遗漏一些数据,对于这个问题我们可以通过取模操作符来解决。

代码如下:

int* findDisappearedNumbers(int* nums, int numsSize, int* returnSize){
    for(int i = 0; i < numsSize; i++){
        int x = (nums[i] - 1) % numsSize;
        nums[x] += numsSize;
    }
    int* arr = (int*) malloc (sizeof(int) * numsSize);
    int n = 0;
    for(int i = 0; i < numsSize; i++){
        if(nums[i] <= numsSize){
            arr[n++] = i + 1;
        }
    }
    *returnSize = n;
    return arr;
}

1512. Number of Good Pairs


1512.好数对的数目

在这里插入图片描述
在这里插入图片描述

这道题也是十分的简单,只需找出有多少对相等的数,方法也很多种,但由于数据量不大,所以我们就直接用暴力法即可。

代码如下:

int numIdenticalPairs(int* nums, int numsSize){
    int num = 0;

    for(int i = 0; i < numsSize; i++){

        for(int j = i + 1; j < numsSize; j++){
            if(nums[i] == nums[j]){
                num++;
            }
        }
    }
    return num;
}

1711. Count Good Meals


1711.大餐计数

在这里插入图片描述
用例:
在这里插入图片描述
这道题的数据量比较大,如果直接用暴力法会超时,时间复杂度是O(n ^ 2),官方的题解是用哈希表来做,但这道题我更中意英雄哥的解法,题目要求我们找出数组内两个元素的和为2的幂,反过来我们可以用2的幂来减去数组的中的元素,先定义一个数组cnt[(1<<21) + 1],因为数据的范围是[1,2 ^ 20],所以两个数据的和最大不会超过2 ^ 21,具体操作如下:

int cnt[ (1<<21) + 1 ];
int countPairs(int* deliciousness, int deliciousnessSize){
    memset(cnt, 0, sizeof(cnt));
    int ret = 0;
    for(int i = 0; i < deliciousnessSize; i++){
		//j表示2的幂
        for(int j = 1; j <= (1 << 21); j *= 2){
			//dis表示差
            int dis = j - deliciousness[i];
            if(dis < 0){
                continue;
            }
            //如果dis>0,则在ret上累加cnt[dis],
            //cnt[dis],内的数据代表deliciousness中dis的个数
            ret += cnt[dis];
            ret %= 1000000007;
        }
        //更新dis的个数。
        cnt[deliciousness[i]]++;
    }      
    return ret;                              
}
//1000000007
  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

友人苏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值