Leetcode 第175场周赛 题解(完结)

Leetcode 第175场周赛 题解

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

数据范围小的可怜,\(O(n^2)\) 解法可行。如果范围大一点,可以先进行排序然后遍历每一个数进行二分查找,时间复杂度 \(O(nlogn)\) 代码是平方解法。

typedef long long ll;
typedef double db;
#define _for(i,a,b) for(int i = (a);i < b;i ++)
#define _rep(i,a,b) for(int i = (a);i > b;i --)
#define INF 0x3f3f3f3f
#define ZHUO 11100000007
#define MOD 1000000007
#define MIKUNUM 39
#define pb push_back
#define debug() printf("Miku Check OK!\n")
#define maxn 200039
#define X first
#define Y second



class Solution
{
public:
	bool checkIfExist(vector<int>& arr)
	{
		int have = 0;
		_for(i,0,arr.size())
			_for(j,0,arr.size())
				if(i!=j && arr[j]==2*arr[i])
					have = 1;
		return have;
	}
};

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

那既然能随便换,哈希一波看看有多少个不一样,因为长度相等,所以如果要换肯定是把一个不应该有的换成一个应该有的。比如 \(s\)\(t\) 多了个 \(a\) ,而 \(t\)\(s\) 多了个 \(b\) ,那要么 \(a\)\(b\) 要么 \(b\)\(a\)

时间复杂度 \(O(max(n,m))\) ,其中 \(n,m\) 分别为字符串 \(s\)\(t\) 的长度。

using namespace std;
typedef long long ll;
typedef double db;
#define _for(i,a,b) for(int i = (a);i < b;i ++)
#define _rep(i,a,b) for(int i = (a);i > b;i --)
#define INF 0x3f3f3f3f
#define ZHUO 11100000007
#define MOD 1000000007
#define MIKUNUM 39
#define pb push_back
#define debug() printf("Miku Check OK!\n")
#define maxn 200039
#define X first
#define Y second


class Solution
{
public:
	int minSteps(string s, string t)
	{
		int A[30];
		int B[30];
		int rnt = 0;
		memset(A,0,sizeof(A));
		memset(B,0,sizeof(B));
		_for(i,0,s.size())
			A[s[i]-'a'] ++;
		_for(i,0,t.size())
			B[t[i]-'a'] ++;
		_for(i,0,30)
			if(A[i]!=B[i])
				rnt += abs(A[i]-B[i]);
		return rnt/2;
	}
};

推文计数

我们用 \(map\) 快速找到一个用户以后,可以得知对于每次询问 \([l,r]\) ,都应该返回一个长度为 \(\frac{r-l}{d}+1\)\(vector\) 。对于每个用户,其实直接遍历他发消息的时间即可,所以要用 \(set\) 或者 \(vector\) 等容器每次都把时间存在对应的人上面。对于时间 \(t\) ,若 \(t\in[l,r]\) 则他应该在结果 \(vector\) 下标 \(\frac{t-l}{d}\) 的位置。其中,\(d\) 是时间段长度。

时间复杂度 \(O(nlogn)\)

using namespace std;
typedef long long ll;
typedef double db;
#define _for(i,a,b) for(int i = (a);i < b;i ++)
#define _rep(i,a,b) for(int i = (a);i > b;i --)
#define INF 0x3f3f3f3f
#define ZHUO 11100000007
#define MOD 1000000007
#define MIKUNUM 39
#define pb push_back
#define debug() printf("Miku Check OK!\n")
#define maxn 10039
#define X first
#define Y second


class TweetCounts
{
public:
	set<int> s[maxn];
    map<string,int> mp;
	int cur;
	TweetCounts()
	{
		cur = 0;
	}

	void recordTweet(string tweetName, int time)
	{
        auto iter = mp.find(tweetName);
		if(iter==mp.end())
		{
			mp[tweetName] = cur;
			s[cur++].insert(time);
		}
		else
			s[iter->second].insert(time);
	}

	vector<int> getTweetCountsPerFrequency(string freq, string tweetName, int startTime, int endTime)
	{
		vector<int> rnt;
		auto iter = mp.find(tweetName);
		int x = iter->second;
        
		if(freq=="minute")
		{
            int sz = (endTime-startTime)/60+1;
			rnt.resize(sz,0);
			for(auto p:s[x])
                if(p>=startTime && p<=endTime)
                    rnt[(p-startTime)/60] ++;
		}
		else if(freq=="hour")
		{
			int sz = (endTime-startTime)/3600+1;
			rnt.resize(sz,0);
			for(auto p:s[x])
                if(p>=startTime && p<=endTime)
                    rnt[(p-startTime)/3600] ++;
		}
		else
		{
			int sz = (endTime-startTime)/86400+1;
			rnt.resize(sz,0);
			for(auto p:s[x])
                if(p>=startTime && p<=endTime)
				    rnt[(p-startTime)/86400] ++;
		}
		return rnt;
	}
};

参加考试的最大学生数

这题我看了看范围直接搜索玄学剪枝过去了,正解应该是状压 \(dp\)

题解参考:https://leetcode-cn.com/problems/maximum-students-taking-exam/solution/zhuang-tai-ya-suo-dp-by-lucifer1004/

在满足以下两个条件的情况下:

  • 本行的合法性:不能把学生安排在坏座位上;不能有相邻的学生
  • 两行之间的合法性:如果第一行某个位置安排了学生,则下一行斜向的两个位置不能安排学生

我们可以在遵守本行合法性的情况下枚举每一行的学生所有可能坐法,这样对于每一行我们都得到了一些满足本行合法性的座位方法。接下来我们考虑两行之间合法性,枚举上一行的所有满足本行合法性情况,再枚举本行的所有满足本行合法性的状态,这次就可以考虑两行之间合法性了,若都满足,则可以从上一行转移下来,加上本行满足合法性的状态的座位数即可。

时间复杂度 \(O(nm2^m)\) ,比爆搜的 \(O(2^{nm})\) 要优秀。

爆搜代码太丑陋就不放了,动规代码感兴趣可以去上面的链接里看。

posted @ 2020-02-09 14:17  Asurudo  阅读(305)  评论(0编辑  收藏  举报