Leetcode 周赛记录

Weekly Contest 228

Minimum Changes To Make Alternating Binary String
Count Number of Homogenous Substrings
Minimum Limit of Balls in a Bag
Minimum Degree of a Connected Trio in a Graph

228.png

题目:

  1. 题目大意:
    只含有01的字符串,两个相同的字母不能够连续,问最少改变几次。
    思路:
    比较改变第一个元素和不改变第一个元素两种情况下的次数取小
    时间复杂度O(n)
class Solution {
public:
    int minOperations(string s) {
        int first = 0,sed = 0;
        char base1 = s[0];
        char base2 = s[0]=='1'?'0':'1';
        for(int i=0;i<s.size();i++){
            if(i%2) {
                first+=(s[i]==base1);
                sed +=(s[i]==base2);
            }
            else{
                first+=(s[i]!=base1);
                sed +=(s[i]!=base2);
            }
        }
        return min(first,sed);
    }
};
  1. 题目大意:
    "sssss" 有 1个'sssss',两个'ssss'...5个's',一共算15次,只有只含有相同字符的字符串才计数,计算给定字符串中的总数目
    思路:
    从ind=0 开始,判断连续字符的字符串长度,然后用长度算次数,整个字符串只需要扫一次。
    时间复杂度O(n)
class Solution {
public:
    long long  sums(long long n){
        return ((1+n)*n/2)%1000000007;
    }
    int countHomogenous(string s) {
        int ans=0;
        int I=0;
        while(i<s.size()){
            int l=1;
            //一共l-1个一样的
            while(i+l-1<s.size() && s[i+l-1]==s[i]){l++;}
            ans+=(sums(l-1));
            ans=ans%1000000007;
            i=(l-1)+I;
        }
        return ans;
    }
};
  1. 题目大意:
    给定vector里面是>=1的正整数,每次可以选择其中一个正整数i,分为和为i 的两个数字,给定最大次数,求出vector中最大元素M,使得M在所有切分情况下最小。
    思路:
    二分法,二分最小可能的元素,根据所需次数进行迭代。
    时间复杂度O(nlogN)
    ,n = vec.size(),N是元素上界。
class Solution {
public:
    int need(vector<int>& nums,int target){
        int ans = 0;
        vector<int>numscp = nums;
        for(int i=0;i<numscp.size();i++){
            ans+=(numscp[i]-1)/target;
        }
        return ans;
    }
    int minimumSize(vector<int>& nums, int maxOperations) {
        int l=1,r = 1000000000;
        int mid;
        while(l<r){
            mid = (l+r)/2;
            //cout<<"main "<<l<<r<<mid<<endl;
            if(need(nums,mid)<=maxOperations)r=mid;
            else l = mid+1;
        }
        return l;
    }
};
  1. 题目大意:
    给一个图,三个节点间两两有边称为trio,计算图中所有trio中最小度数
    思路:
    暴力判断图中trio,判断是否有边的时候借助数组,边的个数借助MAP
    时间复杂度O(n^3)
class Solution {
public:
    int minTrioDegree(int n, vector<vector<int>>& edges) {
        map<int,vector<int>>mp;
        int e[405][405];
        memset(e,0,sizeof(e));
        int ans=n*n/2;
        for(int i=0;i<edges.size();i++){
            mp[edges[i][0]].push_back(edges[i][1]);
            mp[edges[i][1]].push_back(edges[i][0]);
            e[edges[i][0]][edges[i][1]]=1;
            e[edges[i][1]][edges[i][0]]=1;
        }
        bool flag=0;
        for(int i=1;i<=n;i++){
            if(mp[i].size()<2)continue;
            for(int j=i+1;j<=n;j++){
                if(mp[j].size()<2)continue;
                if(!e[i][j]) continue;
                for(int k=j+1;k<=n;k++){
                    if(!e[i][k] || !e[j][k])continue;
                    //cout<<i<<j<<k<<endl;
                    flag=1;
                    int tmp = mp[i].size()+mp[j].size()+mp[k].size()-6;
                    ans = min(ans,tmp);
                }
            }
        }
        if(flag==0)return -1;
        return ans;

    }
};

Weekly Contest 229

229.png

=。= 只做上来两题,第三题超时,第四题理解错了题目意思

题目:
第一题:
题目大意:给两个序列,交替字母合并为一个。
思路:暴力合并
时间复杂度:O(n1+n2)
空间复杂度:O(n1+n2)

