算法实战(数组篇)

26.删除有序数组中的重复项

题目详情

给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:

更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
返回 k 。

题解

int removeDuplicates(int* nums, int numsSize) {
    int i=0,count;
    for(int j=1;j<numsSize;j++){
        if(nums[i]!=nums[j])
            nums[++i]=nums[j];
    }
    count=i+1; // i是数组下标,count应该比i多1.
    return count;
}

27. 移除元素

##题目详情
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

题解

int removeElement(int* nums, int numsSize, int val) {
    int count=0; // 记录val值的个数
    for(int i=0;i<numsSize;i++){
        if(nums[i]==val) // 数组的值等于val值,count++
            count++;
        else
             nums[i-count]=nums[i];
    }
    return numsSize-count;
}

35. 搜索插入位置

题目详情

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为 O(log n) 的算法。

题解

int searchInsert(int* nums, int numsSize, int target) {
    int low=0,high=numsSize-1;
    while(low<=high){
        int mid=(low+high)/2;
        if(nums[mid]==target)
            return mid;
        else if(nums[mid]>target)
            high=mid-1;
        else
            low=mid+1;
    }
    return low; // low指向的位置是target元素应该在数组中存放的位置
}

66. 加1

题目详情

给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。

最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。

你可以假设除了整数 0 之外,这个整数不会以零开头。

题解

int* plusOne(int* digits, int digitsSize, int* returnSize) {
   for(int i=digitsSize-1;i>=0;i--){
       if(digits[i]<9){
           digits[i]++;
           (*returnSize)=digitsSize;
           return digits;
       }else{
           digits[i]=0;
       }
   }
   int* res=(int*)malloc(sizeof(int)*(digitsSize+1));
   res[0]=1;
   for(int i=1;i<digitsSize+1;i++)
        res[i]=digits[i-1];
    (*returnSize)=digitsSize+1;
    return res;     
}

88. 合并两个有序数组

题目详情

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

题解

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
    int i, j = 0, k = 0, tempNums1[nums1Size];
    for (i = 0; i < m; i++) // 移动元素到tempNums1中
        tempNums1[i] = nums1[i];
    i = 0;
    while (i < m && j < n) {
        if (tempNums1[i] < nums2[j]) {
            nums1[k++]=tempNums1[i++];
        }else{
            nums1[k++]=nums2[j++];
        }
    }
    while(i<m){
        nums1[k++]=tempNums1[i++];
    }
    while(j<n){
        nums1[k++]=nums2[j++];
    }
}

108. 将有序数组转换为二叉搜索树

题目详情

给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。

高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。

题解

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
struct TreeNode* travel(int nums[],int low,int high){
    if(low>high) return NULL;
    int mid=(low+high)/2;
    struct TreeNode* root=(struct TreeNode*)malloc(sizeof(struct TreeNode));
    root->val=nums[mid];
    root->left=travel(nums,low,mid-1);
    root->right=travel(nums,mid+1,high);
    return root;
}
 
struct TreeNode* sortedArrayToBST(int* nums, int numsSize) {
    struct TreeNode* head=travel(nums,0,numsSize-1);
    return head;
}

注意

// 第一种
struct TreeNode{
	int data;
	struct TreeNode* left;
	struct TreeNode* right;
}TLnode;

// 第二种
struct TreeNode{
	int data;
	struct TreeNode* left;
	struct TreeNode* right;
};

// 为第一种的话,函数的返回值可以写为 TLnode 或 struct TreeNode
// 为第一种的话,函数的返回值可以写为 struct TreeNode

118. 杨辉三角

题目详情

给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。

在「杨辉三角」中,每个数是它左上方和右上方的数的和。

题解

