LeetCode数组相关算法题(1)【C语言版】

2011. 执行操作后的变量值

存在一种仅支持 4 种操作和 1 个变量 X 的编程语言:

  • ++XX++ 使变量 X 的值 1
  • --XX-- 使变量 X 的值 1

最初,X 的值是 0

给你一个字符串数组 operations ,这是由操作组成的一个列表,返回执行所有操作后,X最终值

示例 1:

复制代码
输入:operations = ["--X","X++","X++"]
输出:1
解释:操作按下述步骤执行:
最初,X = 0
--X:X 减 1 ,X =  0 - 1 = -1
X++:X 加 1 ,X = -1 + 1 =  0
X++:X 加 1 ,X =  0 + 1 =  1

示例 2:

复制代码
输入:operations = ["++X","++X","X++"]
输出:3
解释:操作按下述步骤执行: 
最初,X = 0
++X:X 加 1 ,X = 0 + 1 = 1
++X:X 加 1 ,X = 1 + 1 = 2
X++:X 加 1 ,X = 2 + 1 = 3

示例 3:

复制代码
输入:operations = ["X++","++X","--X","X--"]
输出:0
解释:操作按下述步骤执行:
最初,X = 0
X++:X 加 1 ,X = 0 + 1 = 1
++X:X 加 1 ,X = 1 + 1 = 2
--X:X 减 1 ,X = 2 - 1 = 1
X--:X 减 1 ,X = 1 - 1 = 0

提示:

  • 1 <= operations.length <= 100
  • operations[i] 将会是 "++X""X++""--X""X--"
cpp 复制代码
#include <stdio.h>

// 函数声明:计算最终的x值
// 参数:operations - 操作数组,每个元素是一个字符串操作
//       operationsSize - 操作的数量
// 返回:最终的x值
int finalValueAfterOperations(char** operations, int operationsSize) {
    int x = 0; // 初始化x为0
    for (int i = 0; i < operationsSize; ++i) { // 遍历每个操作
        // 检查操作的第二个字符是否为'+',如果是则x加1,否则x减1
        if (*(*(operations + i) + 1) == '+') {
            x++;
        } else {
            x--;
        }
    }
    return x; // 返回最终的x值
}

int main() {
    // 定义并初始化一个包含三个操作的数组
    char* operations[100] = {"--X", "X++", "X++"};
    // 调用函数并打印结果
    printf("%d ", finalValueAfterOperations(operations, 3));
    return 0;
}

1929. 数组串联

给你一个长度为 n 的整数数组 nums 。请你构建一个长度为 2n 的答案数组 ans ,数组下标从 0 开始计数 ,对于所有 0 <= i < ni ,满足下述所有要求:

  • ans[i] == nums[i]
  • ans[i + n] == nums[i]

具体而言,ans 由两个 nums 数组 串联 形成。

返回数组ans

示例 1:

复制代码
输入:nums = [1,2,1]
输出:[1,2,1,1,2,1]
解释:数组 ans 按下述方式形成:
- ans = [nums[0],nums[1],nums[2],nums[0],nums[1],nums[2]]
- ans = [1,2,1,1,2,1]

示例 2:

复制代码
输入:nums = [1,3,2,1]
输出:[1,3,2,1,1,3,2,1]
解释:数组 ans 按下述方式形成:
- ans = [nums[0],nums[1],nums[2],nums[3],nums[0],nums[1],nums[2],nums[3]]
- ans = [1,3,2,1,1,3,2,1]

提示:

  • n == nums.length
  • 1 <= n <= 1000
  • 1 <= nums[i] <= 1000
cpp 复制代码
#include <stdio.h>
#include <cstdlib>


int* getConcatenation(int* nums, int numsSize, int* returnSize) {
    *returnSize = numsSize*2;
    int* ans = (int*) malloc(*returnSize * sizeof (int));
    if (ans == NULL){
        exit(1);
    }
    for (int i = 0; i < numsSize; ++i) {
        ans[i] = nums[i];
        ans[i+numsSize] = nums[i];
    }
    return ans;
}

int main() {
    int nums[3]= {1,2,1};
    int returnSize = 0;
    int* ans = getConcatenation(nums,3,&returnSize);
    for (int i = 0; i < returnSize; ++i) {
        printf("%d ",ans[i]);
    }
    return 0;
}

1720. 解码异或后的数组

未知 整数数组 arrn 个非负整数组成。

经编码后变为长度为 n - 1 的另一个整数数组 encoded ,其中 encoded[i] = arr[i] XOR arr[i + 1] 。例如,arr = [1,0,2,1] 经编码后得到 encoded = [1,2,3]

给你编码后的数组 encoded 和原数组 arr 的第一个元素 firstarr[0])。

请解码返回原数组 arr 。可以证明答案存在并且是唯一的。

示例 1:

复制代码
输入:encoded = [1,2,3], first = 1
输出:[1,0,2,1]
解释:若 arr = [1,0,2,1] ,那么 first = 1 且 encoded = [1 XOR 0, 0 XOR 2, 2 XOR 1] = [1,2,3]

示例 2:

