文章目录
- 一. 推荐专栏
- 二. 多维枚举
- 二. 课后练习
- 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;
}