int** generate(int numRows, int* returnSize, int** returnColumnSizes){
    //返回的是二维数组,所以需要保存每一行的信息
    *returnSize = numRows;  // 返回有几列
    *returnColumnSizes = (int *)malloc(sizeof(int)*numRows);//returnColumnSizes储存杨辉三角每一行元素的个数
    int** res = (int**)malloc(sizeof(int*)*numRows);
    
    for (int i = 0; i < numRows; i++) {
        (*returnColumnSizes)[i] = i+1;
        res[i] = (int*)malloc(sizeof(int)*(i+1));
        res[i][0] = 1;
        res[i][i] = 1;
        for (int j = 1; j < i; j++) {
            res[i][j] = res[i-1][j] + res[i-1][j-1]; 
        }
    }
    return res;
}

119. 杨辉三角 II

题目详情

给定一个非负索引 rowIndex,返回「杨辉三角」的第 rowIndex 行。

在「杨辉三角」中,每个数是它左上方和右上方的数的和。
示例 1:

输入: rowIndex = 3
输出: [1,3,3,1]
示例 2:

输入: rowIndex = 0
输出: [1]
示例 3:

输入: rowIndex = 1
输出: [1,1]

题解

int* getRow(int rowIndex, int* returnSize) {
    *returnSize = (rowIndex + 1);
    int** arr = (int**)malloc(sizeof(int*) * (rowIndex+1));
    int i, j;
    for (i = 0; i < rowIndex+1; i++) {
        arr[i] = (int*)malloc(sizeof(int) * (i + 1));
        arr[i][0] = 1;
        arr[i][i] = 1;
        for (j = 1; j < i; j++) {
            arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j];
        }
    }
    return arr[rowIndex];
}

136. 只出现一次的数字

题目详情

给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。

示例 1 :

输入:nums = [2,2,1]
输出:1
示例 2 :

输入:nums = [4,1,2,1,2]
输出:4
示例 3 :

输入:nums = [1]
输出:1

题解

int singleNumber(int* nums, int numsSize) {
    int res=0;
    for(int i=0;i<numsSize;i++)
        res^=nums[i];
    return res;
}

169. 多数元素

题目详情

给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

示例 1:

输入:nums = [3,2,3]
输出:3
示例 2:

输入:nums = [2,2,1,1,1,2,2]
输出:2

题解

int majorityElement(int* nums, int numsSize) {
    int i, vote = 0,
           elector; // vote 投票数 elector 选举者(把数组里面的数字看做选举者)
    for (i = 0; i < numsSize; i++) {
        if (!vote) {
            elector = nums[i];
        }
        if (elector == nums[i])
            vote++;
        else
            vote--;
    }
    return elector;
}

摩尔投票算法

该算法的核心就是对拼消耗

摩尔投票算法的优点

时间复杂度低:算法只需要遍历数组两次,时间复杂度为O(n),其中n是数组长度。
空间复杂度低:算法只需要常数级的额外空间,因此空间复杂度为O(1)。 ●
高效:适用于大规模数据,能够在较短时间内找到主要元素。

摩尔投票算法的缺点

  1. 不适用于所有情况:==算法要求主要元素的出现次数超过一半,因此对于没有主要元素的情况不适用。 ==
  2. 需要额外验证:算法找到候选主要元素后,还需要额外的遍历来验证其是否真的满足条件。
    摩尔投票算法

217. 存在重复元素

题目详情

给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false 。

示例 1:

输入:nums = [1,2,3,1]
输出:true
示例 2:

输入:nums = [1,2,3,4]
输出:false
示例 3:

输入:nums = [1,1,1,3,3,4,3,2,4,2]
输出:true

题解

int cmpfunc(const void* a, const void* b) { return (*(int*)a - *(int*)b); }

bool containsDuplicate(int* nums, int numsSize) {
    qsort(nums, numsSize, sizeof(int), cmpfunc);
    for (int i = 0; i < numsSize-1; i++) {
        if (nums[i] == nums[i+1])
            return true;
    }
    return false;
}

219. 存在重复元素 II

题目详情

给你一个整数数组 nums 和一个整数 k ,判断数组中是否存在两个 不同的索引 i 和 j ,满足 nums[i] == nums[j] 且 abs(i - j) <= k 。如果存在,返回 true ;否则,返回 false 。

