题目1
题意
给出二维平面n个点,问是否全部在一条直线上?
思路
根据已知两点(x1,y1),(x2,y2)的直线公式: (y-y1)/(y2-y1)=(x-x1)/(x2-x1)
代码
class Solution {
public:
bool checkStraightLine(vector<vector<int>>& coordinates) {
int num = coordinates.size();
int y2 = coordinates[1][1], y1 = coordinates[0][1];
int x2 = coordinates[1][0], x1 = coordinates[0][0];
for(int i =2;i<num;i++){
if((coordinates[i][0]-x1)*(y2-y1) != (coordinates[i][1]-y1)*(x2-x1)) return false;
}
return true;
}
};
题目2
题意:
给出n个文件路径名,过滤掉其中是别的路径名的子目录的路径名。
思路:
对路径名排序后,名称里最后一个‘/’之前出现过,就过滤掉。O(nlgn)
代码:
class Solution {
public:
vector<string> removeSubfolders(vector<string>& folder) {
vector<string> ans;
sort(folder.begin(),folder.end());
for(int i=0;i<folder.size();i++){
if(i==0){
ans.push_back(folder[i]);
}
else{
if(folder[i].find(ans[ans.size()-1])!=0 || folder[i][ans[ans.size()-1].length()]!='/'){
ans.push_back(folder[i]);
}
}
}
return ans;
}
};
题目3
题意
替换掉长度为4的倍数且只含'QWER'
四个字母的一个子串,让整个字符串的每个字母出现次数一样。
思路
首先可以想到满足要求的子串的条件是:子串外’QWER’个数小于等于总长度/4, 于是我们就可以用一个滑动窗口或者二分去找到这个子串区间。
我用的二分,滑动窗口好久没写了,快忘了。
代码
class Solution {
public:
int id[150], sum[100010][4], length;
bool check(int len){
if(len == 0){
for(int i=0;i<4;i++)
if(sum[length-1][i] != length/4) return false;
return true;
}
for(int i=0;i+len-1<length;i++){
int cnt = 0;
for(int j=0; j<4; j++){
int num = sum[length-1][j] - sum[i+len-1][j];
if(i>0) num += sum[i-1][j];
if(num<=length /4) cnt+=1;
}
if(cnt == 4) return true;
}
return false;
}
int balancedString(string s){
length = s.size();
id['Q'] = 0; id['W'] = 1; id['E'] =2; id['R'] = 3;
memset(sum,0,sizeof(sum));
for(int i=0;s[i];i++){
for(int j=0 ;j<4;j++){
if(id[s[i]] == j) sum[i][id[s[i]]] = i == 0 ? 1 : sum[i-1][id[s[i]]] +1 ;
else sum[i][j] = i==0 ? 0 : sum[i-1][j];
}
}
int l=0,r = length, mid, ans;
while(l<=r){
mid = (l+r)>>1;
if(check(mid)) r= mid-1;
else l = mid+1;
}
return r+1;
}
};
题目4
题意
在一个区间上,给出活动起始时间,和对应报酬,每个活动选择不能重叠,问最大报酬是?
思路
一个贪心思想结合0-1背包,先对活动时间排个序,保证选择不重复和尽量的贪心思想。
然后就是0-1背包问题,对于每个活动选或不选,dp[i]表示前i个活动里报酬最大值:
dp[i] = min(dp[i], dp[p]+ profit[i])
p是满足与i区间不重叠的上个区间位置。
代码
class Solution {
public:
int jobScheduling(vector<int>& startTime, vector<int>& endTime, vector<int>& profit) {
int n = startTime.size();
vector<int> id(n);
for(int i=0;i<n;i++) id[i] = i;
sort(id.begin(), id.end(), [&](int a, int b){
if(endTime[a] == endTime[b])
return startTime[a]<= startTime[b];
else return endTime[a] < endTime[b];
});
vector<int> dp(n+1, 0);
vector<int> endsort(n);
for(int i=0;i<n;i++) endsort[i] = endTime[id[i]];
for(int i=0;i<n;i++){
int p = upper_bound(endsort.begin(), endsort.end(), startTime[id[i]]) - endsort.begin();
p = min(p ,i); //如果找不到,upper_bound会返回最后一个位置
dp[i+1] = max(dp[id[i]], dp[p] + profit[id[p]]);
}
return dp[n];
}
};
总结
周赛中做出来前三道题,但不熟悉leetcode提交,一道都没过…,另外好久没有写C++,很多语法特性都是补题预习…