class Solution {
public:
    string mergeAlternately(string word1, string word2) {
        string ans = "";
        int l1 = 0,l2=0;
        while(l1<word1.size() && l2<word2.size()){
            if(l1<word1.size()) ans+=word1[l1++];
            if(l2<word2.size()) ans+=word2[l2++];
        }
        if(l1<word1.size()) ans+=word1.substr(l1);
        if(l2<word2.size()) ans+=word2.substr(l2);
        return ans;
    }
};

第二题:
题目大意:给一串盒子序列nums,nums[i]=1 表示盒子有一个球,nums[i]=0表示盒子里面没有球,每次只能移动一个位置。返回一串序列cnt,cnt[i]表示把所有盒子中球都移动到盒子i中所需次数。
思路:每个重新移动是O(N^2)复杂度,已知盒子i的移动次数推导盒子i+1,只需要分别计算位于i左右的球所需要的移动次数,i左边的球移动到i+1需要每个多移动一次,右边的每个少移动一次
时间复杂度:O(N)
除返回外额外空间复杂度:O(1)

class Solution {
public:
    vector<int> minOperations(string boxes) {
        vector<int> res;
        int left=0,right=0,ind=1;
        int rightcnt = 0,leftcnt = 0;
        for(int i=1;i<boxes.size();i++){
            right+=(boxes[i]=='1'?i:0);
            rightcnt+=(boxes[i]=='1'?1:0);
        }
        res.push_back(left+right);
        while(ind<boxes.size()){
            right-=rightcnt;
            rightcnt-=(boxes[ind]=='1'?1:0);
            leftcnt+=(boxes[ind-1]=='1'?1:0);
            left+=leftcnt;
            res.push_back(right+left);
            ind++;
        }
        return res;
    }
};

第三题:
题目大意:
给定长度为n序列NUMS,长度为m序列multipliers。
res= 0开始,第i次操作,从nums左边或者右边挑一个数乘multipliers[i] 得到的乘积加到res中,返回res最大可能值。

n == nums.length
m == multipliers.length
1 <= m <= 103
m <= n <= 105
-1000 <= nums[i], multipliers[i] <= 1000

思路:本题最直观的方法就是dfs,但是直接做会超时,一般我们做dfs的时候都会找一个额外的数组记录,但是本题由于有空间限制,只能开1000*1000的数组,开10^5*10^5的数组会超存储。
注意其实最多操作m次,所以数组只需要开m数量级的,需要对下标进行一些变化。
另外,比赛的时候由于不知道可以给数组初始化为空,一直考虑未遍历的怎么记录,导致没有完成。本次积累如何用数组判断状态

时间复杂度:O(2^m)
空间复杂度:O(m^2)

class Solution {
public:
    int dp[1001][1001]={};
    int dfs(vector<int>& nums, vector<int>& multipliers ,int l ,int r ,int mindx){
        if(mindx == multipliers.size()) return 0;
        if(dp[l][nums.size()-r])return dp[l][nums.size()-r];
        int a = nums[l]*multipliers[mindx]+dfs(nums,multipliers,l+1,r,mindx+1);
        int b = nums[r]*multipliers[mindx]+dfs(nums,multipliers,l,r-1,mindx+1);
        return dp[l][nums.size()-r]=max(a,b);
    }
    int maximumScore(vector<int>& nums, vector<int>& multipliers) {
        int l = 0,r = nums.size()-1;
        return dfs(nums,multipliers,l,r,0);
        
    }
};

Weekly Contest 234
第一题一直因为小陷阱卡壳,45分钟做完前三题。然后第四题感觉无力回天(看答案应该是一个纯数学推理题)19分飘过

第一题:
题目大意:给定一个只有数字和小写字母的字符串,统计去掉所有小写字母后一共有多少个不同数字。(001和01算一种)
复杂度 O(n):用map记录数字有没有出现过;但是对于0的处理略显笨拙==

class Solution {
public:
    int numDifferentIntegers(string word) {
        map<string,bool>mp;
        int ans=0;
        for(int i=0;i<word.size();i++){
            if(word[i]>='a' && word[i]<='z')continue;
            int j=0;
            while(j+i<word.size() && word[i+j]>='0' && word[i+j]<='9') j++;
            int ii= i;
            if(word[i]=='0' && j!=1){
                ii=i;
                while(word[ii]=='0')ii++;
            }
            if(word[ii]>='a' && word[ii]<='z')continue;
            string tmp = word.substr(ii,j-(ii-i));
            if(!mp[tmp]) {mp[tmp]=1;ans++;}
            i = i+j-1;
        }
        return ans;
    }
};