示例 1:

输入:nums = [1,2,3,1], k = 3
输出:true
示例 2:

输入:nums = [1,0,1,1], k = 1
输出:true
示例 3:

输入:nums = [1,2,3,1,2,3], k = 2
输出:false

题解

typedef struct{
    int data;
    int index;
}record;

int cmp(int* a,int* b){
    return (*(record*)a).data-(*(record*)b).data;
}


bool containsNearbyDuplicate(int* nums, int numsSize, int k) {
    record temp[numsSize]; // 采用辅助数组
    for(int i=0;i<numsSize;i++){
       temp[i].data=nums[i];
       temp[i].index=i;
    }
    qsort(temp,numsSize,sizeof(record),cmp);

    for (int i = 0; i < numsSize-1; i++) {
            if (temp[i].data == temp[i+1].data && abs(temp[i].index - temp[i+1].index) <= k)
                return true;
    }
    return false;
}

228. 汇总区间

题目详情

给定一个 无重复元素 的 有序 整数数组 nums 。

返回 恰好覆盖数组中所有数字 的 最小有序 区间范围列表 。也就是说,nums 的每个元素都恰好被某个区间范围所覆盖,并且不存在属于某个范围但不属于 nums 的数字 x 。

列表中的每个区间范围 [a,b] 应该按如下格式输出:

“a->b” ,如果 a != b
“a” ,如果 a == b

示例 1:

输入:nums = [0,1,2,4,5,7]
输出:[“0->2”,“4->5”,“7”]
解释:区间范围是:
[0,2] --> “0->2”
[4,5] --> “4->5”
[7,7] --> “7”
示例 2:

输入:nums = [0,2,3,4,6,8,9]
输出:[“0”,“2->4”,“6”,“8->9”]
解释:区间范围是:
[0,0] --> “0”
[2,4] --> “2->4”
[6,6] --> “6”
[8,9] --> “8->9”

题解

char** summaryRanges(int* nums, int numsSize, int* returnSize) {
    char** ret = malloc(sizeof(char*) * numsSize);
    *returnSize = 0;
    int i = 0;
    while (i < numsSize) {
        int low = i;
        i++;
        while (i < numsSize && nums[i] == nums[i - 1] + 1) {
            i++;
        }
        int high = i - 1;
        char* temp = malloc(sizeof(char) * 25);
        sprintf(temp, "%d", nums[low]);
        if (low < high) {
            sprintf(temp + strlen(temp), "->");
            sprintf(temp + strlen(temp), "%d", nums[high]);
        }
        ret[(*returnSize)++] = temp;
    }
    return ret;
}

268.丢失的数字

题目详情

给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。

示例 1:

输入:nums = [3,0,1]
输出:2
解释:n = 3,因为有 3 个数字,所以所有的数字都在范围 [0,3] 内。2 是丢失的数字,因为它没有出现在 nums 中。
示例 2:

输入:nums = [0,1]
输出:2
解释:n = 2,因为有 2 个数字,所以所有的数字都在范围 [0,2] 内。2 是丢失的数字,因为它没有出现在 nums 中。
示例 3:

输入:nums = [9,6,4,2,3,5,7,0,1]
输出:8
解释:n = 9,因为有 9 个数字,所以所有的数字都在范围 [0,9] 内。8 是丢失的数字,因为它没有出现在 nums 中。
示例 4:

输入:nums = [0]
输出:1
解释:n = 1,因为有 1 个数字,所以所有的数字都在范围 [0,1] 内。1 是丢失的数字,因为它没有出现在 nums 中。

题解


int cmp(const void* a, const void* b) { return *((int*)a) - *((int*)b); }

int missingNumber(int* nums, int numsSize) {
    qsort(nums, numsSize, sizeof(int), cmp);
    int i = 0;
    if (nums[i] != 0)
        return 0;
    for (i = 1; i < numsSize; i++) {
        if (nums[i - 1] + 1 != nums[i])
            break;
    }
    return nums[i - 1] + 1;
}

