leetcode 周赛 Weekly Contest 149

         这一次终于没有提交WA了。

         1154. Day of the Year

         简单题。打印一年到现在的天数,区分闰年即可。// 不要问我run, ping是啥意思 = =。

class Solution {
public:
    int dayOfYear(string date) {
        vector<int> days_run = {31,29,31,30,31,30,31,31,30,31,30,31};
        vector<int> days_ping = {31,28,31,30,31,30,31,31,30,31,30,31};
        int year = -1;
        int month = -1;
        int day = -1;
        date.push_back('-');
        string str;
        for(auto& ch : date)
        {
            if(ch == '-')
            {
                if(year == -1)
                {
                    year = atoi(str.c_str());
                }
                else if(month == -1)
                {
                    month = atoi(str.c_str());
                }
                else if(day == -1)
                {
                    day = atoi(str.c_str());
                }
                str.clear();
            }
            else
            {
                str.push_back(ch);
            }
        }
       
        int res = 0;
        if((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0 && year % 3200 != 0)) // runnian
        {
            for(int i = 0;i < month - 1;i++)
            {
                res += days_run[i];
            }
            res += day;
        }
        else
        {
            for(int i = 0;i < month - 1;i++)
            {
                res += days_ping[i];
            }
            res += day;           
        }
        return res;
    }
};

        1155. Number of Dice Rolls With Target Sum

        中等题,动态规划。给你d个骰子,包含数字为1~f,计算所有骰子总和为target的结果个数,比赛时写递推老写不对一着急就改成递归了。过会还得试试非递归能不能写对。题目中的d, f 看着命名真难受。

class Solution {
public:
    vector<vector<int>> dp;
    int numRollsToTarget(int d, int f, int target) { // d : number f : maxnum
        if(dp.size() == 0)
        {
            dp.resize(d + 1, vector<int>(target + 1, -1));
        }
        
        if(d == 0)
        {
            if(target == 0) return 1;
            else return 0;
        }
        if(target <= 0) return 0;
        if(dp[d][target] != -1) return dp[d][target];
        int res = 0;
        for(int k = 1; k <= f; k++)
        {
            res = (res + numRollsToTarget(d - 1, f, target - k)) % 1000000007;
        }
        return  dp[d][target] = res;
    }
};

        刚刚补了个非递归的,确实并不难,不知道比赛时咋回事。

class Solution {
public:
    int numRollsToTarget(int d, int f, int target) { // d : number f : maxnum
        int res = 0;
        vector<vector<int>> dp(d + 1, vector<int>(target + 1, 0));
        dp[0][0] = 1;
        for(int k = 1; k <= d; k++) // times
        {
            for(int sum = 1;sum <= target; sum++) // 
            {
                for(int t = 1; t <= f && t <= sum; t++)
                {                
                    dp[k][sum] = (dp[k - 1][sum - t] + dp[k][sum]) % 1000000007;                  
                }
            }
        }
        return dp[d][target];
    }
};

        1156. Swap For Longest Repeated Character Substring

         中等题,滑动窗口。找到字符串里不包含重复数字的最长子串,最多可以字符串中的两个字符交换一次。

         我维护的窗口是最多只包含一个额外字符的窗口。记录最大窗口大小,起始位置和终止位置。最后再去找有没有办法找到不在这个窗口里的一个字符把那个额外字符换掉。如果能找到,就返回窗口大小;否则返回窗口大小减一(找不到其它的替换品就只能从窗口里找一个替换了)。虽然思路还挺简单的,但是我感觉我写的很不优雅。

class Solution {
public:
    int maxRepOpt1(string text) {
        int n = text.size();
        int begin = 0;
        int res = 0;
        unordered_map<char, int> count;
        int res_begin;
        int res_end;
        for(int i = 0;i < n;i++) // end
        {
            count[text[i]]++;
            while(count.size() >= 3)
            {
                count[text[begin]]--;
                if(count[text[begin]] == 0) count.erase(text[begin]);
                begin++;
            }
            if(count.size() == 2)
            {
                while(true)
                {
                    int x = count.begin()->second;
                    int y = next(count.begin())->second;
                    if(x > 1 && y > 1) 
                    {
                        count[text[begin]]--;
                        if(count[text[begin]] == 0) 
                        {
                            count.erase(begin++);
                            break;
                        }
                        begin++;
                    }
                    else break;
                }
            }
            int len = i - begin + 1;
            if(len > res)
            {
                res_begin = begin;
                res_end = i;
                res = len;
            }
        }
      
        if(res == 2)
        {
            char a = text[res_begin];
            char b = text[res_end];
            for(int i = 0;i < n;i++)
            {
                if(i < res_begin || i > res_end)
                {
                    if(text[i] == a || text[i] == b)
                    {
                        return 2;
                    }
                }                
            }
            return 1;
        }
        else
        {
            char single;
            char repeat;
            unordered_map<char, int> number;
            for(int i = res_begin;i <= res_end;i++)
            {
                number[text[i]]++;
            }
            if(number.size() == 1) return res;
            int x = number.begin()->second;
            int y = next(number.begin())->second;
            
            if(x > y) 
            {
                repeat = number.begin()->first;
                single = next(number.begin())->first;
            }
            else
            {
                single = number.begin()->first;
                repeat = next(number.begin())->first;                
            }
            
            for(int i = 0;i < n;i++)
            {
                if(i < res_begin || i > res_end)
                {
                    if(text[i] == single)
                    {
                        return res;
                    }
                }
            }
            return res - 1;
        }
        return res;
    }
};

         1157. Online Majority Element In Subarray

        困难题,二分搜索和哈希。给一个数组,查询区间[left,right]内出现频率大于阈值的数字。

        好像题目也没说有没有可能有多个大于阈值的?

        我的思路是记录每个数字出现的所有下标,以及每个频率对应的数字。如果要查找区间内大于某个频率的数字,那么只查找整体频数大于这个阈值的数字。之后,由于每个数字出现的下标是按顺序排好的,所以可以用二分查找,找到落在[left,right]区间的有几个数字,然后看是否大于阈值,大于就直接返回。

class MajorityChecker {
public:
    unordered_map<int,vector<int>> index;
    map<int,vector<int>> times;
    MajorityChecker(vector<int>& arr) {
        int n = arr.size();
        unordered_map<int,int> count;
        for(int i = 0; i < n;i++)
        {
            count[arr[i]]++;
            index[arr[i]].push_back(i);
        }
        for(auto& cnt : count)
        {
            int number = cnt.first;
            int time = cnt.second;
            times[time].push_back(number);
        }
    }
    
    int query(int left, int right, int threshold) {
        if(threshold > right - left + 1) return -1;
        auto it = times.lower_bound(threshold);
        for(;it != times.end();it++)
        {
            for(auto& num : it->second)
            {
                vector<int>& idx = index[num];
                auto l = lower_bound(idx.begin(), idx.end(), left);
                auto r = upper_bound(idx.begin(), idx.end(), right);
                if(r == idx.begin()) continue;
           //     cout << num << " " << *l << " " << *r << " " << prev(r) - l + 1 << endl;
                if(prev(r) - l + 1 >= threshold) return num;
            }
        }
        return -1;
    }
};

/**
 * Your MajorityChecker object will be instantiated and called as such:
 * MajorityChecker* obj = new MajorityChecker(arr);
 * int param_1 = obj->query(left,right,threshold);
 */

猜你喜欢

转载自www.cnblogs.com/fish1996/p/11334802.html