当前位置:首页 » 《随便一记》 » 正文

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

29 人参与  2022年05月17日 11:26  分类 : 《随便一记》  评论

点击全文阅读


文章目录

  • 一. 推荐专栏
  • 二. 多维枚举
  • 二. 课后练习
    • 2.1. 找不同
      • 2.1.1 题目链接:
      • 2.1.2 思路分析
    • 2.2 拥有最多糖果的孩子
      • 2.2.1 题目链接
      • 2.2.2 思路分析
    • 2.3 所有奇数长度子数组的和
      • 2.3.1 题目链接
      • 2.3.2 方法一 暴力
      • 2.3.3 方法二 前缀和
      • 2.3.4 方法三 数学
    • 2.4 统计好三元组
    • 2.5 按既定顺序创建目标数组
      • 2.5.1 题目链接
    • 2.6 统计平方和三元组的数目
      • 2.6.1 题目链接

一. 推荐专栏

《算法零基础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;
}

点击全文阅读


本文链接:http://m.zhangshiyu.com/post/40290.html

数组  题目  枚举  
<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1