【Leetcode】第201场周赛

A.整理字符串

解题思路:
多次遍历数组,将前后字符ASCII码差值为32的两个字符删除,直到本次遍历没有改变数组。
代码展示:

class Solution {
public:
    string makeGood(string s) {
        if(s.size()==0 || s.size()==1)  return s;
        int i=0;
        while(1){
            bool tmp=false;
            for(int i=0;i<s.size()-1;){
                if(fabs(s[i]-s[i+1])==32){
                    tmp=true;
                    if(i==0 && s.size()==2) return "";
                    else s.erase(i,2);
                }else   i++;
            }
            if(!tmp) return s;
        }
    }
};

B.找出第 N 个二进制字符串中的第 K 位

解题思路:
模拟。每次长度变为原来的两倍+1。
代码展示:

class Solution {
public:
    char s[2000000];
    char findKthBit(int n, int k) {
        s[1]='0';
        int t = 1;
        for(int i=2;i<=n;i++){
            s[t+1]='1';
            for(int j=1;j<=t;j++){
                if(s[j] == '0')
                    s[j+t+1] = '1';
                else
                    s[j+t+1] = '0';
            }
            int n_t =  t*2 +1;
            for(int j=0;j<(n_t - t-2)/2;j++){
                swap(s[t+2+j],s[n_t-j]);
            }
            t = n_t;
        }
        return s[k];
    }
};

C.和为目标值的最大数目不重叠非空子数组数目

解题思路:
先计算出数组的前缀和,对于第i个前缀和从0~i-1的前缀和找到是否有tmp = sum[i]-target。如果找到sum[j] = tmp,则找到区间j+1~i的区间和为target。(区间不重叠问题)最后将所有满足的区间,按右端点从小到大排序,按序选择不重叠的区间,返回区间数。
代码展示:

bool cmp(pair<int,int> x,pair<int,int> y){
    if(x.second != y.second)    return x.second < y.second;
    else return x.first<y.first;
}
class Solution {
public:
    vector<int> sum;
    vector< pair<int,int> > seg;
    map<int,int> q;
    int maxNonOverlapping(vector<int>& nums, int target) {
        int n = nums.size();
        if(n==0)    return 0;
        sum.resize(n);
        sum[0] = nums[0];
        for(int i=1;i<n;i++){
            sum[i] = nums[i]+sum[i-1];
        }
        for(int i=0;i<n;i++){
            int tmp = sum[i] -target;
            if(q[tmp]>0){
                seg.push_back({q[tmp],i});
            }else if(!tmp){
                seg.push_back({0,i});
            }
            q[sum[i]] = i+1;
        }
        int nseg = seg.size();
        sort(seg.begin(),seg.end(),cmp);
        int ans=0,n_r=-1;
        for(int i=0;i<nseg;i++){
            int l = seg[i].first;
            if(l>n_r){
                ans++;
                n_r = seg[i].second;
            }
        }
        return ans;
    }
};

D.切棍子的最小成本

解题思路:
区间DP,预处理前缀和。dp[i] [j] 表示在当前待切割的木棍的左端点为 cuts[i−1],右端点为 cuts[j] 时,将木棍全部切开的最小总成本。dp[i] [j] = min(dp[i] [j],dp[i] [k]+dp[k+1] [j]+sum[j]-sum[i-1])
代码展示:

class Solution {
public:
    int minCost(int n, vector<int>& cuts) {
        sort(cuts.begin(),cuts.end());
        vector<int> len_ele;
        len_ele.push_back(0);
        len_ele.push_back(cuts[0]);
        for(int i=1;i<cuts.size();i++)
            len_ele.push_back(cuts[i]-cuts[i-1]);
        len_ele.push_back(n-cuts[cuts.size()-1]);
        n = len_ele.size()-1;
        vector<int> sum(n+1,0);
        for(int i = 1;i<=n;i++)
            sum[i] = sum[i-1] + len_ele[i];
        vector<vector<int>> dp(n+2,vector<int>(n+2,0));
        for(int len = 1;len<n ;len ++){
            for(int i=1;i+len<=n;i++){
                int j = i+len;
                dp[i][j] = INT_MAX;
                for(int k=i;k+1<=j;k++){
                    dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);
                }
            }
        }
        return dp[1][n];
    }
};

做题情况:
AC 三题
排名:674 / 5614
总结反思:
排名很差,比赛中第四题并没有成功AC,归结于之前没怎么写过区间DP。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值