复制代码
输入:encoded = [6,2,7,3], first = 4
输出:[4,2,0,7,4]

提示:

  • 2 <= n <= 104
  • encoded.length == n - 1
  • 0 <= encoded[i] <= 105
  • 0 <= first <= 105
cpp 复制代码
#include <cstdio>    // 包含标准输出函数 printf 的头文件
#include <cstdlib>   // 包含动态内存分配函数 malloc 的头文件


int* decode(int* encoded, int encodedSize, int first, int* returnSize) {
    // 计算解码后数组的大小,即编码数组的大小 + 1
    *returnSize = encodedSize + 1;

    // 动态分配内存,用于存储解码后的数组
    int* ans = (int*)malloc(*returnSize * sizeof(int));

    // 初始化第一个元素为 first
    int i = 0;
    ans[i] = first;

    // 根据编码数组解码后续元素
    while (i + 1 <= encodedSize) {
        // 运用异或运算解码:ans[i+1] = ans[i] ^ encoded[i]
        ans[i + 1] = ans[i] ^ encoded[i];
        i++;
    }

    // 返回解码后的数组
    return ans;
}

int main() {
    // 定义一个编码数组
    int encoded[3] = {1, 2, 3};

    // 定义返回的大小
    int returnSize;

    // 调用 decode 函数解码数组
    int* ans = decode(encoded, 3, 1, &returnSize);

    // 打印解码后的数组
    for (int i = 0; i < returnSize; ++i) {
        printf("%d ", ans[i]);
    }

    // 通常需要释放动态分配的内存,但在此示例中没有提供 free 代码(仅演示)
    // free(ans);

    return 0; // 程序结束,返回 0
}

2574. 左右元素和的差值

给你一个下标从 0 开始的整数数组 nums ,请你找出一个下标从 0 开始的整数数组 answer ,其中:

  • answer.length == nums.length
  • answer[i] = |leftSum[i] - rightSum[i]|

其中:

  • leftSum[i] 是数组 nums 中下标 i 左侧元素之和。如果不存在对应的元素,leftSum[i] = 0
  • rightSum[i] 是数组 nums 中下标 i 右侧元素之和。如果不存在对应的元素,rightSum[i] = 0

返回数组 answer

示例 1:

复制代码
输入:nums = [10,4,8,3]
输出:[15,1,11,22]
解释:数组 leftSum 为 [0,10,14,22] 且数组 rightSum 为 [15,11,3,0] 。
数组 answer 为 [|0 - 15|,|10 - 11|,|14 - 3|,|22 - 0|] = [15,1,11,22] 。

示例 2:

复制代码
输入:nums = [1]
输出:[0]
解释:数组 leftSum 为 [0] 且数组 rightSum 为 [0] 。
数组 answer 为 [|0 - 0|] = [0] 。

方式一,直接循环加循环哈哈

cpp 复制代码
#include <cstdio>
#include <cstdlib>
#include <cmath>


int* leftRightDifference(int* nums, int numsSize, int* returnSize) {
    *returnSize = numsSize;
    int* ans = (int*) malloc(*returnSize*sizeof (int ));
    int l = 0,r = 0,leftSum = 0,rightSum = 0;
    for (int i = 0; i < numsSize; ++i) {
        l = i-1;
        while (true){
            if (l < 0){
                leftSum += 0;
                break;
            } else {
                leftSum += nums[l--];
            }
        }
        r = i+1;
        while (true){
            if (r>=numsSize){
                rightSum += 0;
                break;
            } else{
                rightSum+=nums[r++];
            }
        }
        ans[i] = abs((leftSum-rightSum));
        rightSum = 0;
        leftSum = 0;
    }
    return ans;
}

int main() {
    int nums[4] = {10,4,8,3};
    int returnSize = 4;
    int* ans = leftRightDifference(nums,4,&returnSize);
    for (int i = 0; i < returnSize; ++i) {
        printf("%d ",ans[i]);
    }
    return 0;
}

大佬们写的

cpp 复制代码
#include <cstdio>    // 包含标准输出函数 printf 的头文件
#include <cstdlib>   // 包含动态内存分配函数 malloc、abs 的头文件


int* leftRightDifference(int* nums, int numsSize, int* returnSize) {
    *returnSize = numsSize; // 设置返回数组的大小,与输入数组大小相同

    // 动态分配内存,用于存储结果数组
    int* ans = (int*)malloc(*returnSize * sizeof(int));

    // 计算输入数组的总和
    int sum = 0;
    for (int i = 0; i < numsSize; ++i) {
        sum += nums[i]; // 累加数组元素之和
    }

    int left = 0; // 初始化左侧元素之和
    for (int j = 0; j < numsSize; ++j) {
        // 计算右侧元素之和:总和 - 当前元素 - 左侧元素之和
        int right = sum - nums[j] - left;

        // 计算左右侧和的绝对差,并存储到结果数组
        ans[j] = abs(left - right);

        // 累加当前元素到左侧元素之和,用于下一个元素的计算
        left += nums[j];
    }

    return ans; // 返回结果数组
}

