【Leetcode Sheet】Weekly Practice 9

Leetcode Test

2582 递枕头(9.26)

n 个人站成一排,按从 1n 编号。

最初,排在队首的第一个人拿着一个枕头。每秒钟,拿着枕头的人会将枕头传递给队伍中的下一个人。一旦枕头到达队首或队尾,传递方向就会改变,队伍会继续沿相反方向传递枕头。

  • 例如,当枕头到达第 n 个人时,TA 会将枕头传递给第 n - 1 个人,然后传递给第 n - 2 个人,依此类推。

给你两个正整数 ntime ,返回 time 秒后拿着枕头的人的编号。

提示:

  • 2 <= n <= 1000
  • 1 <= time <= 1000

【模拟】走到头的时候clk反转

int passThePillow(int n, int time){
    int cnt=0,pos=1,clk=0;
    while(1){
        if(cnt==time){
            break;
        }
        if(clk==0){
            pos++;
            if(pos==n){
                clk=1;
            }
        }
        else{
            pos--;
            if(pos==1){
                clk=0;
            }
        }
        cnt++;
    }
    return pos;
}

1333 餐厅过滤器(9.27)

给你一个餐馆信息数组 restaurants,其中 restaurants[i] = [idi, ratingi, veganFriendlyi, pricei, distancei]。你必须使用以下三个过滤器来过滤这些餐馆信息。

其中素食者友好过滤器 veganFriendly 的值可以为 true 或者 false,如果为 true 就意味着你应该只包括 veganFriendlyi 为 true 的餐馆,为 false 则意味着可以包括任何餐馆。此外,我们还有最大价格 maxPrice 和最大距离 maxDistance 两个过滤器,它们分别考虑餐厅的价格因素和距离因素的最大值。

过滤后返回餐馆的 id,按照 *rating* 从高到低排序。如果 *rating* 相同,那么按 *id* 从高到低排序。简单起见, veganFriendlyiveganFriendlytrue 时取值为 1,为 false 时,取值为 0 。

提示:

  • 1 <= restaurants.length <= 10^4
  • restaurants[i].length == 5
  • 1 <= idi, ratingi, pricei, distancei <= 10^5
  • 1 <= maxPrice, maxDistance <= 10^5
  • veganFriendlyiveganFriendly 的值为 0 或 1 。
  • 所有 idi 各不相同。

【模拟 + 排序】

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

int cmp(void *a,void *b){
    int *r1=*(int**)a,*r2=*(int**)b;
    return r1[1]!=r2[1] ? r2[1]-r1[1] : r2[0]-r1[0];
}

int* filterRestaurants(int** restaurants, int restaurantsSize, int* restaurantsColSize, int veganFriendly, int maxPrice, int maxDistance, int* returnSize){
    int **potential=malloc(sizeof(int*)*restaurantsSize);
    int cnt=0;
    for(int i=0;i<restaurantsSize;i++){
        if(maxPrice<restaurants[i][3]){
            continue;
        }
        else if(maxDistance<restaurants[i][4]){
            continue;
        }
        else if(veganFriendly==1 && restaurants[i][2]==0){
            continue;
        }
        else{
            potential[cnt++]=restaurants[i];
        }
    }

    qsort(potential,cnt,sizeof(int*),cmp);
    int *ret=malloc(sizeof(int)*cnt);
    for(int i=0;i<cnt;i++){
        ret[i]=potential[i][0];
    }

    *returnSize=cnt;
    return ret;
}

2251 花期内花的数目(9.28)

给你一个下标从 0 开始的二维整数数组 flowers ,其中 flowers[i] = [starti, endi] 表示第 i 朵花的 花期startiendi (都 包含)。同时给你一个下标从 0 开始大小为 n 的整数数组 peoplepeople[i] 是第 i 个人来看花的时间。

请你返回一个大小为 n 的整数数组 answer ,其中 answer[i]是第 i 个人到达时在花期内花的 数目

提示:

  • 1 <= flowers.length <= 5 * 104
  • flowers[i].length == 2
  • 1 <= starti <= endi <= 109
  • 1 <= people.length <= 5 * 104
  • 1 <= people[i] <= 109

【二分 + 排序】

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

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

int binarysearch(int *arr,int left,int right,int target){
    while(left<=right){
        int mid=left+(right-left)/2;
        if(arr[mid]>=target){
            right=mid-1;
        }
        else{
            left=mid+1;
        }
    }
    return right;
}

int* fullBloomFlowers(int** flowers, int flowersSize, int* flowersColSize, int* people, int peopleSize, int* returnSize){
    int n=flowersSize,m=peopleSize;
    int *start=(int*)malloc(sizeof(int)*n),*end=(int*)malloc(sizeof(int)*n);
    for(int i=0;i<n;i++){
        start[i]=flowers[i][0];
        end[i]=flowers[i][1];
    }

    qsort(start,n,sizeof(int),cmp);
    qsort(end,n,sizeof(int),cmp);

    int *ret=(int*)malloc(sizeof(int)*m);
    *returnSize=m;
    for(int i=0;i<m;i++){
        //search for start & end
        int on=binarysearch(start,0,n-1,people[i]+1);
        int off=binarysearch(end,0,n-1,people[i]);
        ret[i]=on-off;
    }
    return ret;
}

605 种花问题(9.29)

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

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

提示:

  • 1 <= flowerbed.length <= 2 * 104
  • flowerbed[i]01
  • flowerbed 中不存在相邻的两朵花
  • 0 <= n <= flowerbed.length