283.移动零

题目详情

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

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

示例 1:

输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
示例 2:

输入: nums = [0]
输出: [0]

题解

void moveZeroes(int* nums, int numsSize) {
    int i, k = 0, count = 0; // k负责记录0出现的次数
    for (i = 0; i < numsSize; i++) {
        if (nums[i] != 0)
            nums[k++] = nums[i];
    }
    for (i = k; i < numsSize; i++)
        nums[i] = 0;
}

349.两个数组的交集

题目详情

给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]
示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的

题解

int cmp(const void* a,const void* b){
    return (*(int*)a-*(int*)b);
}

int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size,int* returnSize) {
    int i,count=0,k=0,j=0, assist[1000] = {0};
    int* arr = (int*)malloc(sizeof(int) * ((nums1Size > nums2Size) ? nums1Size : nums2Size));
    for (i = 0; i < nums1Size; i++) // 存储nums1各数出现的次数
        assist[nums1[i]]++;
    for(i=0;i<nums2Size;i++){
        if(assist[nums2[i]]>=1)
            arr[k++]=nums2[i];
    }
    if(k==0){
        *returnSize=0;
        return arr;
    }
    qsort(arr,k,sizeof(int),cmp);
    for(i=1;i<k;i++)
        if(arr[i]!=arr[j])
            arr[++j]=arr[i];
    *returnSize=j+1;
    return arr;
}

350. 两个数组的交集 II

题目详情

给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]
示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]

题解

int cmp(const void* a, const void* b) { return *(int*)a - *(int*)b; }

int* intersect(int* nums1, int nums1Size, int* nums2, int nums2Size,
               int* returnSize) {
    int i = 0, j = 0, k = 0;
    int* arr = malloc(sizeof(int) * (nums1Size > nums2Size ? nums1Size : nums2Size));
    qsort(nums1, nums1Size, sizeof(int), cmp);
    qsort(nums2, nums2Size, sizeof(int), cmp);
    while (i < nums1Size && j < nums2Size) {
        if (nums1[i] == nums2[j]) {
            arr[k++] = nums1[i];
            i++;
            j++;
        } else if (nums1[i] < nums2[j])
            i++;
        else
            j++;
    }
    *returnSize = k;
    return arr;
}

414. 第三大的数

题目详情

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

示例 1:

输入:[3, 2, 1]
输出:1
解释:第三大的数是 1 。
示例 2:

输入:[1, 2]
输出:2
解释:第三大的数不存在, 所以返回最大的数 2 。
示例 3:

输入:[2, 2, 3, 1]
输出:1
解释:注意,要求返回第三大的数,是指在所有不同数字中排第三大的数。
此例中存在两个值为 2 的数,它们都排第二。在所有不同数字中排第三大的数为 1 。

题解

int thirdMax(int* nums, int numsSize) {
    int i;
    long max[3] = {LONG_MIN, LONG_MIN, LONG_MIN};
    for (i = 0; i < numsSize; i++) {
        if (nums[i] > max[0]) {
            max[2] = max[1];
            max[1] = max[0];
            max[0] = nums[i];
        } else if (nums[i] < max[0] && nums[i] > max[1]) {
            max[2] = max[1];
            max[1] = nums[i];
        } else if (nums[i] < max[1] && nums[i] > max[2]) {
            max[2] = nums[i];
        }
    }
    if (max[2] == LONG_MIN)
        return max[0];
    else
        return max[2];
}

448. 找到所有数组消失的数字

题目详情

给你一个含 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]

题解

int* findDisappearedNumbers(int* nums, int numsSize, int* returnSize) {
    int i = 0,k=0;
    int* arr = malloc(sizeof(int) * (numsSize+1));
    int *ret=malloc(sizeof(int)*numsSize);
    for (i = 1; i <= numsSize; i++)
        arr[i] = 0;
    // 出现的位置1
    for (i = 0; i < numsSize; i++)
        arr[nums[i]] = 1;
    for(i=1;i<=numsSize;i++)
        if(arr[i]==0)
            ret[k++]=i;
    *returnSize=k;
    return ret;
}

