• 【LeetCode】力扣364.周赛题解


    在这里插入图片描述
    Halo,这里是Ppeua。平时主要更新C++,数据结构算法,Linux与ROS…感兴趣就关注我bua!
    img

    1.最大二进制奇数

    🍉题目:image-20230924231011246

    🍉例子:

    image-20230924231101415

    🍉 题解:

    首先看题目,最大二进制奇数,在一个二进制表示法当中,只要最后一位为1,这个数就是奇数,将一个字符串中原有的一重新排列组合,将1尽可能的放到高位.最后留一位放在低位即可.

    假设给定字符串中1的数量为cnt.那么我们想要达到的就是如下关系

    d034fb0f22b9e1f048a60c95179d9e8

    🍉代码解析:

    具体思路如下:

    1. 遍历当前字符串,若为1则cnt++,并将当前位置置为0;

    2. 之后将低位也就是字符串的最后一位制成1,保证是奇数;

      这里不需要考虑字符串没有1的情况,因为题给条件保证一定有一个1

    3. 从高位遍历,依次将当前为置为1,直到cnt为0则停止

    class Solution {
    public:
        string maximumOddBinaryNumber(string s) {
            int  cnt=0;
            for(auto &ss:s)
            {
                if(ss=='1')cnt++;
                ss='0';
            }
            s[s.size()-1]='1';
            cnt--;
            for(int i=0;i<s.size()-1;i++)
            {
                if(cnt>0)
                {
                    s[i]='1';
                    cnt--;
                }
                else break;
            }
            return s;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    2. 2865. 美丽塔 I

    🍉 题目:

    image-20230925150702686

    🍉示例:

    image-20230925150842337

    🍉题意:

    先来分析下题目表达的意思:

    给定一个maxHeights数组在其中选一个数为美丽塔的塔尖.塔的两边呈递减状态.

    题给的maxHeights数组可以理解为是可以在这个地方建造美丽塔的最高高度,也就是塔高的上界.

    当选择第i位maxHeights[i]为塔尖的时,则有[0][i-1]均小于maxHeights[i]、[i+1][n-1]均小于maxHeights[i].

    对于[0]~[i-1]:则有s[i]<=s[i+1] (s为答案数组)

    对于[i+1]~[n-1]:则有s[i+2]<=s[i+1] (s为答案数组)

    具体关系如下图所示.

    d7095ad16d241b02bd896186d382d98

    根据数据范围来推算法

    我们需要学会一个方法: 根据数据范围来推导使用什么算法,c++中1s可以处理的次数为1e7,也就是超过这个时间就会报超时

    具体的有如下关系,(数据来自acwing)

    一般ACM或者笔试题的时间限制是1秒或2秒。
    在这种情况下,C++代码中的操作次数控制在 1e7 为最佳。

    下面给出在不同数据范围下,代码的时间复杂度和算法该如何选择:

    n≤30, 指数级别, dfs+剪枝,状态压缩dp
    n≤100 => O(n3),floyd,dp
    n≤1000 => O(n2),O(n2logn),dp,二分
    n≤10000 => O(n∗√n),块状链表
    n≤100000 => O(nlogn) => 各种sort,线段树、树状数组、set/map、heap、dijkstra+heap、spfa、求凸包、求半平面交、二分
    n≤1000000 => O(n), 以及常数较小的 O(nlogn) 算法 => hash、双指针扫描、kmp、AC自动机,常数比较小的 O(nlogn) 的做法:sort、树状数组、heap、dijkstra、spfa
    n≤10000000 => O(n),双指针扫描、kmp、AC自动机、线性筛素数
    n≤109 => O(√n),判断质数
    n≤1018 => O(logn),最大公约数

    在做题中有意识的先看数据范围,可以极大的帮助解题

    那么我们先看这一题的数据范围

    image-20230925153647661

    1 e 3 1e^3 1e3,也就是采用o( n 2 n^2 n2)的时间复杂度都可以通过.观察题目来看,我们直接暴力模拟两层循环即可.

    注意,这里的数据大小范围为 1 e 9 1e^9 1e9,而int的范围大概为 2 e 9 2e^9 2e9左右.如果使用int来存储最终数据,很容易造成溢出,所以我们使用long long来存储

    🍉 题解:

    观察题目要求会发现,如果顺序遍历这个数组,很容易出现在出现一个极小的数字,从而影响了前面整个塔的建设.

    也就是后续的高度会影响前面已经确定的结果,如果顺序遍历问题一下复杂起来了.所以我们选择从塔尖开始向前遍历.也就是逆序遍历.

    d42bb99836b3da141b6f4d874d54a96

    整体思路如下:

    设定一个值来存储已遍历区间的最小值(我们可以将这个最小值初始化为此时塔尖的高度:因为这半个区间中的所有高度都要小于等于塔尖)

    若当前值小于等于这个最小值,则可以加入到答案中(因为我们是逆序遍历,此时说明他是非递增)

    若当前值大于这个值,则将最小值加入到答案中.(maxHeights[cur]>=min,就会出现上图的情况)

    左右两边进行一个对称的操作,之后将和加入到答案数组即可.(ans[i]表示以i位为塔尖此时的高度和)

    最后对数组排序取出最后一个值,即为最大值.

    0adfabbbf61439216dde06b26fbde17

    class Solution {
    public:
        long long maximumSumOfHeights(vector<int>& maxHeights) {
            //存储最大高度和
            vector<long long>ans;
            int n = maxHeights.size();
            for (int i = 0; i < n; i++)
            {
                long long sum = maxHeights[i];
                int min_heightl = maxHeights[i];
                int min_heightr = maxHeights[i];
                for (int j = i-1; j >=0; j--)
                {
                    min_heightl = min(min_heightl, maxHeights[j]);
                    sum += min_heightl;
                }
                for (int j = i + 1; j < n; j++)
                {
                    min_heightr = min(min_heightr, maxHeights[j]);
                    sum += min_heightr;
                }
                ans.push_back(sum);
            }
            sort(ans.begin(), ans.end());
            return ans[n - 1];
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    3. 2866. 美丽塔 II

    🍉题目

    image-20230925150702686

    🍉示例:

    image-20230925150842337

    🍉题意:

    这题和美丽塔I的题目完全一样,唯一的区别就是

    image-20230926195712817

    数据范围从 1 0 3 10^3 103,变成了 1 0 5 10^5 105这意味着不能使用O( n 2 n^2 n2)的算法了.我们需要真正的解决这道题.

    🍉 题解:

    这里我们可以用前后缀差分的方法,和我们之前美丽塔I的思想类似,也是从分别算出塔的两边再相加.但不同的是:我们仅遍历数组一遍来算出以当前位置为塔尖的(左边或者右边)的和

    具体的我们利用单调栈来解决这道题:

    以下以右边为例:

    假设有数组[1,3,9,5,4,7]

    我们第一个遇到的数字是7,此时把他加入到和中.

    下一个遇到的数数字是4.因为是递减的排列,所以我们从右向左看.他很明显会被7给遮住.

    10bc0b648e121663d1420ce6bf7e093

    所以我们将7踢出栈撤销之前更新的答案(也就是减去这个7),再将4入栈.并更新答案.

    此时最关键的是,7是被压缩到4同样的高度,而不是被删掉了,也就是此时栈中有两个4.

    那我们如何去记录这个栈中有x个y呢?

    我们可以在栈中不存数字,存对应数字的数组下标.我们将栈中初始化一个数组大小n,此时只需要用前一个栈中下标减去要入栈的下标,就知道答案需要更新x个y了

    0031dd4fa1673d77fce7a910c3498a7

    右边栈初始值是n,左边栈初始值是-1.

    注意用来存储当前和的数组需要用longlong 否则会爆

    class Solution {
    public:
        long long maximumSumOfHeights(vector<int>& maxHeights) {
            long long sum=0;
            int n=maxHeights.size();
            stack<int>right;
            right.push(n);
            vector<long long>rsum(n+1);
            rsum.reserve(n+1);
            //存储答案数组会爆int
            vector<long long>lsum(n+1);
            lsum.reserve(n+1);
            //差分后缀
            for (int i = n - 1; i >= 0; i--) {
                while (right.size() > 1 && maxHeights[i] <= maxHeights[right.top()]) {
                    int value = right.top();
                    right.pop();
                    sum -= (long long)(right.top() - value) * maxHeights[value];
                }
                sum += (long long)(right.top() - i) * maxHeights[i];
                right.push(i);
                rsum[i] = sum;
            }
            long long ans=sum;
            stack<int>left;
            sum=0;
            left.push(-1);
            for(int i=0;i<n;i++)
            {
                while(left.size()>1&&maxHeights[i]<=maxHeights[left.top()])
                {   
                    int value=left.top();
                    left.pop();
                    sum-=(long long)(value-left.top())*maxHeights[value];   
                }
                sum+=(long long)(i-left.top())*maxHeights[i];
                ans=max(ans,sum+rsum[i+1]);
                left.push(i);
                lsum[i]=sum;
            }
            return ans;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    image-20230905164632777

  • 相关阅读:
    【MD5】采用MD5+盐的加密方式完成注册用户和登录账号
    Python的Lambda函数: 一把极简编程的瑞士军刀
    ORA-28000: the account is locked
    一文速学-让神经网络不再神秘,一天速学神经网络基础(五)-最优化
    多租户平台前端存储结构的选择
    重学设计模式之 装饰者模式
    Java String 类回顾(期末复习版)
    ios 开发问题小集 [持续更新]
    hive、spark、presto 中的增强聚合-grouping sets、rollup、cube
    STL(C++)
  • 原文地址:https://blog.csdn.net/qq_62839589/article/details/133323115