因为对于每组 startTime 和 endTime 只查询一次,所以也没啥可优化的点,直接暴力枚举所有的 [startTime[i], endTime[i]],判断queryTime 是否在这个区间内即可。
class Solution {
public:
int busyStudent(vector<int>& startTime, vector<int>& endTime, int queryTime) {
int cnt = 0;
for(int i = 0; i < startTime.size(); i++) {
if(startTime[i] <= queryTime && queryTime <= endTime[i]) {
cnt++;
}
}
return cnt;
}
};
首先将 text 按空格分割,将分割结果放入一个 vetor
分割步骤如下:
part 放入 result 时,可以判断下 part[0] 是否为大写字母。大小写转换公式如下:
接下来,将 result 按照题目要求排序。因为要求长度相同的元素保持原来的位置,即稳定排序,可以使用 std::stable_sort 代替常用的 std::sort。
排序结束后,将 result 中字符串用空格拼接即可。
最后将句子首字符转换为大写。
class Solution {
public:
string arrangeWords(string text) {
vector<string> data;
string part;
for(int i = 0, n = text.size(); i <= n; i++) {
if(i == n || text[i] == ' ') {
if(part.size() > 0) {
if('A' <= part[0] && part[0] <= 'Z') {
(part[0] -= 'A') += 'a';
}
data.push_back(part);
part = "";
}
} else {
part += text[i];
}
}
string anw;
stable_sort(data.begin(), data.end(), [](const string &l, const string &r) -> bool {
return l.size() < r.size();
});
for(int i = 0, n = data.size(); i < n; i++) {
if(i == 0) {
anw += data[i];
(anw[0] -= 'a') += 'A';
} else {
anw += " ";
anw += data[i];
}
}
return anw;
}
};
为了方便,下文中将 favoriteCompanies 简称为 FC。
首先,定义一个与 FC 等长的 vector
然后,枚举 DL[i],判断DL[i] 是否为 DL[j] (i != j) 的子集。如果DL[i] 不是其他 DL[j] 的子集,则 cnt += 1。
判断过程:
有两个 unordered_set
子集定义:如果 A 的所有元素均在 B 中,则 A 为 B 的子集。
用迭代器 iter 枚举 A 的所有元素,如果对于每个 iter 都有 B.find(*iter) != B.end() ,那么 A 就是 B 子集。否则 A 不是 B 的子集。
class Solution {
public:
bool check(const unordered_set<string> &l, const unordered_set<string> &r) {
for(const auto &v : l) {
if(r.find(v) == r.end()) {
return true;
}
}
return false;
}
vector<unordered_set<string>> data;
vector<int> peopleIndexes(vector<vector<string>>& fc) {
for(const auto &v : fc) {
unordered_set<string> us;
for(const auto &s : v) {
us.insert(s);
}
data.push_back(std::move(us));
}
vector<int> res;
for(int i = 0, n = fc.size(); i < n; i++) {
bool flag = true;
for(int j = 0; j < n && flag; j++) {
if(i == j || check(data[i], data[j])) { continue; }
flag = false;
}
if(flag) {
res.push_back(i);
}
}
return res;
}
};
首先来思考一个问题,如果一个圆 C 能覆盖点集 S,当S包含两个及以上数量的点时,我们可以移动 C 找到一个 C’,使得 C’ 也能覆盖 S,且至少有两个点在 C’ 上。
为什么一定能通过平移和旋转C来找到C’呢?
首先所有的点都在 C 内,在移动过程中,必然会有点跑到 C 上。因为移动会导致点跑到C外面,但是一个点由圆内变为圆外时,必然要先从圆内变成圆上。
设有两个不重合的点A,B。分别以 A, B 为圆心,r 为半径,画两个圆。
设 A,B 连线的终点为 M。两圆的一个交点为P。设 MP 长度为d(可通过勾股定理求得)。另外,又知道MP的方向向量 dir 为(A.y-B.y,B.x-A.x)。所以:
P . x = d ∗ d i r . x / s q r t ( d i r . x 2 + d i r . y 2 ) + M . x P.x ={d*dir.x}/{sqrt(dir.x^2+ dir.y^2)} + M.x P.x=d∗dir.x/sqrt(dir.x2+dir.y2)+M.x
P . y = d ∗ d i r . y / s q r t ( d i r . x 2 + d i r . y 2 ) + M . y P.y ={d*dir.y}/{sqrt(dir.x^2+ dir.y^2)} + M.y P.y=d∗dir.y/sqrt(dir.x2+dir.y2)+M.y
那么接下来的问题就变成了,暴力枚举两个点 A,B,通过A,B 及确定的半径计算出 C’ 的圆心 center。然后再暴力枚举所有点,判断有多少点在以 center 为圆心的C’ 内。
#define N 101
#define LL long long
#define INF 0xfffffff
const double eps = 1e-8;
const double pi = acos(-1.0);
const double inf = ~0u>>2;
struct point {
double x,y;
point(double x = 0,double y =0 ):x(x),y(y){}
}p[N];
double dis(point a,point b) {
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int dcmp(double x) {
if(fabs(x)<eps)return 0;
else return x<0?-1:1;
}
point getcircle(point p1, point p2, double r) {
point dir(p1.y-p2.y, p2.x-p1.x);
point mid((p1.x+p2.x)/2, (p1.y+p2.y)/2);
double d = sqrt(r*r-dis(p1,mid)*dis(p1,mid));
double detX = d*dir.x/sqrt(dir.x*dir.x + dir.y*dir.y);
double detY = d*dir.y/sqrt(dir.x*dir.x + dir.y*dir.y);
return point(mid.x + detX, mid.y + detY);
}
class Solution {
public:
int numPoints(vector<vector<int>>& points, int ir) {
int n = points.size();
for(int i = 1 ;i <= n; i++) {
p[i].x = points[i-1][0];
p[i].y = points[i-1][1];
}
int maxz = 1;
for(int i = 1; i <= n; i++) {
for(int j = 1 ; j <= n ;j++) {
if(i == j || dcmp(dis(p[i],p[j])-2*ir)>0) {
continue;
}
int tmax = 0;
point cir = getcircle(p[i],p[j], ir);
for(int g = 1; g <= n ;g++)
{
if(dcmp(dis(cir,p[g])-ir)>0)
continue;
tmax++;
}
maxz = max(maxz,tmax);
}
}
return maxz;
}
};