455. 分发饼干

题目详情

假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。

对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。

示例 1:

输入: g = [1,2,3], s = [1,1]
输出: 1
解释:
你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。
虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。
所以你应该输出1。
示例 2:

输入: g = [1,2], s = [1,2,3]
输出: 2
解释:
你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。
你拥有的饼干数量和尺寸都足以让所有孩子满足。
所以你应该输出2.

题解

int cmp(const void* a, const void* b) { return (*(int*)a - *(int*)b); }
int findContentChildren(int* g, int gSize, int* s, int sSize) {
    int i = 0, j = 0, count = 0;
    // 进行排序
    qsort(g, gSize, sizeof(int), cmp);
    qsort(s, sSize, sizeof(int), cmp);

    while (i < sSize && j < gSize) {
        // 饼干如果大于孩子的胃口 i++; j++; s是饼干 g是孩子的胃口
        if (s[i] >= g[j]) {
            i++;
            j++;
            count++;
        } else
            i++;
    }
    return count;
}

496. 下一个更大元素 I

nums1 中数字 x 的 下一个更大元素 是指 x 在 nums2 中对应位置 右侧 的 第一个 比 x 大的元素。

给你两个 没有重复元素 的数组 nums1 和 nums2 ,下标从 0 开始计数,其中nums1 是 nums2 的子集。

对于每个 0 <= i < nums1.length ,找出满足 nums1[i] == nums2[j] 的下标 j ,并且在 nums2 确定 nums2[j] 的 下一个更大元素 。如果不存在下一个更大元素,那么本次查询的答案是 -1 。

返回一个长度为 nums1.length 的数组 ans 作为答案,满足 ans[i] 是如上所述的 下一个更大元素 。

示例 1:

输入:nums1 = [4,1,2], nums2 = [1,3,4,2].
输出:[-1,3,-1]
解释:nums1 中每个值的下一个更大元素如下所述:

  • 4 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。
  • 1 ,用加粗斜体标识,nums2 = [1,3,4,2]。下一个更大元素是 3 。
  • 2 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。
    示例 2:

输入:nums1 = [2,4], nums2 = [1,2,3,4].
输出:[3,-1]
解释:nums1 中每个值的下一个更大元素如下所述:

  • 2 ,用加粗斜体标识,nums2 = [1,2,3,4]。下一个更大元素是 3 。
  • 4 ,用加粗斜体标识,nums2 = [1,2,3,4]。不存在下一个更大元素,所以答案是 -1 。

题解

int* nextGreaterElement(int* nums1, int nums1Size, int* nums2, int nums2Size,
                        int* returnSize) {
    *returnSize = nums1Size;
    int k = 0, m;
    int* arr = malloc(sizeof(int) * nums1Size);
    for (int i = 0; i < nums1Size; i++) {
        int j = 0;
        while (j < nums2Size && nums1[i] != nums2[j])
            j++;
        int k = j + 1;
        while (k < nums2Size && nums2[k] < nums2[j])
            k++;
        arr[i] = k < nums2Size ? nums2[k] : -1;
    }
    return arr;
}

506. 相对名次

题目详情

给你一个长度为 n 的整数数组 score ,其中 score[i] 是第 i 位运动员在比赛中的得分。所有得分都 互不相同 。

运动员将根据得分 决定名次 ,其中名次第 1 的运动员得分最高,名次第 2 的运动员得分第 2 高,依此类推。运动员的名次决定了他们的获奖情况:

名次第 1 的运动员获金牌 “Gold Medal” 。
名次第 2 的运动员获银牌 “Silver Medal” 。
名次第 3 的运动员获铜牌 “Bronze Medal” 。
从名次第 4 到第 n 的运动员,只能获得他们的名次编号(即,名次第 x 的运动员获得编号 “x”)。
使用长度为 n 的数组 answer 返回获奖,其中 answer[i] 是第 i 位运动员的获奖情况。

