【LeetCode】力扣364.周赛题解

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

1.最大二进制奇数

题目:【LeetCode】力扣364.周赛题解_第1张图片

例子:

【LeetCode】力扣364.周赛题解_第2张图片

题解:

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

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

【LeetCode】力扣364.周赛题解_第3张图片

代码解析:

具体思路如下:

  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;
    }
};

2. 2865. 美丽塔 I

题目:

【LeetCode】力扣364.周赛题解_第4张图片

示例:

【LeetCode】力扣364.周赛题解_第5张图片

题意:

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

给定一个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为答案数组)

具体关系如下图所示.

【LeetCode】力扣364.周赛题解_第6张图片

根据数据范围来推算法

我们需要学会一个方法: 根据数据范围来推导使用什么算法,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),最大公约数

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

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

【LeetCode】力扣364.周赛题解_第7张图片

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来存储

题解:

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

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

【LeetCode】力扣364.周赛题解_第8张图片

整体思路如下:

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

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

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

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

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

【LeetCode】力扣364.周赛题解_第9张图片

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];
    }
};

3. 2866. 美丽塔 II

题目

【LeetCode】力扣364.周赛题解_第10张图片

示例:

【LeetCode】力扣364.周赛题解_第11张图片

题意:

这题和美丽塔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给遮住.

【LeetCode】力扣364.周赛题解_第12张图片

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

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

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

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

【LeetCode】力扣364.周赛题解_第13张图片

右边栈初始值是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;
    }
};

image-20230905164632777

你可能感兴趣的:(小菜鸡的LeetCode之路,leetcode,算法,职场和发展)