LeetCode 每日一题 2070. 每一个查询的最大美丽值

2070. 每一个查询的最大美丽值

给你一个二维整数数组 items ,其中 items[i] = [pricei, beautyi] 分别表示每一个物品的 价格 和 美丽值 。
同时给你一个下标从 0 开始的整数数组 queries 。对于每个查询 queries[j] ,你想求出价格小于等于 queries[j] 的物品中,最大的美丽值 是多少。如果不存在符合条件的物品,那么查询的结果为 0 。
请你返回一个长度与 queries 相同的数组 answer,其中 answer[j]是第 j 个查询的答案。
示例 1:
输入:items = [[1,2],[3,2],[2,4],[5,6],[3,5]], queries = [1,2,3,4,5,6]
输出:[2,4,5,5,6,6]
解释:
-queries[0]=1 ,[1,2] 是唯一价格 <= 1 的物品。所以这个查询的答案为 2 。
-queries[1]=2 ,符合条件的物品有 [1,2] 和 [2,4] 。
它们中的最大美丽值为 4 。
-queries[2]=3 和 queries[3]=4 ,符合条件的物品都为 [1,2] ,[3,2] ,[2,4] 和 [3,5] 。
它们中的最大美丽值为 5 。
-queries[4]=5 和 queries[5]=6 ,所有物品都符合条件。
所以,答案为所有物品中的最大美丽值,为 6 。
示例 2:
输入:items = [[1,2],[1,2],[1,3],[1,4]], queries = [1]
输出:[4]
解释:
每个物品的价格均为 1 ,所以我们选择最大美丽值 4 。
注意,多个物品可能有相同的价格和美丽值。
示例 3:
输入:items = [[10,1000]], queries = [5]
输出:[0]
解释:
没有物品的价格小于等于 5 ,所以没有物品可以选择。
因此,查询的结果为 0 。
提示:
1 <= items.length, queries.length <= 105
items[i].length == 2
1 <= pricei, beautyi, queries[j] <= 109

题解

题目要求找到满足价格小于等于 queries[j] 的所有物品中的最大美丽值
那么最直接的做法就是对每一个 queries[j] 都去遍历 items 数组,找到所有价格<=queries[j] 的物品并记录其中的最大值

但是这道题目的难度是 1724
那么很显然这种直接的做法会超时
时间复杂度为O(n^2)
接下来就是找到更优的做法

思路1 二分查找 + 数组预处理

因为要求解每一个 queries[j] 对应的值,那么肯定是要遍历 queries 数组的
那么我们可以优化的地方就是 查找价格小于等于 queries[j] 的所有物品以及其中最大的美丽值

  • 查找价格小于等于 queries[j] 的所有物品
    • 我们可以先对数组 items 按照价格进行排序,那么我们就只需要找到小于等于 queries[j] 的最大的价格,其本身以及左边便是所有价格小于等于 queries[j] 的物品
    • 对于查找有序数组中的小于等于某一数值的最大数,可以使用二分查找,类似题目有744. 寻找比目标字母大的最小字母
  • 满足条件的所有物品中最大美丽值
    • 此前我们找到了小于等于queries[j]的最大数,我们记此数在item中的下标为 i,我们自然不能从 0 到 i 进行遍历再找出其最大美丽值,这样时间复杂度依旧会是 n^2
    • 我们可以对数组进行提前处理,从而减少这一步的操作
    • 对于每一个位置 i 我们都需要知道从 0 到 i 的最大美丽值,那么不难想到,我们可以对排序之后的 item 的美丽值修改为 0 到 i 的最大美丽值,即对 item 进行遍历,每次遍历都记录下当前最大的美丽值并将其修改为 item[i][1]

简而言之,解题过程就是先对 items 按照价格进行排序,然后利用数组排序的性质一次遍历将 items[i][1] 中记录的美丽值修改为 0 到 i 的最大美丽值
那么我们只需要通过二分查找找到 <= queries[j] 的最大价格的位置 i ,其最大美丽值就是修改后的最大美丽值


代码如下↓

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */

int* maximumBeauty(int** items, int itemsSize, int* itemsColSize, int* queries, int queriesSize, int* returnSize) {
    int cmp(const void* a,const void* b)
    {
        return (*(int**)a)[0] - (*(int**)b)[0];
    }
    qsort(items,itemsSize,sizeof(items[0]),cmp);

    int be[itemsSize];
    int max=0;
    for(int i=0;i<itemsSize;i++)
    {
        if(items[i][1]>max)
        {
            max=items[i][1];
        }
        be[i]=max;
    }
    int pr[itemsSize];
    for(int i=0;i<itemsSize;i++)
    {
        pr[i]=items[i][0];
    }
    *returnSize=queriesSize;
    int* re = (int*)malloc(sizeof(int)*queriesSize);
    int f=0;
    for(int i=0;i<queriesSize;i++)
    {
        int res=-1;
        int x=queries[i];
        int l=0;
        int r=itemsSize-1;
        int m=(l+r)/2;
        while(l<=r)
        {
            m=(l+r)/2;
            if(pr[m]>x)
            {
                r=m-1;
            }
            else
            {
                res=m;
                l=m+1;
            }
        }
        if(res==-1)
        {
            re[f++]=0;
        }
        else
        {
            re[f++]=be[res];
        }
    }
    return re;
}

思路2 双指针 + 处理queries

这里只提供思路(才不是因为代码懒得写

同样的我们先对数组 items 按照价格进行排序

假如 数组 queries 是升序的,对于 queries[0],我们需要找到所有 价格<=queries[0] 的物品并求其中最大美丽值 a
接着对于 queries[1],我们需要找到所有 价格<=queries[1] 的物品并求其中最大美丽值,但是由于上一步我们已经知道了所有 价格<=queries[0] 的物品中的最大美丽值 a,那么我们就只需要找价格大于 queries[0] 且小于等于queries[1]的物品中的最大美丽值b,然后取 max(a,b)
接下来就以此类推

由于每次寻找最大美丽值都是在前一次 queries[i-1] 与 queries[i] 中进行寻找,
那么直到循环结束查找的操作也就执行了 n 次,所以循环的时间复杂度依旧是 n
时间复杂度的瓶颈在排序 nlogn

你可能感兴趣的:(LeetCode题目题解,leetcode,算法,数据结构,c语言)