int main() {
    int nums[4] = {10,4,8,3}; // 输入数组
    int returnSize = 4; // 返回数组的大小

    // 调用 leftRightDifference 函数,传入输入数组和返回大小的指针
    int* ans = leftRightDifference(nums,4,&returnSize);

    // 打印结果数组
    for (int i = 0; i < returnSize; ++i) {
        printf("%d ", ans[i]);
    }

    // 释放动态分配的内存(在实际项目中应该释放,但在此示例中未提供)
    // free(ans);

    return 0; // 程序结束,返回 0
}

1365. 有多少小于当前数字的数字

给你一个数组 nums,对于其中每个元素 nums[i],请你统计数组中比它小的所有数字的数目。

换而言之,对于每个 nums[i] 你必须计算出有效的 j 的数量,其中 j 满足 j != i nums[j] < nums[i]

以数组形式返回答案。

示例 1:

复制代码
输入:nums = [8,1,2,2,3]
输出:[4,0,1,1,3]
解释: 
对于 nums[0]=8 存在四个比它小的数字:(1,2,2 和 3)。 
对于 nums[1]=1 不存在比它小的数字。
对于 nums[2]=2 存在一个比它小的数字:(1)。 
对于 nums[3]=2 存在一个比它小的数字:(1)。 
对于 nums[4]=3 存在三个比它小的数字:(1,2 和 2)。

示例 2:

复制代码
输入:nums = [6,5,4,8]
输出:[2,1,0,3]

示例 3:

复制代码
输入:nums = [7,7,7,7]
输出:[0,0,0,0]

提示:

  • 2 <= nums.length <= 500
  • 0 <= nums[i] <= 100
cpp 复制代码
#include <cstdio>    // 包含标准输出函数 printf 的头文件
#include <cstdlib>   // 包含动态内存分配函数 malloc 的头文件


int* smallerNumbersThanCurrent(int* nums, int numsSize, int* returnSize) {
    *returnSize = numsSize; // 设置返回数组的大小为输入数组大小

    // 动态分配内存用于存储结果数组
    int* ans = (int*)malloc(*returnSize * sizeof(int));

    int count = 0; // 用于计数比当前元素小的数目

    // 遍历每个元素
    for (int i = 0; i < numsSize; ++i) {
        int current = nums[i]; // 获取当前元素

        // 遍历整个数组,统计比当前元素小的数目
        for (int j = 0; j < numsSize; ++j) {
            if (current > nums[j]) {
                count++; // 遇到比当前元素小的元素,计数加一
            }
        }

        // 将计数结果存入结果数组
        ans[i] = count;

        // 重置计数器,准备下一个元素的统计
        count = 0;
    }

    return ans; // 返回结果数组
}

int main() {
    int nums[4] = {6,5,4,8}; // 输入数组
    int returnSize = 4;      // 返回数组的大小

    // 调用函数,并获取结果数组
    int* ans = smallerNumbersThanCurrent(nums, 4, &returnSize);

    // 打印结果数组
    for (int i = 0; i < returnSize; ++i) {
        printf("%d ", ans[i]);
    }

    // 释放动态分配的内存
    free(ans);

    return 0; // 程序结束,返回 0
}

1732. 找到最高海拔

有一个自行车手打算进行一场公路骑行,这条路线总共由 n + 1 个不同海拔的点组成。自行车手从海拔为 0 的点 0 开始骑行。

给你一个长度为 n 的整数数组 gain ,其中 gain[i] 是点 i 和点 i + 1净海拔高度差0 <= i < n)。请你返回 最高点的海拔

示例 1:

复制代码
输入:gain = [-5,1,5,0,-7]
输出:1
解释:海拔高度依次为 [0,-5,-4,1,1,-6] 。最高海拔为 1 。

示例 2:

复制代码
输入:gain = [-4,-3,-2,-1,4,3,2]
输出:0
解释:海拔高度依次为 [0,-4,-7,-9,-10,-6,-3,-1] 。最高海拔为 0 。

提示:

  • n == gain.length
  • 1 <= n <= 100
  • -100 <= gain[i] <= 100
cpp 复制代码
#include <cstdio>    // 包含标准输出函数 printf 的头文件
#include <cstdlib>   // 包含动态内存分配函数 malloc 的头文件


int largestAltitude(int* gain, int gainSize) {
    int ansSize = gainSize + 1; // 海拔数组的大小(起点海拔加上每一步的净高度差)
    int* ans = (int*)malloc(ansSize * sizeof(int)); // 动态分配内存存储海拔数组

    ans[0] = 0; // 初始化起点海拔为 0
    int max = 0; // 初始化最高海拔为 0

    // 计算每个点的海拔高度,并跟踪最大值
    for (int i = 1; i < ansSize; ++i) {
        ans[i] = ans[i - 1] + gain[i - 1]; // 当前海拔 = 前一点海拔 + 当前净高度差
        if (max < ans[i]) { // 如果当前海拔高于当前最大值,更新最大值
            max = ans[i];
        }
    }

   
    free(ans);// 释放内存

    return max; // 返回最高海拔高度
}