示例 1:

输入:score = [5,4,3,2,1]
输出:[“Gold Medal”,“Silver Medal”,“Bronze Medal”,“4”,“5”]
解释:名次为 [1st, 2nd, 3rd, 4th, 5th] 。
示例 2:

输入:score = [10,3,8,9,4]
输出:[“Gold Medal”,“5”,“Bronze Medal”,“Silver Medal”,“4”]
解释:名次为 [1st, 5th, 3rd, 2nd, 4th] 。

题解

typedef struct record {
    int data;
    int index;
} record;

int cmp(const void* a, const void* b) {
    return (*(record*)b).data - (*(record*)a).data;
}

char** findRelativeRanks(int* score, int scoreSize, int* returnSize) {
    // 申请动态二维数组
    char** arr = malloc(sizeof(char*) * scoreSize);
    record recordRanks[scoreSize];
    for (int i = 0; i < scoreSize; i++) {
        recordRanks[i].data = score[i];
        recordRanks[i].index = i;
    }
    qsort(recordRanks, scoreSize, sizeof(record), cmp);
    for (int i = 0; i < scoreSize; i++) {
        char* temp = malloc(sizeof(char) * 25);
        if (i == 0) // 第一名
            sprintf(temp, "%s", "Gold Medal");
        else if (i == 1)
            sprintf(temp, "%s", "Silver Medal");
        else if (i == 2)
            sprintf(temp, "%s", "Bronze Medal");
        else
            sprintf(temp, "%d", i + 1);
        arr[recordRanks[i].index] = temp;
    }
    *returnSize = scoreSize;
    return arr;
}

561. 数组拆分

题目详情

给定长度为 2n 的整数数组 nums ,你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), …, (an, bn) ,使得从 1 到 n 的 min(ai, bi) 总和最大。

返回该 最大总和 。

示例 1:

输入:nums = [1,4,3,2]
输出:4
解释:所有可能的分法(忽略元素顺序)为:

  1. (1, 4), (2, 3) -> min(1, 4) + min(2, 3) = 1 + 2 = 3
  2. (1, 3), (2, 4) -> min(1, 3) + min(2, 4) = 1 + 2 = 3
  3. (1, 2), (3, 4) -> min(1, 2) + min(3, 4) = 1 + 3 = 4
    所以最大总和为 4
    示例 2:

输入:nums = [6,2,6,5,1,2]
输出:9
解释:最优的分法为 (2, 1), (2, 5), (6, 6). min(2, 1) + min(2, 5) + min(6, 6) = 1 + 2 + 6 = 9

题解

int cmp(const void* a, const void* b) { return *(int*)a - *(int*)b; }

int arrayPairSum(int* nums, int numsSize) {
    int min, ret = 0;
    qsort(nums, numsSize, sizeof(int), cmp);
    for (int i = 0; i < numsSize; i++) { // 遍历找到每两个的最小值
        if (i % 2 == 0)
            min = nums[i];
        else {
            min = min < nums[i] ? min : nums[i];
            ret += min;
        }
    }
    return ret;
}

575. 分糖果

题目详情

Alice 有 n 枚糖,其中第 i 枚糖的类型为 candyType[i] 。Alice 注意到她的体重正在增长,所以前去拜访了一位医生。

医生建议 Alice 要少摄入糖分,只吃掉她所有糖的 n / 2 即可(n 是一个偶数)。Alice 非常喜欢这些糖,她想要在遵循医生建议的情况下,尽可能吃到最多不同种类的糖。

给你一个长度为 n 的整数数组 candyType ,返回: Alice 在仅吃掉 n / 2 枚糖的情况下,可以吃到糖的 最多 种类数。

示例 1:

输入:candyType = [1,1,2,2,3,3]
输出:3
解释:Alice 只能吃 6 / 2 = 3 枚糖,由于只有 3 种糖,她可以每种吃一枚。
示例 2:

输入:candyType = [1,1,2,3]
输出:2
解释:Alice 只能吃 4 / 2 = 2 枚糖,不管她选择吃的种类是 [1,2]、[1,3] 还是 [2,3],她只能吃到两种不同类的糖。
示例 3:

输入:candyType = [6,6,6,6]
输出:1
解释:Alice 只能吃 4 / 2 = 2 枚糖,尽管她能吃 2 枚,但只能吃到 1 种糖。

题解

int cmp(const void* a, const void* b) { return *(int*)a - *(int*)b; }

int distributeCandies(int* candyType, int candyTypeSize) {
    qsort(candyType, candyTypeSize, sizeof(int), cmp);
    int i, k = 0, sum = 0, count = 0;
    for (i = 0; i < candyTypeSize; i++)
        if (candyType[k] != candyType[i])
            candyType[++k] = candyType[i];
            
    if(k+1>candyTypeSize/2)
        return candyTypeSize/2;
    else
        return k+1; 
}

605. 种花问题

题目详情

假设有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花不能种植在相邻的地块上,它们会争夺水源,两者都会死去。

给你一个整数数组 flowerbed 表示花坛,由若干 0 和 1 组成,其中 0 表示没种植花,1 表示种植了花。另有一个数 n ,能否在不打破种植规则的情况下种入 n 朵花?能则返回 true ,不能则返回 false 。

示例 1:

输入:flowerbed = [1,0,0,0,1], n = 1
输出:true
示例 2:

输入:flowerbed = [1,0,0,0,1], n = 2
输出:false

题解

bool canPlaceFlowers(int* flowerbed, int flowerbedSize, int n) {
    int i = 0, count = n;
    if (n == 0)
        return true;
    for (i = 0; i < flowerbedSize; i++) {
        int pre = i > 0 ? flowerbed[i - 1] : 0;
        int cur = flowerbed[i];
        int next = i < flowerbedSize - 1 ? flowerbed[i + 1] : 0;
        if (pre == 0 && cur == 0 && next == 0) {
            flowerbed[i] = 1;
            count--;
        }
        if (count == 0)
            return true;
    }
    return false;
}

628. 三个数的最大乘积

题目详情

给你一个整型数组 nums ,在数组中找出由三个数组成的最大乘积,并输出这个乘积。

示例 1:

输入:nums = [1,2,3]
输出:6
示例 2:

输入:nums = [1,2,3,4]
输出:24
示例 3:

输入:nums = [-1,-2,-3]
输出:-6

题解

int cmp(const void* a, const void* b) { return *(int*)a - *(int*)b; }

int maximumProduct(int* nums, int numsSize) {
    int maximum = INT_MIN;
    qsort(nums, numsSize, sizeof(int), cmp); // 进行排序
    maximum = nums[numsSize - 1] * nums[numsSize - 2] * nums[numsSize - 3];
    maximum = maximum > nums[0] * nums[1] * nums[numsSize - 1]? maximum: nums[0] * nums[1] * nums[numsSize - 1];
    return maximum;
}

643. 子数组最大平均数 I

题目详情

给你一个由 n 个元素组成的整数数组 nums 和一个整数 k 。

请你找出平均数最大且 长度为 k 的连续子数组,并输出该最大平均数。

任何误差小于 10-5 的答案都将被视为正确答案。

示例 1:

输入:nums = [1,12,-5,-6,50,3], k = 4
输出:12.75
解释:最大平均数 (12-5-6+50)/4 = 51/4 = 12.75
示例 2:

输入:nums = [5], k = 1
输出:5.00000

题解

double findMaxAverage(int* nums, int numsSize, int k) {
    int i, start, end;
    double sum = 0, res;
    // 计算前k个数字之和
    for (i = 0; i < k; i++)
        sum += nums[i];
    res = sum;
    for (start = 0, end = k; end < numsSize; end++, start++) {
        sum += nums[end] - nums[start]; 
        res = sum > res ? sum : res;
    }
    return res / k;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

CPanMirai

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

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

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

打赏作者

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

抵扣说明:

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

余额充值