2022-01-02每日刷题打卡

2022-01-02每日刷题打卡

飞书——每日一题

42. 接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

示例 1:

rainwatertrap.png (412×161) (leetcode-cn.com)

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。

首先我们知道,只有中间的高度小于左右两边的高度才可以接到雨水,这种情况下我们可以使用头尾双指针向中间移动遍历。准备两个值l_max和r_max,来存左右两边的最大高度。开始遍历,每次比较height[l]和heigh[r]的大小,如果l大那就可以知道左边已经出现了大于当前高度的地方,只要在右边找到大于当前高度的地方即可,我们先更新一下最大高度,看是r_max大还是height[r]大,如果height[r]大就更新一下r_max,我们计算r_max-heigh[r]的值即为我们可以接到雨水的值,如果当前我们遍历到的柱子就是最高的柱子,那自然右边不会出现更高的柱子来让我们接雨水,所以是0,如果r_max大于heigh[r]则说明右边也有高的柱子,满足了中间小两边大的条件,此时能接雨水的容量就是r_max-heigh[r],然后r–。如果是l小了则以上操作改一下即可。

class Solution {
public:
    int trap(vector<int>& height) {
        int l=0,r=height.size()-1,l_max=0,r_max=0,ans=0;
        while(l<r)
        {
            if(height[l]<height[r])
            {
                l_max=max(l_max,height[l]);
                ans+=l_max-height[l];
                l++;
            }
            else
            {
                r_max=max(r_max,height[r]);
                ans+=r_max-height[r];
                r--;
            }
        }
        return ans;
    }
};

力扣——每日一题

390. 消除游戏

列表 arr 由在范围 [1, n] 中的所有整数组成,并按严格递增排序。请你对 arr 应用下述算法:

从左到右,删除第一个数字,然后每隔一个数字删除一个,直到到达列表末尾。
重复上面的步骤,但这次是从右到左。也就是,删除最右侧的数字,然后剩下的数字每隔一个删除一个。
不断重复这两步,从左到右和从右到左交替进行,直到只剩下一个数字。
给你整数 n ,返回 arr 最后剩下的数字。

示例 1:

输入:n = 9
输出:6
解释:
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
arr = [2, 4, 6, 8]
arr = [2, 6]
arr = [6]

我们可以看出来,每次删除会删除一半的数字(如是奇数,删除的数向上取整),而且,每次删除的是两数中间的数,也就是说,每进行一次删除,相邻两个数之间的差值会翻倍,比如一开始是1 2 3 4 5 6,两数之间差值是1,第一次删除后变成了2 4 6,差值变成了2……。我们就可以看出一个规律,每次删除,开头和末尾的数必有一个会变化(被删除),如果现有的数是奇数,那么开头和末尾的数都会变化,如果现有的数是偶数,那么就和删除的次数有关,如果删除的次数是奇数,那么开头数字会变(删除的次数如果是奇数,那么删除会从头部开始删),如果删除的次数是偶数,那么会从尾部开始删,即尾部数字变化,变化的大小是2^(删除的次数)。我们开始循环,每次循环删除一半的数,当剩下的数小于等于2时结束,每次删除根据删除的次数,剩余数字的奇偶来修改开头和末尾的数,结束循环后,根据循环次数的奇偶性判断是返回开头数还是末位数。

class Solution {
public:
    int lastRemaining(int n) {
        int num=n,l=1,r=n,loop=0,d=1;
        while(num>2)
        {
            loop++;
            if((num%2==1)||(num%2==0&&loop%2==1))l+=d;
            if((num%2==1)||(num%2==0&&loop%2==0))r-=d;
            num/=2;
            d*=2;
        }
        return loop%2==1?l:r;
    }
};

Acwing

838. 堆排序 - AcWing题库

输入一个长度为 n 的整数数列,从小到大输出前 m 小的数。

输入格式

第一行包含整数 n 和 m。

第二行包含 n 个整数,表示整数数列。

输出格式

共一行,包含 m 个整数,表示整数数列中前 m 小的数。

数据范围

1≤m≤n≤10^5
1≤数列中元素≤10^9

输入样例:

5 3
4 5 1 3 2

输出样例:

1 2 3

记模板就好。

#include<iostream>
using namespace std;
const int N = 100010;
int arr[N], n, m, len;

void down(int u)
{
    int t = u;
    if (u * 2 <= len && arr[2 * u] < arr[t])t = 2 * u;
    if (u * 2 + 1 <= len && arr[2 * u + 1] < arr[t])t = 2 * u + 1;
    if (u != t)
    {
        swap(arr[t], arr[u]);
        down(t);
    }
}

int main()
{
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++)scanf("%d", &arr[i]);
    len = n;
    for (int i = n / 2; i; i--)down(i);
    while (m--)
    {
        cout << arr[1] << " ";
        arr[1] = arr[len];
        len--;
        down(1);
    }
    return 0;
}
参与评论 您还未登录,请先 登录 后发表或查看评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:深蓝海洋 设计师:CSDN官方博客 返回首页

打赏作者

你好_Ä

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

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值