int main() {
    int nums[5] = {-5, 1, 5, 0, -7}; // 输入的净海拔高度差数组
    printf("%d\n", largestAltitude(nums, 5)); // 调用函数并打印最高海拔高度值

    return 0; // 程序结束,

1464. 数组中两元素的最大乘积

给你一个整数数组 nums,请你选择数组的两个不同下标 ij 使 (nums[i]-1)*(nums[j]-1) 取得最大值。

请你计算并返回该式的最大值。

示例 1:

复制代码
输入:nums = [3,4,5,2]
输出:12 
解释:如果选择下标 i=1 和 j=2(下标从 0 开始),则可以获得最大值,(nums[1]-1)*(nums[2]-1) = (4-1)*(5-1) = 3*4 = 12 。 

示例 2:

复制代码
输入:nums = [1,5,4,5]
输出:16
解释:选择下标 i=1 和 j=3(下标从 0 开始),则可以获得最大值 (5-1)*(5-1) = 16 。

示例 3:

复制代码
输入:nums = [3,7]
输出:12

提示:

  • 2 <= nums.length <= 500
  • 1 <= nums[i] <= 10^3
cpp 复制代码
#include <cstdio>    // 包含标准输入输出头文件



// 其实就是找最大的两个数
int maxProduct(int* nums, int numsSize) {
    int low, high, mid, temp; // 定义辅助变量用于排序过程

    // 使用插入排序(基于二分查找的优化)对数组进行升序排序
    for (int i = 1; i < numsSize; ++i) {
        low = 0;             // 初始比较范围左边界
        high = i - 1;        // 初始比较范围右边界
        temp = nums[i];      // 待插入元素

        // 使用二分查找确定插入位置
        while (low <= high) {
            mid = (low + high) / 2; // 中间位置
            if (nums[mid] > temp) { // 如果中间元素大于待插入元素
                low = mid + 1;      // 插入位置应在中间位置右侧
            } else {                // 如果中间元素小于或等于待插入元素
                high = mid - 1;     // 插入位置应在中间位置左侧
            }
        }

        // 将插入位置后的元素向后移动一位,为待插入元素腾出空间
        for (int j = i - 1; j >= low; --j) {
            nums[j + 1] = nums[j];
        }

        // 将待插入元素放入正确的位置
        nums[low] = temp;
    }

    // 排序完成后,数组前两个元素是最大的两个元素
    // 返回这两个元素(每个元素减一后的乘积)
    return (nums[0] - 1) * (nums[1] - 1);
}

int main() {
    int nums[4] = {3,4,5,2}; // 输入数组
    printf("%d ", maxProduct(nums, 4)); // 调用函数并打印结果
    return 0; // 程序结束,返回 0
}

2496. 数组中字符串的最大值

一个由字母和数字组成的字符串的 定义如下:

  • 如果字符串 包含数字,那么值为该字符串在 10 进制下的所表示的数字。
  • 否则,值为字符串的 长度

给你一个字符串数组 strs ,每个字符串都只由字母和数字组成,请你返回 strs 中字符串的 最大值

示例 1:

复制代码
输入:strs = ["alic3","bob","3","4","00000"]
输出:5
解释:
- "alic3" 包含字母和数字,所以值为长度 5 。
- "bob" 只包含字母,所以值为长度 3 。
- "3" 只包含数字,所以值为 3 。
- "4" 只包含数字,所以值为 4 。
- "00000" 只包含数字,所以值为 0 。
所以最大的值为 5 ,是字符串 "alic3" 的值。

示例 2:

复制代码
输入:strs = ["1","01","001","0001"]
输出:1
解释:
数组中所有字符串的值都是 1 ,所以我们返回 1 。

提示:

  • 1 <= strs.length <= 100
  • 1 <= strs[i].length <= 9
  • strs[i] 只包含小写英文字母和数字。
cpp 复制代码
#include <cstdio>    // 包含标准输入输出头文件
#include <cstdlib>
#include <cstring>

// 定义一个函数,返回字符串数组中的最大值
int maximumValue(char** strs, int strsSize) {
    int max = 0; // 初始化最大值为0

    for (int i = 0; i < strsSize; ++i) { // 遍历每一个字符串
        bool flag = true; // 标志位,标记当前字符串是否全为数字

        // 遍历字符串中的每一个字符,判断是否全为数字
        for (int j = 0; j < strlen(strs[i]); ++j) {
            if (!(strs[i][j] >= '0' && strs[i][j] <= '9')) { // 如果字符不是数字
                flag = false; // 标记当前字符串存在非数字字符
                break;        // 退出字符检查循环
            } else {
                flag = true;  // 当前字符是数字,继续保持标记为真
            }
        }

        // 根据flag判断当前字符串是否全为数字
        if (flag) { // 如果全部是数字
            // 将字符串转换为整数,并比较大小
            if (atoi(strs[i]) > max) {
                max = atoi(strs[i]); // 更新最大值
            }
        } else { // 如果存在非数字字符
            // 比较字符串的长度
            int currentLength = strlen(strs[i]);
            if (currentLength > max) {
                max = currentLength; // 更新最大值
            }
        }
    }

    return max; // 返回计算得到的最大值
}

int main() {
    char strs[4][9] = {"1","01","001","0001"}; // 定义一个二维字符数组,初始化为4个字符串

    // 创建一个指针数组,用于存放字符数组的指针
    char** point = (char **) malloc(5 * sizeof(char *)); // 动态分配内存

    // 将二维字符数组中的每个字符串的地址赋值给指针数组
    for (int i = 0; i < 4; ++i) {
        point[i] = strs[i];
    }

    // 调用 maximumValue 函数,并打印结果
    printf("%d ", maximumValue(point, 4));

    return 0; // 程序结束,返回0
}

1979. 找出数组的最大公约数

给你一个整数数组 nums ,返回数组中最大数和最小数的 最大公约数

两个数的 最大公约数 是能够被两个数整除的最大正整数。

示例 1:

复制代码
输入:nums = [2,5,6,9,10]
输出:2
解释:
nums 中最小的数是 2
nums 中最大的数是 10
2 和 10 的最大公约数是 2

示例 2:

复制代码
输入:nums = [7,5,6,8,3]
输出:1
解释:
nums 中最小的数是 3
nums 中最大的数是 8
3 和 8 的最大公约数是 1

示例 3:

复制代码
输入:nums = [3,3]
输出:3
解释:
nums 中最小的数是 3
nums 中最大的数是 3
3 和 3 的最大公约数是 3

提示:

  • 2 <= nums.length <= 1000
  • 1 <= nums[i] <= 1000
cpp 复制代码
#include <cstdio>    // 包含标准输入输出头文件,用于printf等函数

// 定义一个函数findGCD,用于计算数组中所有整数的最大公约数(GCD)
// 参数:nums - 指向整数数组的指针;numsSize - 数组的大小
int findGCD(int* nums, int numsSize) {
    // 初始化max和min为数组的第一个元素
    int max = *nums;
    int min = *nums;
    
    // 遍历数组,找到最大值和最小值
    for (int i = 0; i < numsSize; ++i) {
        // 如果当前元素大于max,则更新max
        if (max < *(nums + i)) {
            max = *(nums + i);
        }
        // 如果当前元素小于min,则更新min
        if (min > *(nums + i)) {
            min = *(nums + i);
        }
    }
    
    // 使用更相减损术计算最大公约数
    // 更相减损术:通过不断减去较小数来找到两个数的最大公约数
    while (min != max) {
        // 如果max大于min,将max减去min
        if (max > min) {
            max -= min;
        } else {
            // 否则,将min减去max
            min -= max;
        }
    }
    
    // 返回计算得到的最大公约数
    return max;
}

// 程序的主函数
int main() {
    // 定义一个整数数组nums,并初始化
    int nums[5] = {2, 5, 6, 9, 10};
    
    // 调用findGCD函数,计算数组的最大公约数,并打印结果
    printf("%d ", findGCD(nums, 5));
    
    // 程序结束,返回0
    return 0;
}

485. 最大连续 1 的个数

给定一个二进制数组 nums , 计算其中最大连续 1 的个数。

示例 1:

复制代码
输入:nums = [1,1,0,1,1,1]
输出:3
解释:开头的两位和最后的三位都是连续 1 ,所以最大连续 1 的个数是 3.

示例 2:

复制代码
输入:nums = [1,0,1,1,0,1]
输出:2

提示:

  • 1 <= nums.length <= 105
  • nums[i] 不是 0 就是 1.
cpp 复制代码
#include <cstdio>    // 包含标准输入输出头文件,用于使用printf等函数

// 定义一个函数,用于找到数组中连续1的最大数量
int findMaxConsecutiveOnes(int* nums, int numsSize) {
    int maxCount = 0;    // 记录最大连续1的数量
    int currentCount = 0;    // 记录当前连续1的数量
    
    // 遍历数组中的每一个元素
    for (int i = 0; i < numsSize; ++i) {
        if (nums[i] == 1) {
            currentCount++;    // 当前元素为1,增加当前连续1的数量
        } else {
            currentCount = 0;    // 当前元素不为1,重置当前连续1的数量
        }
        
        // 如果当前连续1的数量大于最大连续1的数量,则更新最大值
        if (currentCount > maxCount) {
            maxCount = currentCount;
        }
    }
    
    return maxCount;    // 返回最大连续1的数量
}

int main() {
    int nums[6] = {1, 1, 1, 1, 1, 1};    // 定义一个包含6个1的整数数组
    printf("%d ", findMaxConsecutiveOnes(nums, 6));    // 调用函数并打印结果
    return 0;    // 程序结束,返回0
}

414. 第三大的数

给你一个非空数组,返回此数组中 第三大的数 。如果不存在,则返回数组中最大的数。

示例 1:

复制代码
输入:[3, 2, 1]
输出:1
解释:第三大的数是 1 。

示例 2:

复制代码
输入:[1, 2]
输出:2
解释:第三大的数不存在, 所以返回最大的数 2 。

示例 3:

复制代码
输入:[2, 2, 3, 1]
输出:1
解释:注意,要求返回第三大的数,是指在所有不同数字中排第三大的数。
此例中存在两个值为 2 的数,它们都排第二。在所有不同数字中排第三大的数为 1 。
cpp 复制代码
#include <cstdio>  // 包含标准输入输出头文件

// 函数:找到数组中的第三大数
int thirdMax(int* nums, int numsSize) {
    // 归并排序(从大到小)
    int high, mid, low, temp;  // 定义变量用于排序
    for (int i = 1; i < numsSize; ++i) {  // 遍历数组,从第二个元素开始
        low = 0;  // 初始的低位指针
        high = i - 1;  // 初始的高位指针
        temp = nums[i];  // 保存当前元素的值

        // 使用二分查找确定插入位置
        while (low <= high) {
            mid = (high + low) / 2;  // 计算中间位置
            if (nums[mid] > temp) {
                low = mid + 1;  // 如果中间元素大于当前元素,调整低位指针
            } else {
                high = mid - 1;  // 否则,调整高位指针
            }
        }

        // 将插入位置后的元素向右移动
        for (int j = i - 1; j >= low; --j) {
            nums[j + 1] = nums[j];  // 元素右移
        }
        nums[low] = temp;  // 将当前元素插入正确位置
    }

    // 查找第三大数
    int prev = nums[0];  // 用于记录前一个不同的数字
    int count = 1;  // 记录不同数字的数量,默认已有一个最大的数
    int third_largest = 0;  // 用于存储第三大的数字

    // 遍历排序后的数组,统计不同数字的数量
    for (int i = 1; i < numsSize; ++i) {
        if (nums[i] != prev) {  // 如果遇到不同的数字
            count++;  // 增加不同数字的计数
            if (count == 3) {  // 如果达到第三个不同的数字
                third_largest = nums[i];  // 记录第三大的数字
                break;  // 退出循环
            }
            prev = nums[i];  // 更新前一个不同的数字
        }
    }

    // 如果整个数组中不同的数字少于三个,返回最大的数字
    if (count < 3) {
        return nums[0];  // 返回最大的数字
    }
    return third_largest;  // 返回第三大的数字
}

int main() {
    int nums[4] = {3, 2, 2, 1};  // 定义输入数组
    printf("%d ", thirdMax(nums, 4));  // 调用函数并打印结果
    return 0;  // 程序结束,返回0
}

645. 错误的集合

集合 s 包含从 1n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复

给定一个数组 nums 代表了集合 S 发生错误后的结果。

请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。

示例 1:

复制代码
输入:nums = [1,2,2,4]
输出:[2,3]

示例 2:

复制代码
输入:nums = [1,1]
输出:[1,2]
cpp 复制代码
#include <cstdio>    // 包含标准输入输出头文件
#include <cstdlib>
#define N 9  // 定义数组大小为9

// 函数:找出数组中的最大值
int findMax(int* temp, int size) {
    int max = temp[0]; // 假设数组至少有一个元素,初始最大值为数组的第一个元素
    for (int i = 1; i < size; i++) { // 遍历数组
        if (temp[i] > max) { // 如果当前元素大于max,更新max
            max = temp[i];
        }
    }
    return max; // 返回最大值
}

// 函数:找出重复出现的整数和丢失的整数,并返回结果数组
int* findErrorNums(int* nums, int numsSize, int* returnSize) {
    *returnSize = 2; // 返回数组的大小为2,包含重复和丢失的整数
    int max = findMax(nums, numsSize); // 找出数组中的最大值
    int* ans = (int*) malloc(2 * sizeof(int)); // 动态分配返回数组的空间
    int* temp = (int*) malloc((max + 2) * sizeof(int)); // 动态分配一个辅助数组,大小为max+2,确保覆盖所有可能的数字

    // 初始化辅助数组为0,记录每个数字出现的次数
    for (int i = 0; i < max + 2; ++i) {
        temp[i] = 0;
    }

    // 统计每个数字在输入数组中的出现次数
    for (int i = 0; i < numsSize; ++i) {
        temp[nums[i]]++;
    }

    // 查找重复的整数和丢失的整数
    for (int i = 0; i < max + 2; ++i) {
        if (temp[i] > 1) { // 如果某个数字出现次数超过1,说明它重复了
            ans[0] = i; // 记录重复的整数
            // 查找丢失的整数
            // 优先检查重复的数字后面的数字是否存在丢失
            if (i == 1 && temp[i + 1] == 0) { // 特殊情况:如果重复的是1,检查2是否丢失
                ans[1] = i + 1;
                return ans; // 返回结果
            }
            for (int j = i; j > 0; --j) { // 从重复数字的位置向前查找丢失的数字
                if (temp[j] == 0) { // 找到丢失的数字
                    ans[1] = j;
                    return ans; // 返回结果
                }
            }
            for (int j = i; j < max + 2; j++) { // 如果向前没找到,再向后查找丢失的数字
                if (temp[j] == 0) {
                    ans[1] = j;
                    return ans; // 返回结果
                }
            }
        }
    }
    return ans; // 返回结果
}

// 主函数
int main() {
    int nums[N] = {3, 5, 9, 4, 1, 2, 7, 8, 1}; // 定义输入数组
    int returnSize;
    int* ans = findErrorNums(nums, N, &returnSize); // 调用函数获取结果
    // 打印结果
    for (int i = 0; i < returnSize; ++i) {
        printf("%d ", ans[i]);
    }
    return 0; // 程序结束,返回0
}

697. 数组的度

给定一个非空且只包含非负数的整数数组 nums,数组的 的定义是指数组里任一元素出现频数的最大值。

你的任务是在 nums 中找到与 nums 拥有相同大小的度的最短连续子数组,返回其长度。

示例 1:

复制代码
输入:nums = [1,2,2,3,1]
输出:2
解释:
输入数组的度是 2 ,因为元素 1 和 2 的出现频数最大,均为 2 。
连续子数组里面拥有相同度的有如下所示:
[1, 2, 2, 3, 1], [1, 2, 2, 3], [2, 2, 3, 1], [1, 2, 2], [2, 2, 3], [2, 2]
最短连续子数组 [2, 2] 的长度为 2 ,所以返回 2 。

示例 2:

复制代码
输入:nums = [1,2,2,3,1,4,2]
输出:6
解释:
数组的度是 3 ,因为元素 2 重复出现 3 次。
所以 [2,2,3,1,4,2] 是最短子数组,因此返回 6 。

提示:

  • nums.length150,000 范围内。
  • nums[i] 是一个在 049,999 范围内的整数
cpp 复制代码
#include <stdio.h>
#include <stdlib.h>

// 功能:找出数组中的最大值
// 参数:nums - 数组,numsSize - 数组长度
// 返回值:数组中的最大值
int findMax(int* nums, int numsSize) {
    int max = nums[0]; // 初始化最大值为数组的第一个元素
    for (int i = 1; i < numsSize; i++) { // 遍历数组,寻找最大值
        if (nums[i] > max) {
            max = nums[i]; // 更新最大值
        }
    }
    return max;
}

// 功能:找出数组中最短的同度子数组的长度
// 参数:nums - 数组,numsSize - 数组长度
// 返回值:最短同度子数组的长度
int findShortestSubArray(int* nums, int numsSize) {
    if (numsSize == 0) return 0; // 如果数组为空,返回0

    // 使用三个数组记录每个元素的出现次数、首次出现的位置和最后一次出现的位置。
    int maxVal = findMax(nums, numsSize); // 获取数组中的最大值,用于确定数组的大小
    int* count = (int*)malloc((maxVal + 1) * sizeof(int)); // 用于记录每个元素的出现次数
    int* first = (int*)malloc((maxVal + 1) * sizeof(int)); // 用于记录每个元素首次出现的位置
    int* last = (int*)malloc((maxVal + 1) * sizeof(int));  // 用于记录每个元素最后一次出现的位置

    // 初始化三个数组
    for (int i = 0; i <= maxVal; i++) {
        count[i] = 0;     // 初始出现次数为0
        first[i] = -1;    // 初始首次出现的位置为-1
        last[i] = -1;     // 初始最后一次出现的位置为-1
    }

    // 遍历数组,填充count、first和last数组
    for (int i = 0; i < numsSize; i++) {
        int num = nums[i]; // 当前元素
        count[num]++;      // 更新出现次数
        if (first[num] == -1) { // 如果是第一次出现该元素
            first[num] = i;    // 记录首次出现的位置
        }
        last[num] = i;         // 更新最后一次出现的位置
    }

    // 找出数组中的最大度数(最大出现次数)
    int maxDegree = 0;
    for (int i = 0; i <= maxVal; i++) {
        if (count[i] > maxDegree) {
            maxDegree = count[i]; // 更新最大度数
        }
    }

    // 计算最短子数组长度
    int minLen = numsSize; // 初始化最短长度为数组长度
    for (int i = 0; i <= maxVal; i++) {
        if (count[i] == maxDegree) { // 如果该元素的出现次数等于最大度数
            int currentLen = last[i] - first[i] + 1; // 当前元素的子数组长度
            if (currentLen < minLen) {
                minLen = currentLen; // 更新最短长度
            }
        }
    }

    // 释放动态分配的内存
    free(count);
    free(first);
    free(last);

    return minLen;
}

int main() {
    int nums[] = {1, 2, 2, 3, 1}; // 示例数组
    int numsSize = sizeof(nums) / sizeof(nums[0]); // 数组长度
    printf("最短子数组长度为: %d\n", findShortestSubArray(nums, numsSize)); // 测试并打印结果
    return 0;
}

给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。

示例 1:

复制代码
输入:nums = [4,3,2,7,8,2,3,1]
输出:[5,6]

示例 2:

复制代码
输入:nums = [1,1]
输出:[2]

提示:

  • n == nums.length
  • 1 <= n <= 105
  • 1 <= nums[i] <= n
cpp 复制代码
#include <cstdio>
#include <cstdlib>


int* findDisappearedNumbers(int* nums, int numsSize, int* returnSize) {
    // 申请结果数组,大小为numsSize+1,用于存储消失的数字
    int* ans = (int*) malloc((numsSize + 1) * sizeof(int));
    // 申请辅助数组temp,大小为numsSize+1,用于计数每个数字出现的次数
    int* temp = (int*) malloc((numsSize + 1) * sizeof(int));

    // 初始化结果数组ans和辅助数组temp,将所有元素置为0
    for (int i = 0; i < numsSize + 1; ++i) {
        temp[i] = 0;
        ans[i] = 0;
    }

    // 遍历输入数组nums,统计每个数字出现的次数
    for (int i = 0; i < numsSize; ++i) {
        int num = nums[i];
        temp[num]++;  // 将对应位置的计数加1
    }

    // 遍历辅助数组temp,找出计数为0的数字,即为消失的数字
    int j = 0;
    for (int i = 1; i < numsSize + 1; ++i) {
        if (temp[i] == 0) {
            ans[j++] = i;  // 将消失的数字存入结果数组
        }
    }

    // 设置返回的大小为消失的数字的数量
    *returnSize = j;
    return ans;
}


int main() {
    int nums[] = {1,1};
    int numsSize = sizeof(nums) / sizeof(nums[0]); // 数组长度
    int returnSize = 0;
    int* ans = findDisappearedNumbers(nums,numsSize,&returnSize);
    for (int i = 0; i < returnSize; ++i) {
        printf("%d ",ans[i]);
    }
    return 0;
}

283. 移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:

复制代码
输入: nums = [0,1,0,3,12]

输出: [1,3,12,0,0]

示例 2:

复制代码
输入: nums = [0]

输出: [0]
cpp 复制代码
#include <cstdio>   // 包含标准输入输出头文件
#include <cstdlib>  // 包含标准库头文件

// 函数:将数组中的零元素移动到数组的末尾,同时保持非零元素的相对顺序
// 方法:类似冒泡排序,通过交换相邻元素将零元素向后移动
void moveZeroes(int* nums, int numsSize) {
    // 外层循环控制遍历的次数
    for (int i = numsSize - 1; i >= 0; i--) { 
        // 内层循环用于比较相邻元素并交换
        for (int j = 0; j < i; ++j) { 
            if (nums[j] == 0) { // 如果当前元素是零
                // 交换当前元素和下一个元素
                int temp = nums[j]; 
                nums[j] = nums[j + 1];
                nums[j + 1] = temp;
            }
        }
    }
    
    // 打印结果数组
    for (int i = 0; i < numsSize; ++i) {
        printf("%d ", nums[i]); 
    }
}

int main() {
    int nums[] = {0, 1, 0, 3, 12}; // 示例输入数组
    int numsSize = sizeof(nums) / sizeof(nums[0]); // 计算数组长度
    
    moveZeroes(nums, numsSize); // 调用函数处理数组
    
    return 0; // 程序结束
}
cpp 复制代码
#include <cstdio>   // 包含标准输入输出头文件
#include <cstdlib>  // 包含标准库头文件

// 功能:将数组中的零元素移动到数组的末尾,同时保持非零元素的相对顺序
// 参数:nums - 数组,numsSize - 数组长度
void moveZeroes(int* nums, int numsSize) {
    int current = 0; // 当前数组的位置,用于记录非零元素的放置位置

    // 遍历数组,将非零元素移动到数组的前面
    for (int i = 0; i < numsSize; ++i) {
        if (nums[i] != 0) { // 如果当前元素不是零
            nums[current++] = nums[i]; // 将非零元素移动到 current 指定的位置,并递增 current
        }
    }

    // 将数组中剩余的位置填充为零
    for (int i = current; i < numsSize; ++i) {
        nums[i] = 0; // 从 current 开始,将后续元素全部设置为零
    }

    // 打印处理后的数组
    for (int i = 0; i < numsSize; ++i) {
        printf("%d ", nums[i]); // 逐个打印数组元素
    }
}

int main() {
    int nums[] = {0, 1, 0, 3, 12}; // 定义示例输入数组
    int numsSize = sizeof(nums) / sizeof(nums[0]); // 计算数组长度

    moveZeroes(nums, numsSize); // 调用函数处理数组

    return 0; // 程序结束
}
相关推荐
CodeJourney.15 分钟前
DeepSeek关联PPT使用教程
数据库·人工智能·算法
xiaolin03331 小时前
146. LRU 缓存
算法·哈希·lru·双向链表
m0nesy_86801 小时前
1314--力扣情人节特别篇
java·算法·leetcode
Liu_Meihao1 小时前
【LeetCode】1. 两数之和
算法·leetcode
MiyamiKK571 小时前
leetcode_二叉树 108. 将有序数组转换为二叉搜索树
算法·leetcode·职场和发展
Wang's Blog2 小时前
数据结构与算法之数组: LeetCode 541. 反转字符串 II (Ts版)
算法·leetcode
嵌入式学习菌2 小时前
常见的排序算法:插入排序、选择排序、冒泡排序、快速排序
java·算法·排序算法
在成都搬砖的鸭鸭3 小时前
【LeetCode】时间复杂度和空间复杂度
算法·leetcode·golang·排序算法
Mercury_Lc3 小时前
【力扣 - 简单题】88. 合并两个有序数组
数据结构·算法·leetcode·acm
qy发大财3 小时前
全排列(力扣46)
算法·leetcode·职场和发展