Leetcode 175场周赛

2020-02-09 22:44:14

5332. 检查整数及其两倍数是否存在

给你一个整数数组 arr,请你检查是否存在两个整数 N 和 M,满足 N 是 M 的两倍(即,N = 2 * M)。

更正式地,检查是否存在两个下标 i 和 j 满足:

i != j
0 <= i, j < arr.length
arr[i] == 2 * arr[j]

我的方法:用了两个map,两个vector,还用了排序,有些麻烦:

我的想法是从前到后遍历的话,后面一定要是前面的两倍,否则无法判断:

class Solution {
public:
    bool checkIfExist(vector<int>& arr) {
        vector<int> pos,neg;
        map<int,int> mp;
        int n = arr.size();
        for(int i = 0;i < n;i++){
            if(arr[i] > 0) pos.push_back(arr[i]);
            else neg.push_back(arr[i]);
        }
        sort(pos.begin(),pos.end());
        sort(neg.begin(),neg.end(),greater<int>());
        int n1 = pos.size();
        int n2 = neg.size();
        map<int,int> mp2;
        for(int i = 0; i < n1; i++){
            if(mp.count(pos[i]) == 0) mp[pos[i]*2] = 1;
            else return true;
        }
        for(int i = 0; i < n2; i++){
            if(mp.count(neg[i]) == 0) mp[neg[i]*2] = 1;
            else return true;
        }
        return false;
    }
};

直接暴力:(数据量少,不会超时)

class Solution {
public:
    bool checkIfExist(vector<int>& arr) {
        int n = arr.size();
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (i != j && arr[i] == 2 * arr[j]) {
                    return true;
                }
            }
        }
        return false;
    }
};

巧妙做法:遍历两遍,思路是全部存入map并标记为1,然后之后如果找不到的就会标记为0;

class Solution {
    map<int,int> m;
public:
    bool checkIfExist(vector<int>& arr) {
        m.clear();
        for(auto i:arr)m[i]++;//先全部存入map,设置为1
        if(m[0]>1)return 1;//区分0和非0;
        for(auto i:arr)if(i&&m[2*i])return 1;//非0时,能找到2*i,则返回;
        return 0;
    }
};

5333. 制造字母异位词的最小步骤数

给你两个长度相等的字符串 s 和 t。每一个步骤中,你可以选择将 t 中的 任一字符 替换为 另一个字符。

返回使 t 成为 s 的字母异位词的最小步骤数。

字母异位词 指字母相同,但排列不同的字符串。

只需要统计s中所有字符与t中的差即可:结果只需t比s少的字符即可(多的可以转换)

class Solution {
public:
    int minSteps(string s, string t) {
        int a[26],b[26];
        for(int i = 0;i < 26; i++) a[i] = b[i] = 0;
        int n = s.size();
        for(int i = 0; i < n; i++){
            a[s[i]-'a']++;
            b[t[i]-'a']++;
        }
        int count = 0;
        int res = 0;
        for(int i = 0; i < 26; i++){
            if(b[i] > a[i]) count += b[i] - a[i];
            else res += a[i] - b[i];
        }return res;
    }
    
};

1348. 推文计数

请你实现一个能够支持以下两种方法的推文计数类 TweetCounts:

1. recordTweet(string tweetName, int time)

记录推文发布情况:用户 tweetName 在 time(以 秒 为单位)时刻发布了一条推文。
2. getTweetCountsPerFrequency(string freq, string tweetName, int startTime, int endTime)

返回从开始时间 startTime(以 秒 为单位)到结束时间 endTime(以 秒 为单位)内,每 分 minute,时 hour 或者 日 day (取决于 freq)内指定用户 tweetName 发布的推文总数。
freq 的值始终为 分 minute,时 hour 或者 日 day 之一,表示获取指定用户 tweetName 发布推文次数的时间间隔。
第一个时间间隔始终从 startTime 开始,因此时间间隔为 [startTime, startTime + delta*1>,  [startTime + delta*1, startTime + delta*2>, [startTime + delta*2, startTime + delta*3>, ... , [startTime + delta*i, min(startTime + delta*(i+1), endTime + 1)>,其中 i 和 delta(取决于 freq)都是非负整数。

做了很久都没做出来,然后看结果才发现少了一个判断条件:

不过做法也比较麻烦,每次都要排序;

class TweetCounts {
public:
    TweetCounts() {   
    }
    
    void recordTweet(string tweetName, int time) {
        mp[tweetName].push_back(time);
        sort(mp[tweetName].begin(),mp[tweetName].end());
    }
    vector<int> getTweetCountsPerFrequency(string freq, string tweetName, int startTime, int endTime) {
        vector<int> res;
        vector<int> temp = mp[tweetName];
        int fre = freq == "minute"? 60: freq == "hour"? 3600:3600*24;
        int s = lower_bound(temp.begin(),temp.end(),startTime)-temp.begin();
        for(int i = startTime; i <=endTime; i+=fre){
            int c = 0;
            //比赛时少了 temp[s] <= endTime,导致最后一个时间段会出错;
            while(s < temp.size() && temp[s] - i < fre && temp[s] <= endTime) {
                            c++;s++;}
            res.push_back(c);
        }
        return res;
    }
private:
    map<string,vector<int>> mp;
};

比较好的解法:直接确定时间段的长度,这样就可以不用排序直接遍历;

class TweetCounts {
    map<string, vector<int> > mp;
public:
    TweetCounts() {
        mp.clear();
    }
    
    void recordTweet(string tweetName, int time) {
        mp[tweetName].push_back(time);
    }
    
    vector<int> getTweetCountsPerFrequency(string freq, string tweetName, int startTime, int endTime) {
        int delta = freq == "minute" ? 60 : freq == "hour" ? 3600 : 86400;
        vector<int> ans((endTime - startTime) / delta + 1);//确定时间段长度
        for (auto i : mp[tweetName]) {
            if (startTime <= i && i <= endTime)
                ++ans[(i - startTime) / delta];
        }
        return ans;
    }
};

5335. 参加考试的最大学生数

给你一个 m * n 的矩阵 seats 表示教室中的座位分布。如果座位是坏的(不可用),就用 '#' 表示;否则,用 '.' 表示。

学生可以看到左侧、右侧、左上、右上这四个方向上紧邻他的学生的答卷,但是看不到直接坐在他前面或者后面的学生的答卷。请你计算并返回该考场可以容纳的一起参加考试且无法作弊的最大学生人数。

学生必须坐在状况良好的座位上。

 

 这题直接不会,应该是回溯,但是不会写:

看题解是状态压缩dp,又是一个没听过的东东:

 

猜你喜欢

转载自www.cnblogs.com/Aliencxl/p/12289212.html