【贪心】遇到可以种的地方就种下

bool canPlaceFlowers(int* flowerbed, int flowerbedSize, int n){
    for(int i=0;i<flowerbedSize;i++){
        if( (i==0 || flowerbed[i-1]==0) && flowerbed[i]==0 && (i==flowerbedSize-1 || flowerbed[i+1]==0) ){
            n--;
            i++;//the next position cannot plant flower
        }
    }
    return n<=0;
}

2136 全部开花的最早一天(9.30)

你有 n 枚花的种子。每枚种子必须先种下,才能开始生长、开花。播种需要时间,种子的生长也是如此。给你两个下标从 0 开始的整数数组 plantTimegrowTime ,每个数组的长度都是 n

  • plantTime[i]播种i 枚种子所需的 完整天数 。每天,你只能为播种某一枚种子而劳作。无须 连续几天都在种同一枚种子,但是种子播种必须在你工作的天数达到 plantTime[i] 之后才算完成。
  • growTime[i] 是第 i 枚种子完全种下后生长所需的 完整天数 。在它生长的最后一天 之后 ,将会开花并且永远 绽放

从第 0 开始,你可以按 任意 顺序播种种子。

返回所有种子都开花的 最早 一天是第几天。

提示:

  • n == plantTime.length == growTime.length
  • 1 <= n <= 105
  • 1 <= plantTime[i], growTime[i] <= 104

【贪心 + 排序】2136. 全部开花的最早一天 - 力扣(LeetCode)

typedef struct {
    int plant;
    int flower;
} Grass;

//按照flower(grow)从大到小排序
int Compare(void *a, void *b)
{
    Grass *aa = (Grass *)a;
    Grass *bb = (Grass *)b;
    return bb->flower - aa->flower; 
}

int earliestFullBloom(int* plantTime, int plantTimeSize, int* growTime, int growTimeSize){
    //定义grass-data
    Grass *data = (Grass *)calloc(plantTimeSize, sizeof(Grass));
    for (int i = 0; i < plantTimeSize; i++) {
        data[i].plant = plantTime[i];
        data[i].flower = growTime[i];
    }

    qsort(data, plantTimeSize, sizeof(Grass), Compare);

    int ans = 0;
    int time = 0;
    for (int i = 0; i < plantTimeSize; i++) {
        //累计种植时间 + 当前植物种植时间 + 当前植物开花时间,最大值更新
        ans = fmax(ans, time + data[i].plant + data[i].flower);
        //增加上一个植物消耗的种植时间,即累计种植时间
        time += data[i].plant;
    }
    return ans;
}

121 买卖股票的最佳时机(10.1)

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0

提示:

  • 1 <= prices.length <= 105
  • 0 <= prices[i] <= 104

【枚举】时间复杂度O(n)

min 维护的是 prices[i]左侧元素的最小值

int maxProfit(int* prices, int pricesSize){
    int n=pricesSize,max=0,min=prices[0];
    for(int i=0;i<n;i++){
        max=fmax(max,prices[i]-min);
        //更新最大利益
        min=fmin(min,prices[i]);
        //更新最小值
    }
    return max;
}

122 买卖股票的最佳时机Ⅱ(10.2)

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。

在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。

返回 你能获得的 最大 利润

提示:

  • 1 <= prices.length <= 3 * 104
  • 0 <= prices[i] <= 104

【贪心】递增小区间的总和计算

int maxProfit(int* prices, int pricesSize){
    int ret=0;
    for(int i=1;i<pricesSize;i++){
        ret+=fmax(0,prices[i]-prices[i-1]);
    }
    return ret;
}

【动态规划】
d p [ i ] [ 0 ] 表示第 i 天交易完后手里没有股票的最大利润 dp[i][0]表示第i天交易完后手里没有股票的最大利润 dp[i][0]表示第i天交易完后手里没有股票的最大利润

d p [ i ] [ 1 ] 表示第 i 天交易完后手里持有一支股票的最大利润 dp[i][1]表示第i天交易完后手里持有一支股票的最大利润 dp[i][1]表示第i天交易完后手里持有一支股票的最大利润

d p [ i ] [ 0 ] = m a x ( d p [ i − 1 ] [ 0 ] , d p [ i − 1 ] [ 1 ] + p r i c e s [ i ] ) dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i]) dp[i][0]=max(dp[i1][0],dp[i1][1]+prices[i])

d p [ i ] [ 1 ] = m a x ( d p [ i − 1 ] [ 1 ] , d p [ i − 1 ] [ 0 ] − p r i c e s [ i ] ) dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i]) dp[i][1]=max(dp[i1][1],dp[i1][0]prices[i])

没有股票的迭代:前一天没有股票的利润,或,前一天有股票且今天卖出

有股票的迭代:前一天有股票的利润,或,前一天没有股票且今天买入

int maxProfit(int* prices, int pricesSize) {
    int dp[pricesSize][2];
    dp[0][0] = 0, dp[0][1] = -prices[0];
    for (int i = 1; i < pricesSize; ++i) {
        dp[i][0] = fmax(dp[i - 1][0], dp[i - 1][1] + prices[i]);
        dp[i][1] = fmax(dp[i - 1][1], dp[i - 1][0] - prices[i]);
    }
    return dp[pricesSize - 1][0];
}

你可能感兴趣的:(随想录,leetcode,算法,数据结构)