Leetcode进阶之路——Weekly Contest 149

37 篇文章 0 订阅

1154. Day of the Year
1154
给定一个字符串日期,返回该天是该年的第几天
首先把字符串按年月日拎出来,判断是否为闰年,最后求和即可

class Solution {
public:
    int strtoInt(string s)
	{
		int begin = 0;
		for (int i = 0; i < s.length(); ++i)
			if (s[i] == '0') begin++;
			else break;
		int res = 0;
		for (int i = begin; i < s.length(); ++i)
			res = res * 10 + s[i] - '0';
		return res;
	}

	int dayOfYear(string date) {
		int year = strtoInt(date.substr(0, 4));
		int month = strtoInt(date.substr(5, 2));
		int day = strtoInt(date.substr(8));
		int ds[12] = { 31, 30, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
		int res = day;
		for (int i = 0; i < month - 1; ++i)
			res += ds[i];
		if (month > 2)
		{
			if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
				res -= 1;
			else res -= 2;
		}
		return res;
			
	}
};

1155. Number of Dice Rolls With Target Sum
1155
给定d个骰子,每个骰子有f个面,编号从1~f,抛d次,使得和为target,共有多少种情况,对所有的方案数取模(1e9+7)
明显的dp,dp[i][j]表示用i个骰子抛出和为j的情况数,因此
d p [ i ] [ j ] = ∑ k = 1 f d p [ i − 1 ] [ j − k ] dp[i][j]=\sum_{k=1}^{f}dp[i-1][j-k] dp[i][j]=k=1fdp[i1][jk]
代码如下:

const int MOD = 1000000007;
class Solution {
public:
    int numRollsToTarget(int d, int f, int target) 
	{
		if (target == d * f) return 1;
        if (target > d * f) return 0;
		vector<vector<int>> dp(d + 1, vector<int>(d * f + 1, 0));
        for(int i = 1; i <= f; ++i)
            dp[1][i] = 1;
		for (int i = 2; i <= d; ++i)
		{
			int minn = i - 1, maxn = (i - 1) * f;
			for (int j = maxn; j >= minn; --j)
			{
				for (int k = f; k > 0; --k)
					dp[i][j + k] = (dp[i][j + k] + dp[i - 1][j]) % MOD;
			}
		}
		return dp[d][target];
	}
};

1156. Swap For Longest Repeated Character Substring
1156
给定一个字符串,仅能交换一次,判断最多有多少个连续的重复字符
从头遍历,直到找到第二个不同字符(因为只能交换一次)此轮结束:

class Solution {
public:
    int maxRepOpt1(string text) {
		map<char, int> count;
		for (char c : text)
			count[c]++;
		int maxn = 1;
		for (int i = 0; i < text.length(); ++i)
		{
			if (count[text[i]] < 2) continue;
			int cnt = 1, cur = 1;
			for (int j = i + 1; j < text.length(); ++j)
			{
				if (text[j] != text[i])
				{
					if (cnt == 0) break;
					else cnt--, cur++;
				}
				else cur++;
			}
			cur = min(cur, count[text[i]]);
			maxn = max(maxn, cur);
		}
		return maxn;
	}
};

1157. Online Majority Element In Subarray
1157
首先根据给定数组初始化,之后每个Query包含三个数:left、right和threshold,返回在[left, right]下标的区间内,出现次数超过threshold的数字,若不存在,则返回-1
很明显不能每次query都遍历一遍记录出现次数,会TLE,因此在初始化时需要做一些预先操作,我这里保存了三个数:

prepos: 表示数组中每个数出现的位置
presum: presum[i]表示到下标i为止,出现次数最多的数的个数
precnt: 内存放的是一个pair<int, int>,表示每个数字(first)出现的个数(second)
cmp表示将precnt按照出现次数从高到低排序

因此,每次query时,先判断到presum[right]为止,出现最多的次数,是否超过threshold,若比threshold小,则直接返回-1
之后,从头遍历precnt,以及用lower_bound()函数(本质是二分),从prepos中找到其在[left, right]区间内最早和最晚出现的位置,两个位置之间的距离若大于等于threshold,则找到,否则一直寻找,直至找不到返回-1

class MajorityChecker {
private:
    vector<int> v;
    unordered_map<int, vector<int>> prepos;
    vector<int> presum;
    vector<pair<int, int>> precnt;;
public:
    
    static bool cmp(const pair<int, int>& p1, const pair<int, int>& p2)
    {
        return p1.second > p2.second;
    }
    MajorityChecker(vector<int>& arr) {
        v = arr;
        presum.resize(arr.size(), 0);
        precnt.resize(20001);
        for(int i = 0; i < arr.size(); ++i)
        {
            pair<int, int> p = precnt[arr[i]];
            precnt[arr[i]] = make_pair(arr[i], p.second + 1);
            prepos[arr[i]].emplace_back(i);
            if(i == 0) presum[i] = precnt[arr[i]].second;
            else presum[i] = max(presum[i - 1], precnt[arr[i]].second);
        }
        sort(precnt.begin(), precnt.end(), cmp);
    }
    
    int query(int left, int right, int threshold) {
        if(presum[right] < threshold) return -1;
        int maxn = 0;
        for(int i = 0; i < precnt.size(); ++i)
        {
            if(precnt[i].second < threshold) break;
            int num = precnt[i].first;
            vector<int>::iterator it1 = lower_bound(prepos[num].begin(), prepos[num].end(), left), 
            it2 = lower_bound(prepos[num].begin(), prepos[num].end(), right);
            if(v[right] != num) it2--;
            if(it2 - it1 + 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);
 */
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值