• 【LeetCode周赛】LeetCode第364场周赛


    最大二进制奇数

    给你一个 二进制 字符串 s ,其中至少包含一个 ‘1’ 。
    你必须按某种方式 重新排列 字符串中的位,使得到的二进制数字是可以由该组合生成的 最大二进制奇数 。
    以字符串形式,表示并返回可以由给定组合生成的最大二进制奇数。
    注意 返回的结果字符串 可以 含前导零。
    示例 1:

    输入:s = “010”
    输出:“001”
    解释:因为字符串 s 中仅有一个 ‘1’ ,其必须出现在最后一位上。所以答案是 “001” 。

    示例 2:

    输入:s = “0101”
    输出:“1001”
    解释:其中一个 ‘1’ 必须出现在最后一位上。而由剩下的数字可以生产的最大数字是 “100”。所以答案是 “1001” 。

    提示:

    1 <= s.length <= 100
    s 仅由 ‘0’ 和 ‘1’ 组成
    s 中至少包含一个 ‘1’

    分析:
    不难想到,因为要求返回的是一个奇数,所以最后一位肯定是1,同时,要使得整个数最大,所以1的位置要尽可能在前面的位数上。直接模拟即可。
    代码:

    class Solution {
    public:
        string maximumOddBinaryNumber(string s) {
            int zero=0,one=0;
            for(int i=0;i<s.size();i++){
                if(s[i]=='0')zero++;
                else one++;
            }
            string t="";
            while(one>1){
                t+="1";
                one--;
            }
            while(zero--)t+="0";
            t+="1";
            return t;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    美丽塔Ⅰ

    给你一个长度为 n 下标从 0 开始的整数数组 maxHeights 。
    你的任务是在坐标轴上建 n 座塔。第 i 座塔的下标为 i ,高度为 heights[i] 。
    如果以下条件满足,我们称这些塔是 美丽 的:
    1 <= heights[i] <= maxHeights[i]
    heights 是一个 山状 数组。
    如果存在下标 i 满足以下条件,那么我们称数组 heights 是一个 山状 数组:
    对于所有 0 < j <= i ,都有 heights[j - 1] <= heights[j]
    对于所有 i <= k < n - 1 ,都有 heights[k + 1] <= heights[k]
    请你返回满足 美丽塔 要求的方案中,高度和的最大值
    示例 1:

    输入:maxHeights = [5,3,4,1,1]
    输出:13
    解释:和最大的美丽塔方案为 heights = [5,3,3,1,1],这是一个美丽塔方案,因为:

    • 1 <= heights[i] <= maxHeights[i]
    • heights 是个山状数组,峰值在 i = 0 处。 13 是所有美丽塔方案中的最大高度和。

    示例 2:

    输入:maxHeights = [6,5,3,9,2,7]
    输出:22
    解释: 和最大的美丽塔方案为 heights =[3,3,3,9,2,2] ,这是一个美丽塔方案,因为:

    • 1 <= heights[i] <= maxHeights[i]
    • heights 是个山状数组,峰值在 i = 3 处。 22 是所有美丽塔方案中的最大高度和。

    示例 3:

    输入:maxHeights = [3,2,5,5,2,3]
    输出:18
    解释:和最大的美丽塔方案为 heights =[2,2,5,5,2,2] ,这是一个美丽塔方案,因为:

    • 1 <= heights[i] <= maxHeights[i]
    • heights 是个山状数组,最大值在 i = 2 处。 注意,在这个方案中,i = 3 也是一个峰值。 18 是所有美丽塔方案中的最大高度和。

    提示:
    1 < = n = = m a x H e i g h t s < = 1 0 3 1 <= n == maxHeights <= 10^3 1<=n==maxHeights<=103
    1 < = m a x H e i g h t s [ i ] < = 1 0 9 1 <= maxHeights[i] <= 10^9 1<=maxHeights[i]<=109

    分析:
    根据此题n的数据范围,可以考虑暴力做法,对于一个山状数组,只要我们能够找到"山峰"这个点,山峰i的高度h[i]肯定是当前maxHeights[i]的值,然后往左边逐渐递减,左边每一个塔j的值h[j]=min(maxHeights[j],h[j+1])。同理,右边每一个塔j的值h[j]=min(maxHeights[j],h[j-1])。因此,可以暴力计算出以每个塔为"山峰"时,最大的高度和,从而计算出整体最大的高度和。
    代码:

    class Solution {
    public:
        long long maximumSumOfHeights(vector<int>& maxHeights) {
            long long res=0;
            int n=maxHeights.size();
            vector<int>h(n+1);
            for(int i=0;i<n;i++){//取每一个为峰值
                long long ans=maxHeights[i];
                h[i]=maxHeights[i];
                for(int j=i-1;j>=0;j--){//左边递减
                    int now=min(maxHeights[j],h[j+1]);
                    h[j]=now;
                    ans+=now;
                }
                for(int j=i+1;j<n;j++){//右边递减
                    int now=min(maxHeights[j],h[j-1]);
                    h[j]=now;
                    ans+=now;
                }
                res=max(res,ans);
            }
            return res;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    美丽塔Ⅱ

    给你一个长度为 n 下标从 0 开始的整数数组 maxHeights 。
    你的任务是在坐标轴上建 n 座塔。第 i 座塔的下标为 i ,高度为 heights[i] 。
    如果以下条件满足,我们称这些塔是 美丽 的:
    1 <= heights[i] <= maxHeights[i]
    heights 是一个 山状 数组。
    如果存在下标 i 满足以下条件,那么我们称数组 heights 是一个 山状 数组:
    对于所有 0 < j <= i ,都有 heights[j - 1] <= heights[j]
    对于所有 i <= k < n - 1 ,都有 heights[k + 1] <= heights[k]
    请你返回满足 美丽塔 要求的方案中,高度和的最大值 。
    示例 1:

    输入:maxHeights = [5,3,4,1,1]
    输出:13
    解释:和最大的美丽塔方案为 heights = [5,3,3,1,1],这是一个美丽塔方案,因为:

    • 1 <= heights[i] <= maxHeights[i]
    • heights 是个山状数组,峰值在 i = 0 处。 13 是所有美丽塔方案中的最大高度和。

    示例 2:

    输入:maxHeights = [6,5,3,9,2,7]
    输出:22
    解释: 和最大的美丽塔方案为 heights =[3,3,3,9,2,2] ,这是一个美丽塔方案,因为:

    • 1 <= heights[i] <= maxHeights[i]
    • heights 是个山状数组,峰值在 i = 3 处。 22 是所有美丽塔方案中的最大高度和。

    示例 3:

    输入:maxHeights = [3,2,5,5,2,3]
    输出:18
    解释:和最大的美丽塔方案为 heights =[2,2,5,5,2,2] ,这是一个美丽塔方案,因为:

    • 1 <= heights[i] <= maxHeights[i]
    • heights 是个山状数组,最大值在 i = 2 处。 注意,在这个方案中,i = 3 也是一个峰值。 18 是所有美丽塔方案中的最大高度和。

    提示:
    1 < = n = = m a x H e i g h t s < = 1 0 5 1 <= n == maxHeights <= 10^5 1<=n==maxHeights<=105
    1 < = m a x H e i g h t s [ i ] < = 1 0 9 1 <= maxHeights[i] <= 10^9 1<=maxHeights[i]<=109

    分析:
    该题比美丽塔Ⅰ相比来说,就是数据范围变大了,同样,我们美丽塔Ⅰ的暴力做法,时间复杂度为 O ( N 2 ) O(N^2) O(N2),在当前n的范围下,是会TLE的。那么,我们可以在哪个地方减少时间的开销呢?
    不难想到,主要的时间开销在枚举每一个塔作为山峰,以及计算每个塔作为山峰时,整体的一个最大高度和,都需要遍历n个塔,如果整体的高度和能够很快计算出来,可以减少时间的开销。
    我们分析一下这个山状数组,当塔i作为山峰时,其高度为 h i h_{i} hi,即maxHeighs[i],如果左边的塔j的maxHeights[j]比它高,那么其高度也只能是 h i h_{i} hi,那么,我们往左边一直找,只要塔的maxHeights比 h i h_{i} hi高,那么该塔的高度就是 h i h_{i} hi,直到找到 m a x H e i g h t s [ j ] < h i maxHeights[j]maxHeights[j]<hi的塔j,那么此时到塔i的最大高度和 p r e [ i ] = ( i − j ) ∗ h [ i ] + p r e [ j ] pre[i]=(i-j)*h[i]+pre[j] pre[i]=(ij)h[i]+pre[j]。如果左边没有比i低的塔,那么此时到塔i的最大高度和 p r e [ i ] = i ∗ h [ i ] pre[i]=i*h[i] pre[i]=ih[i]
    因此,对于塔i左边的塔,我们只需要能够快速找到第一个比 h i h_{i} hi矮的塔,即可维护一个最大的高度和。那么这个问题又变成了单调栈的解法,有一个类似的题,找一个数右边的最近最大的数下一个更大元素 I。对于本题,利用单调栈,每次将一个数入栈,然后凡是栈中比其大的数,都出栈,然后此时栈顶的数就是离他最近的比其小的数,单调栈里从栈顶开始是一个递减序列。(为什么出栈更大的数呢,因为出栈更大的数是对后续找左边更小的数是没有影响的,留下来的数都是最近最小的数字),这样就可以在线性时间内找到左边最近最小的数。
    右边的塔的处理同理,最后枚举每一个点作为峰值,即可快速得到最大的高度和。
    代码:

    class Solution {
    public:
        //找到每一个maxHeights[i]左边最近的一个更小的值j,这一片都采用当前maxHeights[i]的值,然后再取j那边维护的值
        void cal(vector<long long>& p,vector<int>& maxHeights){
            int n=maxHeights.size();
            stack<int>st;
            for(int i=0;i<n;i++){
                while(!st.empty()&&maxHeights[st.top()]>=maxHeights[i])st.pop();
                if(st.empty())p[i]=(long long)(i+1)*maxHeights[i];//左边没有更小的值了,那么左边的高度和全是当前的maxHeights[i]
                else p[i]=(long long)(i-st.top())*maxHeights[i]+p[st.top()];//一直到左边这个比它小的值取当前的maxHeights[i],其他的值取之前维护好的
                st.push(i);
            }
        }
        long long maximumSumOfHeights(vector<int>& maxHeights) {
            int n=maxHeights.size();
            vector<long long>pre(n+1),suf(n+1);
            cal(pre,maxHeights);
            //找右边最近的最小的数 翻转一下,就是找左边最近最小的数
            reverse(maxHeights.begin(),maxHeights.end());
            cal(suf,maxHeights);
            long long ans=0;
            //枚举山峰
            for(int i=0;i<n;i++)ans=max(ans,pre[i]+suf[n-1-i]-maxHeights[n-1-i]);
            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
  • 相关阅读:
    社交网络的数据挖掘与分析,什么是社交网络分析
    01线程概述
    【BOOST C++】教程2:最简程序段(Hello World)
    初识Git
    【21天python打卡】第18天 python经典案例(4)
    9.SpringBoot与调度器
    【Java】图书管理系统,完整版+源代码!!!
    C++-Debug与Release的不同-Debug可行-Release下出错-莫名其妙的bug-AI插件开发
    【项目部署-apache】windows系统下apache部署django+channels
    127-Vue中“@/”路径提示配置
  • 原文地址:https://blog.csdn.net/ladiez/article/details/133296083