突然觉得自己还是挺菜的,智商还是不够……第一题竟然最后都想打表了……其实很多时候,当思路挺乱的时候,先把代码备份到一边,然后再重新想,很可能答案就呼之欲出了。

A. 日期之间隔几天

题目链接

题目描述

请你编写一个程序来计算两个日期之间隔了多少天。

日期以字符串形式给出,格式为 YYYY-MM-DD,如示例所示。

思路

最开始想怎么算,其实这道题范围很小,只有 1971 到 2100 年,直接模拟就好了。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
class Solution {
public:
int cnt[3005],p[14];
int daysBetweenDates(string date1, string date2) {
int n1=0,m1=0,r1=0,n2=0,m2=0,r2=0;
for(int i=0;i < 4;i++)
{
n1=(n1*10)+date1[i]-'0';
n2=(n2*10)+date2[i]-'0';
}
for(int i=5;i < 7;i++)
{
m1=(m1*10)+date1[i]-'0';
m2=(m2*10)+date2[i]-'0';
}
for(int i=8;i < 10;i++)
{
r1=(r1*10)+date1[i]-'0';
r2=(r2*10)+date2[i]-'0';
}
p[1]=31;p[2]=28;p[3]=31;p[4]=30;p[5]=31;p[6]=30;
p[7]=31;p[8]=31;p[9]=30;p[10]=31;p[11]=30;p[12]=31;
if(n1 > n2)
{
swap(n1,n2);
swap(m1,m2);
swap(r1,r2);
}
else if(n1==n2)
{
if(m1 > m2)
{
swap(m1,m2);
swap(r1,r2);
}
else if(m1==m2)
{
if(r1 > r2) swap(r1,r2);
}
}
int ans=0;
while(n1!=n2||m1!=m2||r1!=r2)
{
if(n1%4==0&&n1!=2100) p[2]=29;
else p[2]=28;
r1++;ans++;
if(r1 > p[m1])
{
r1=1;m1++;
}
if(m1 > 12)
{
m1=1;n1++;
}
}
return ans;
}
};

B. 验证二叉树

题目链接

题目描述

二叉树上有 n 个节点,按从 0 到 n - 1 编号,其中节点 i 的两个子节点分别是 leftChild[i] 和 rightChild[i]。

只有 所有 节点能够形成且 只 形成 一颗 有效的二叉树时,返回 true;否则返回 false。

如果节点 i 没有左子节点,那么 leftChild[i] 就等于 -1。右子节点也符合该规则。

注意:节点没有值,本问题中仅仅使用节点编号。

思路

考查二叉树的定义:只有一个点入度为 0 ,其他点的入度都为 1 ,注意一些细节。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Solution {
public:
bool vis[100005];
int rd[100005],m=0;
bool validateBinaryTreeNodes(int n, vector < int > & leftChild, vector < int > & rightChild) {
for(int i=0;i < n;i++)
{
int x=leftChild[i],y=rightChild[i];
if(x!=-1)
{
vis[x]=true;
rd[x]++;
m++;
}
if(y!=-1)
{
vis[y]=true;
rd[y]++;
m++;
}
}
if(m!=n-1) return false;
int f=0,f2=0;
for(int i=1;i < n;i++)
{
if(rd[i]!=1)
{
if(!rd[i]&&!f) f=1;
else return false;
}
if(!vis[i])
{
if(!f&&!rd[i]) f2=1;
else return false;
}
}
return true;
}
};

C. 最接近的因数

题目链接

题目描述

给你一个整数 num,请你找出同时满足下面全部要求的两个整数:

  • 两数乘积等于  num + 1 或 num + 2
  • 以绝对差进行度量,两数大小最接近

你可以按任意顺序返回这两个整数。

思路

很显然以 O(nn)O(n\cdot\sqrt n) 的时间复杂度直接枚举两个因数取最优就好了。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Solution {
public:
vector < int > closestDivisors(int num) {
int ta,tb,sa,sb;
int s=sqrt(num+1)+1;
for(int i=s;i;i--)
{
if((num+1)%i==0)
{
ta=i;
tb=(num+1)/i;
break;
}
}
s=sqrt(num+2)+1;
for(int i=s;i;i--)
{
if((num+2)%i==0)
{
sa=i;
sb=(num+2)/i;
break;
}
}
vector < int > ans;
int p1=abs(ta-tb),p2=abs(sa-sb);
if(p1 < p2)
{
ans.push_back(ta);
ans.push_back(tb);
}
else
{
ans.push_back(sa);
ans.push_back(sb);
}
return ans;
}
};

D. 形成三的最大倍数

题目链接

题目描述

给你一个整数数组 digits,你可以通过按任意顺序连接其中某些数字来形成 3 的倍数,请你返回所能得到的最大的 3 的倍数。

由于答案可能不在整数数据类型范围内,请以字符串形式返回答案。

如果无法得到答案,请返回一个空字符串。

思路

采用先全部选,然后删去的方法,先算出所有 digits 的和 tot

  • 如果 (tot-1) % 3 == 0 ,那么肯定先扣除 1 , 4 , 7 ,如果没有,再考虑扣除两个 2 , 5 , 8 ,如果还不行就看是否有 0 ,如果没有就无解。
  • 如果 (tot-2) % 3 == 0 ,那么就反着来就好了。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
class Solution {
public:
int cnt[105],tot=0;
string largestMultipleOfThree(vector < int > & digits) {
for(int i=0;i < digits.size();i++)
{
cnt[digits[i]]++;
tot+=digits[i];
}
if(tot%3==1)
{
for(int i=1;i < =7;i+=3)
{
if(cnt[i])
{
cnt[i]--;
tot-=i;
break;
}
}
if(tot%3)
{
for(int i=2;i < =8;i+=3)
{
if(cnt[i] > =2)
{
cnt[i]-=2;
tot-=i*2;
break;
}
}
}
}
if(tot%3==2)
{
for(int i=2;i < =8;i+=3)
{
if(cnt[i])
{
cnt[i]--;
tot-=i;
break;
}
}
if(tot%3)
{
for(int i=1;i < =7;i+=3)
{
if(cnt[i] > =2)
{
cnt[i]-=2;
tot-=i*2;
break;
}
}
}
}
string ans="";
if(tot%3) return ans;
if(tot==0&&cnt[0])
{
ans+="0";
return ans;
}
for(int i=9;~i;i--)
{
for(int j=1;j < =cnt[i];j++) ans+=(char)(i+'0');
}
return ans;
}
};

weekly-contest-177