前言
原文链接:《算法零基础100讲》(第31讲) 多维枚举(一) - 入门
目录
概念
之前讲到的线性枚举,就是循环一遍来计数解决问题。那多维枚举就需要多重循环来解决问题。
int i, j, k;
for(i = 0; i < x; ++i) {
for(j = 0; j < y; ++j) {
for(k = 0; k < z; ++k) {
....
}
}
}
392. 判断子序列
原题链接:392. 判断子序列
代码
循环一遍,当 *s与 *t 都没走到末尾时,如果当前位置字符相同,就让t往后走。
循环退出时,*s为 ‘\0’,取反就为真。
bool isSubsequence(char * s, char * t)
{
while (*s && *t)
{
if (*s == *t)
{
s++;
}
t++;
}
return !*s;
}
240. 搜索二维矩阵 II
原题链接:240. 搜索二维矩阵 II
分析
因为这个矩阵的行和列都是按升序排列的,所以可以从矩阵的右上角开始查找。
若当前位置等于target,就退出;
若当前位置 > target,因为升序排列, 就从当前列往前找;
若当前位置 < target, 由于升序排列, 就直接改变行数。
这样的做法,每次改变都是改变整个行和列,比枚举快很多。
代码
bool searchMatrix(int** matrix, int matrixSize, int* matrixColSize, int target)
{
if (NULL == matrix)
return false;
int row = 0, col = *matrixColSize - 1;
while (row < matrixSize && col >= 0)
{
if (matrix[row][col] == target)
return true;
if (matrix[row][col] > target)
{
--col;
}
else
{
++row;
}
}
return false;
}
2006. 差的绝对值为 K 的数对数目
原题链接 : 2006. 差的绝对值为 K 的数对数目
代码
直接按照题目要求枚举
int countKDifference(int* nums, int numsSize, int k)
{
int count = 0;
for (int i = 0; i < numsSize - 1; ++i)
{
for (int j = i + 1; j < numsSize; ++j)
{
if (nums[i] - nums[j] == k || nums[j] - nums[i] == k)
{
count++;
}
}
}
return count;
}
389. 找不同
原题链接:389. 找不同
分析
我的做法是用一个数组,记录原字符串每个字母出现的次数,再遍历改变后的数组,对于每个出现的字符,在保存的数组中减去对应的字符个数;
如果某个字符个数被减到 -1,就说明找到这个字符了。
代码
char findTheDifference(char * s, char * t)
{
if (NULL == s || NULL == t)
return 0;
int hash[26] = {0};
for (int i = 0; i < strlen(s); ++i)
{
++hash[s[i] - 'a'];
}
for (int i = 0; i < strlen(t); ++i)
{
--hash[t[i] - 'a'];
if (hash[t[i] - 'a'] < 0)
return t[i];
}
return '';
}
1431. 拥有最多糖果的孩子
原题链接:1431. 拥有最多糖果的孩子
代码
按照题目要求直接写出
很讨厌两种人:
- 写代码不写注释的人(没错好像是我)
- 让别人写注释的人。。。
bool* kidsWithCandies(int* candies, int candiesSize, int extraCandies, int* returnSize)
{
*returnSize = 0;
if (candies == NULL)
return NULL;
bool* ans = (bool*)malloc(sizeof(bool) * candiesSize);
if (ans == NULL)
return NULL;
int i = 0;
int max = -1;
for (i; i < candiesSize; ++i)
{
if (max < candies[i])
{
max = candies[i];
}
}
for (i = 0; i < candiesSize; ++i)
{
if (candies[i] + extraCandies >= max)
{
ans[i] = true;
}
else
{
ans[i] = false;
}
}
*returnSize = candiesSize;
return ans;
}
1588. 所有奇数长度子数组的和
原题链接: 1588. 所有奇数长度子数组的和
分析
如果多维枚举,时间复杂度为 O(n^3)
那如果利用前缀和, 可以将最内层循环时间复杂度优化为 O(1)。
代码
int sumOddLengthSubarrays(int* arr, int arrSize)
{
if (NULL == arr)
return 0;
int prefixSums[arrSize + 1];
memset(prefixSums, 0, sizeof(prefixSums));
for (int i = 0; i < arrSize; i++)
{
prefixSums[i + 1] = prefixSums[i] + arr[i];
}
int sum = 0;
for (int start = 0; start < arrSize; ++start)
{
for (int length = 1; start + length <= arrSize; length += 2)
{
int end = start + length - 1;
sum += prefixSums[end + 1] - prefixSums[start];
}
}
return sum;
}
1534. 统计好三元组
原题链接:1534. 统计好三元组
代码
直接根据题目多维枚举即可
int countGoodTriplets(int* arr, int arrSize, int a, int b, int c)
{
if (NULL == arr)
return 0;
int count = 0;
for (int i = 0; i < arrSize; ++i)
{
for (int j = i + 1; j < arrSize; ++j)
{
for (int k = j + 1; k < arrSize; ++k)
{
if (fabs(arr[i] - arr[j]) <= a && fabs(arr[j] - arr[k]) <= b && fabs(arr[i] - arr[k]) <= c)
{
++count;
}
}
}
}
return count;
}
771. 宝石与石头
原题链接:771. 宝石与石头
代码
枚举
int numJewelsInStones(char * jewels, char * stones)
{
if (jewels == NULL || stones == NULL)
return 0;
int jewelsLength = strlen(jewels);
int stonesLength = strlen(stones);
int count = 0;
for (int i = 0; i < stonesLength; ++i)
{
for (int j = 0; j < jewelsLength; ++j)
{
if (stones[i] == jewels[j])
{
count++;
}
}
}
return count;
}
14. 最长公共前缀
原题链接:14. 最长公共前缀
分析
二维枚举,并在原字符串上改动,如果第一行的字符串的第 i 个字母与其他行哪个字母不同,就将 i 的位置改为字符串末尾, 即 ‘\0’。
代码
char * longestCommonPrefix(char ** strs, int strsSize)
{
if (NULL == strs || strsSize == 0)
return NULL;
for (int i = 0; i < strlen(strs[0]); ++i)
{
char c = strs[0][i];
for (int j = 0; j < strsSize; ++j)
{
if (c != strs[j][i])
{
strs[0][i] = '\0';
return strs[0];
}
}
}
return strs[0];
}
1925. 统计平方和三元组的数目
原题链接:1925. 统计平方和三元组的数目
代码
多维枚举
int countTriples(int n)
{
if(n == 1)
return 0;
int count = 0;
for(int i = 1; i < n; i++)
{
for(int j = 1; j < n; j++)
{
for(int k = 1; k <= n; k++)
{
if(i * i + j * j == k * k)
{
count++;
}
}
}
}
return count;
}