贪心算法练习题

376. 摆动序列

中等

860

相关企业

如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为 摆动序列 。第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。

  • 例如, [1, 7, 4, 9, 2, 5] 是一个 摆动序列 ,因为差值 (6, -3, 5, -7, 3) 是正负交替出现的。

  • 相反,[1, 4, 7, 2, 5] 和 [1, 7, 4, 5, 5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。

子序列 可以通过从原始序列中删除一些(也可以不删除)元素来获得,剩下的元素保持其原始顺序。

给你一个整数数组 nums ,返回 nums 中作为 摆动序列 的 最长子序列的长度 。

示例 1:

输入:nums = [1,7,4,9,2,5]
输出:6
解释:整个序列均为摆动序列,各元素之间的差值为 (6, -3, 5, -7, 3) 。

示例 2:

输入:nums = [1,17,5,10,13,15,10,5,16,8]
输出:7
解释:这个序列包含几个长度为 7 摆动序列。
其中一个是 [1, 17, 10, 13, 10, 16, 8] ,各元素之间的差值为 (16, -7, 3, -3, 6, -8) 。

示例 3:

输入:nums = [1,2,3,4,5,6,7,8,9]
输出:2

提示:

  • 1 <= nums.length <= 1000
  • 0 <= nums[i] <= 1000
    int up[numsSize];
    memset(up,0,sizeof(int)*numsSize);
    up[0]=1;
    int down[numsSize];
    memset(down,0,sizeof(int)*numsSize);
    down[0]=1;
    int max=0;
    for(int i=0;i<numsSize;i++){
        for(int j=0;j<i;j++){
            if(nums[i]>nums[j]){
                down[i]=fmax(up[j]+1,down[i]);
            }
            if(nums[i]<nums[j]){
                up[i]=fmax(down[j]+1,up[i]);
            }
            
        }
        if(up[i]>max){
            max=up[i];
        }
        if(down[i]>max){
            max=down[i];
        }
    }
    return max;
}

402. 移掉 K 位数字

中等

923

相关企业

给你一个以字符串表示的非负整数 num 和一个整数 k ,移除这个数中的 k 位数字,使得剩下的数字最小。请你以字符串形式返回这个最小的数字。

示例 1 :

输入:num = "1432219", k = 3
输出:"1219"
解释:移除掉三个数字 4, 3, 和 2 形成一个新的最小的数字 1219 。

示例 2 :

输入:num = "10200", k = 1
输出:"200"
解释:移掉首位的 1 剩下的数字为 200. 注意输出不能有任何前导零。

示例 3 :

输入:num = "10", k = 2
输出:"0"
解释:从原数字移除所有的数字,剩余为空就是 0 。

提示:

  • 1 <= k <= num.length <= 105
  • num 仅由若干位数字(0 - 9)组成
  • 除了 0 本身之外,num 不含任何前导零
char * removeKdigits(char * num, int k){
    int length=strlen(num),top=-1,i=0;
    char *stack=(char *)malloc(sizeof(char)*(length+1));
    for(i;i<length;i++)
    {
        while(top!=-1&&stack[top]>num[i]&&k>0)//出栈
        {
            top--;
            k--;
        }
        if(num[i]!='0'||top!=-1)//入栈,删除了0之前的所有有效数字就不入栈
        stack[++top]=num[i];
    }
    while(k>0&&top>-1)
    {
        top--;
        k--;
    }
    if(top==-1)//里面空空如也
    stack[++top]='0';
    stack[++top]='\0';
    return stack;
}

406. 根据身高重建队列

提示

中等

1.5K

相关企业

假设有打乱顺序的一群人站成一个队列,数组 people 表示队列中一些人的属性(不一定按顺序)。每个 people[i] = [hi, ki] 表示第 i 个人的身高为 hi ,前面 正好 有 ki 个身高大于或等于 hi 的人。

请你重新构造并返回输入数组 people 所表示的队列。返回的队列应该格式化为数组 queue ,其中 queue[j] = [hj, kj] 是队列中第 j 个人的属性(queue[0] 是排在队列前面的人)。

示例 1:

输入:people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]
输出:[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]
解释:
编号为 0 的人身高为 5 ,没有身高更高或者相同的人排在他前面。
编号为 1 的人身高为 7 ,没有身高更高或者相同的人排在他前面。
编号为 2 的人身高为 5 ,有 2 个身高更高或者相同的人排在他前面,即编号为 0 和 1 的人。
编号为 3 的人身高为 6 ,有 1 个身高更高或者相同的人排在他前面,即编号为 1 的人。
编号为 4 的人身高为 4 ,有 4 个身高更高或者相同的人排在他前面,即编号为 0、1、2、3 的人。
编号为 5 的人身高为 7 ,有 1 个身高更高或者相同的人排在他前面,即编号为 1 的人。
因此 [[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]] 是重新构造后的队列。

示例 2:

输入:people = [[6,0],[5,0],[4,0],[3,2],[2,2],[1,4]]
输出:[[4,0],[5,0],[2,2],[3,2],[1,4],[6,0]]

提示:

  • 1 <= people.length <= 2000
  • 0 <= hi <= 106
  • 0 <= ki < people.length
  • 题目数据确保队列可以被重建
int cmp(const void* _a, const void* _b) {
    int *a = *(int**)_a, *b = *(int**)_b;
    return a[0] == b[0] ? a[1] - b[1] : b[0] - a[0];
}

int** reconstructQueue(int** people, int peopleSize, int* peopleColSize, int* returnSize, int** returnColumnSizes) {
    qsort(people, peopleSize, sizeof(int*), cmp);
    int** ans = malloc(sizeof(int*) * peopleSize);
    *returnSize = 0;
    *returnColumnSizes = malloc(sizeof(int) * peopleSize);
    for (int i = 0; i < peopleSize; i++) {
        (*returnColumnSizes)[i] = 2;
    }
    for (int i = 0; i < peopleSize; ++i) {
        int* person = people[i];
        (*returnSize)++;
        for (int j = (*returnSize) - 1; j > person[1]; j--) {
            ans[j] = ans[j - 1];
        }
        int* tmp = malloc(sizeof(int) * 2);
        tmp[0] = person[0], tmp[1] = person[1];
        ans[person[1]] = tmp;
    }
    return ans;
}

435. 无重叠区间

中等

902

相关企业

给定一个区间的集合 intervals ,其中 intervals[i] = [starti, endi] 。返回 需要移除区间的最小数量,使剩余区间互不重叠 

示例 1:

输入: intervals = [[1,2],[2,3],[3,4],[1,3]]
输出: 1
解释: 移除 [1,3] 后,剩下的区间没有重叠。

示例 2:

输入: intervals = [ [1,2], [1,2], [1,2] ]
输出: 2
解释: 你需要移除两个 [1,2] 来使剩下的区间没有重叠。

示例 3:

输入: intervals = [ [1,2], [2,3] ]
输出: 0
解释: 你不需要移除任何区间,因为它们已经是无重叠的了。

提示:

  • 1 <= intervals.length <= 105
  • intervals[i].length == 2
  • -5 * 104 <= starti < endi <= 5 * 104
int cmp(const void* ptr1, const void* ptr2) {
    int* a = *(int**)ptr1;
    int* b = *(int**)ptr2;
    return a[1] == b[1] ? a[0] - b[0] : a[1] - b[1];
}

int eraseOverlapIntervals(int** intervals, int intervalsSize, int* intervalsColSize){

    qsort(intervals, intervalsSize, sizeof(int*), cmp);  //区间右端点排序
    int del = 0;  //需要删除的区间个数
    int res = intervals[0][1];  //初始化起始位置
    for (int i = 1; i < intervalsSize; i++) {
        if (res > intervals[i][0]) { //如果右端大于左端,则删掉下一个区间
            del++;
        } else { //如果右端小于等于左端,则保留下一个区间
            res = intervals[i][1];  //以下一个区间为当前区间进行新一轮比较
        }
    }
    return del;  //返回需要删除的区间个数

}

581. 最短无序连续子数组

中等

1K

相关企业

给你一个整数数组 nums ,你需要找出一个 连续子数组 ,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。

请你找出符合题意的 最短 子数组,并输出它的长度。

示例 1:

输入:nums = [2,6,4,8,10,9,15]
输出:5
解释:你只需要对 [6, 4, 8, 10, 9] 进行升序排序,那么整个表都会变为升序排序。

示例 2:

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

示例 3:

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

提示:

  • 1 <= nums.length <= 104
  • -105 <= nums[i] <= 105
int cmp(const void * a, const void * b)//升序子函数
{
    return *(int *)a - *(int *)b;
}
/*
*int findUnsortedSubarray(int* nums, int numsSize)
int findUnsortedSubarray:寻找不符合区间
int* nums:数组
int numsSize:数组长度
返回值:不符合区间长度
*/
int findUnsortedSubarray(int* nums, int numsSize)
{
    int * ans = malloc(sizeof(int) * numsSize);
    memcpy(ans, nums, sizeof(int) * numsSize);
    qsort(ans, numsSize, sizeof(int), cmp);//初始化变量
    int i, j;
    int n = -1, m = -1; 
    for(i = 0; i < numsSize; i++)//判断左边第一个不同点
    {
        if(ans[i] != nums[i])
        {
            n = i;
            break;
        }
    }
    for(j = numsSize-1; j >= 0; j--)//判断右边第一个不同点
    {
        if(ans[j] != nums[j])
        {
            m = j;
            break;
        }
    }
    return n == -1 ? 0 : m - n + 1; 
}
控制台

猜你喜欢

转载自blog.csdn.net/weixin_63357306/article/details/129269029