discuss 中有很灵巧的做法:
灵巧之处在于用set去重,两个指针,如果只有单字母那么0也放进去,直到第一个不是0的字符出现将前缀0 去除。nice~

int numDifferentIntegers(string w) {
    unordered_set<string> s{""};    
    int i = 0;
    for (int j = 0; j < w.size(); ++j) {
        if (isdigit(w[j]))
            i += i < j && w[i] == '0';
        else {
            s.insert(w.substr(i, j - i));
            i = j + 1;
        }
    }
    s.insert(w.substr(i));
    return s.size() - 1;
}

第二题:
题目大意:
给定操作,计算一个向量经过几次操作能够复原为原先的向量。
思路:模拟运算,时间复杂度O(n^2),空间复杂度O(n)
In one operation, you will create a new array arr, and for each i:

  • If i % 2 == 0, then arr[i] = perm[i / 2].
  • If i % 2 == 1, then arr[i] = perm[n / 2 + (i - 1) / 2].
class Solution {
public:
    vector<int> help(vector<int>a){
        vector<int> ans(a);
        int n = a.size();
        for(int i=0;i<n;i++){
            if(i%2)ans[i]=a[ n/ 2 + (i - 1) / 2];
            else ans[i] = a[i/2];
        }
        return ans;
    }
    int reinitializePermutation(int n) {
        vector<int> ori;
        for(int i=0;i<n;i++)ori.push_back(i);
        vector<int> prem(ori);
        int ans = 1;
        vector<int> tmp = help(prem);
        while(tmp!=ori){
            ans++;
            tmp = help(tmp);
        }
        return ans;
    }
};

看了discuss ,果然有很简单的方法:
因为偶数下标i 变为 i/2<n/2,所以偶数位置上的一定会压缩到[0,n/2)中,
奇数下标i 变为 n/2+(i - 1) / 2,会>=n/2。
这样打乱后如果一个坐标能在=回到原位那么所有坐标都回到了原位
我们可以追溯i=1的坐标的逆过程:

int reinitializePermutation(int n) {
        int res = 0, i = 1;
        while (res == 0 || i > 1) {
            if (i < n / 2)
                i *= 2;
            else
                i = (i - n / 2) * 2 + 1;
            res++;
        }
        return res;
    }

时间复杂度降到了O(n),空间复杂度降到了O(1)

第三题:
题目大意:
给定一个字符串,将字符串中括号里的key替换成相应的value,如果没有替换成?
思路:直接存成map后暴力替换,时间复杂度 O(n)

class Solution {
public:
    string evaluate(string s, vector<vector<string>>& knowledge) {
        map<string,string>mp;
        for(int i=0;i<knowledge.size();i++)mp[knowledge[i][0]] = knowledge[i][1];
        string ans = "";
        for(int i=0;i<s.size();i++){
            if(s[i]!='(')ans+=s[i];
            else{
                int j=0;
                while(s[i+j]!=')')j++;
                string tmp = s.substr(i+1,j-1);
                if(mp.find(tmp)==mp.end())ans+="?";
                else ans+=mp[tmp];
                i+=j;
            }
        }
        return ans;
    }
};

第四题:
本届无语子就是他!!!
居然直接写出前几项找规律
题目大意:
给定一个整数primeFactors,你要用不超过这个整数的质数数组A(可以重复)组合成数字集合B,使得集合中的所有数字均能被A中所有质数整除。求出给定primeFactors后B中元素最大个数。(结果mod 1000000007)
For example, if n = 12, then its prime factors are [2,2,3], then 6 and 12 are nice divisors, while 3 and 4 are not.
it has 5 prime factors: [2,2,2,5,5], and it has 6 nice divisors: [10,20,40,50,100,200]
直接上答案:

long modpow(long base, int exp, int modulus) {
  long result = 1;
  for (; exp > 0; exp >>= 1) {
    result = result * (exp & 1 ? base : 1) % modulus;
    base = base * base % modulus;
  }
  return result;
}    
int maxNiceDivisors(int n) {
    int st[6] = {0, 1, 2, 3, 4, 6}, mod = 1000000007;
    return n < 6 ? st[n] : st[3 + n % 3] * modpow(3, n / 3 - 1, mod) % mod;
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容