[题解]《算法零基础100讲》(第31讲) 多维枚举(一) - 入门

一. 推荐专栏

《算法零基础100讲》(第31讲) 多维枚举(一) - 入门
  
  
  

二. 多维枚举

  多维枚举实际上就是在进行循环嵌套,例如二维枚举:在一个for循环中嵌套一个for循环。

#incldue <stdio.h>

int main(){
	int n;
	scanf("%d", &n);
	for(int i = 0; i < n; i++){
		for(int j = 0; j < n; j++){
			pritnf("%d%d ", i,j);
		}
		printf("\n");
	}
	return 0;
}

其中,第一层循环通常代表列,第二层循环代表行。
  
  
  

二. 课后练习

2.1. 找不同

2.1.1 题目链接:

389. 找不同

2.1.2 思路分析

  

  题目要求我们找出两个序列的不同字母,应该说是字符串s相对于字符串t缺少了那一个字符,其实就是将s对应与t进行排列,s需要添加一个字符即可得到t。

所以我们只需要将t的字符都加起来,然后减去s中的字符,剩下的值就是缺少的字母的ASCLL码值。

代码如下:

char findTheDifference(char * s, char * t){
    int sum = 0;
    for(int i = 0; t[i]; i++){
        sum += t[i];
    }
    for(int i = 0; s[i]; i++){
        sum -= s[i];
    }
    char ret = sum;
    return ret;
}

2.2 拥有最多糖果的孩子

2.2.1 题目链接

1431. 拥有最多糖果的孩子

2.2.2 思路分析

题目的意思是,给定我们一个数组candies,candies[i]的意思是指第 i 个孩子所分得的糖果,还给定一个变量extracandies,额外得糖果数量,现在我们要将额外得糖果分配给这些孩子,对每一个孩子,是否有一种方案能够让他成为拥有糖果数最多得孩子,如果存在,则为true。

我们只需对所有孩子进行一次判断candies[i] + extracandies >= maxNum,即可。

代码如下:

bool* kidsWithCandies(int* candies, int candiesSize, int extraCandies, int* returnSize){
    bool* ret = (bool*)malloc(sizeof(bool) * (candiesSize + 1));
    int max = 0;
    for(int i = 0; i < candiesSize; i++){
        if(max < candies[i])max = candies[i];
    }
    for(int i = 0; i < candiesSize; i++){
        if(candies[i] + extraCandies >= max){
            ret[i] = true;
        }
        else{
            ret[i] = false;
        }
    }
    *returnSize = candiesSize;
    return ret;
}

2.3 所有奇数长度子数组的和

2.3.1 题目链接

1588. 所有奇数长度子数组的和

2.3.2 方法一 暴力

  我们可以枚举所以为奇数的长度的子序列,假设长度为n,子序列的起点为start,长度为length,结束下标为 end,则有0 <= start <= end < n,length = end - length + 1为奇数。

代码如下:

int sumOddLengthSubarrays(int* arr, int arrSize) {
    int sum = 0;
    for (int start = 0; start < arrSize; start++) {
        for (int length = 1; start + length <= arrSize; length += 2) {
            int end = start + length - 1;
            for (int i = start; i <= end; i++) {
                sum += arr[i];
            }
        }
    }
    return sum;
}

2.3.3 方法二 前缀和

  我们定义一个数组prefixSums[],prefixSum[ i ]表示从0到i - 1的数字和,得到前缀和数组后,对于0 <= start <= end < n,数组arr 的下标范围[start,end] 的子数组的和为prefixSums[end + 1] - prefixSums[start]。

代码图下:

int sumOddLengthSubarrays(int* arr, int arrSize){
    int prefixSum[arrSize + 1];
    prefixSum[0] = 0;
    for(int i = 0; i < arrSize; i++){
        prefixSum[i + 1] = prefixSum[i] + arr[i]; 
    }
    int sum = 0;
    for(int start = 0; start < arrSize; start++){
        for(int length = 1; length + start <= arrSize; length += 2){
            int end = start + length;
            sum += (prefixSum[end] - prefixSum[start]);
        }
    }
    return sum;
}

2.3.4 方法三 数学

数学推导

代码如下:

int sumOddLengthSubarrays(int* arr, int arrSize){
    int sum = 0;
    for(int i = 0; i < arrSize; i++){
        int left = i, right = arrSize - left - 1;
        int leftodd = (left + 1) / 2;
        int rightodd = (right + 1) / 2;
        int lefteven = left / 2 + 1;
        int righteven = right / 2 + 1;
        sum += arr[i] * (leftodd * rightodd + lefteven * righteven);
    }
    return sum;
}

2.4 统计好三元组

1534. 统计好三元组

我们只需要用三层遍历进行判断找出符合条件的即可。

代码如下:

int countGoodTriplets(int* arr, int arrSize, int a, int b, int c){
    int count = 0;

    for(int i = 0; i < arrSize - 2; i++){
        for(int j = i + 1; j < arrSize - 1; j++){
            for(int k = j + 1; k < arrSize; k++){
                if(abs(arr[i]-arr[j])<=a && abs(arr[j]-arr[k])<=b && 
                						abs(arr[i] - arr[k]) <= c){
                        count++;
                    }
            }
        }
    }
    return count;
}

2.5 按既定顺序创建目标数组

2.5.1 题目链接

1389. 按既定顺序创建目标数组

这道题我们只需要用一个遍量记录当前数数字所达到的下标,当要往前面插入数据时,则需讲后面的数据往后移。

代码如下:

int* createTargetArray(int* nums, int numsSize, int* index, int indexSize, int* returnSize){
    int* target = (int*)malloc(sizeof(int) * numsSize);
    int tail = -1;
    for(int i = 0; i < numsSize; i++){
        tail++;
        for(int j = tail; j > index[i]; j--){
            target[j] = target[j - 1];
        }
        target[index[i]] = nums[i];
    }
    *returnSize = numsSize;
    return target;
}

2.6 统计平方和三元组的数目

2.6.1 题目链接

1925. 统计平方和三元组的数目
这道题很简单,我们还是进行三层遍历,找出所所有符合条件的情况。

代码如下:

int countTriples(int n){
    int count = 0;
    for(int i = 1; i < n - 1; i++){
        for(int j = i + 1; j < n; j++){
            for(int k = j + 1; k <= n; k++){
                if(i * i + j * j == k * k){
                    count++;
                }
            }
        }
    }
    return count * 2;
}
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

友人苏

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

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

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

打赏作者

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

抵扣说明:

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

余额充值