1.判断矩阵是否是一个 X 矩阵
题目链接
思路:模拟判断即可
bool checkXMatrix(vector<vector<int>>& grid) {
bool res = true;
int n = grid.size();
for(int i = 0; i < n; i ++){
for(int j = 0; j < n; j ++){
if(i == j || i + j == n - 1){
if(grid[i][j] == 0)
res = false;
}
else{
if(grid[i][j] != 0)
res = false;
}
if(!res) return res;
}
}
return res;
}
2.统计放置房子的方式数
题目链接
思路:状态机DP, 由于道路两边的情况互不影响,因此总方案数为两边的方案数相乘。对于一边的方案数,我们假设
g
[
i
]
[
0
]
g[i][0]
g[i][0]为第
i
i
i个位置上不放房子的方案数,则
g
[
i
]
[
0
]
=
g
[
i
−
1
]
[
0
]
+
g
[
i
−
1
]
[
1
]
,
g
[
i
]
[
1
]
=
g
[
i
−
1
]
[
0
]
g[i][0] = g[i - 1][0] + g[i-1][1],g[i][1]=g[i-1][0]
g[i][0]=g[i−1][0]+g[i−1][1],g[i][1]=g[i−1][0],那么假设
f
[
i
]
f[i]
f[i]为第
i
i
i个位置上的总方案数,
f
[
i
]
=
g
[
i
−
1
]
[
0
]
∗
2
+
g
[
i
−
1
]
[
1
]
f[i] = g[i-1][0]*2+g[i-1][1]
f[i]=g[i−1][0]∗2+g[i−1][1]
f
[
i
+
1
]
=
g
[
i
]
[
0
]
∗
2
+
g
[
i
]
[
1
]
=
3
∗
g
[
i
−
1
]
[
0
]
+
2
∗
g
[
i
−
1
]
[
1
]
=
f
[
i
]
+
f
[
i
−
1
]
f[i+1]=g[i][0]*2+g[i][1] =3*g[i-1][0]+2*g[i-1][1]=f[i]+f[i-1]
f[i+1]=g[i][0]∗2+g[i][1]=3∗g[i−1][0]+2∗g[i−1][1]=f[i]+f[i−1]
f
[
i
+
1
]
=
f
[
i
]
+
f
[
i
−
1
]
f[i+1]=f[i]+f[i-1]
f[i+1]=f[i]+f[i−1]是一个斐波那契数列。答案即为
f
[
n
]
∗
f
[
n
]
(
需
求
余
)
f[n] * f[n](需求余)
f[n]∗f[n](需求余)
代码:
class Solution {
public:
int f[10005];
static const int mod = 1e9 + 7;
int countHousePlacements(int n) {
f[0] = 1, f[1] = 1;
for(int i = 2; i <= n + 1; i ++) f[i] = (long long)(f[i - 1] + f[i - 2]) % mod;
int res = (long long)f[n + 1] * f[n + 1] % mod;
return res;
}
};
3. 拼接数组的最大分数
题目链接
思路:最大子段和 题目要求从a中选取一段连续字段代替b中一段,或者用b中一段代替a中一段,设置数组
d
d
d使得
d
[
i
]
=
a
[
i
]
−
b
[
i
]
d[i]=a[i]-b[i]
d[i]=a[i]−b[i],计算
d
d
d数组的最大字段和以及最小字段和,将其
a
a
a数组的和加上最大字段和即为替换
a
a
a数组得到的最大值,将
b
b
b数组的和加上最小字段和的绝对值即为替换
b
b
b数组的最大值,两者的最大值即为本题的答案。
代码:
class Solution {
public:
int pd[100005], nd[100005];
int maximumsSplicedArray(vector<int>& nums1, vector<int>& nums2) {
int n = nums1.size(), sum1 = 0, sum2 = 0;
for(int i = 0; i < n; i ++){
pd[i] = nums1[i] - nums2[i], sum1 += nums1[i], sum2 += nums2[i];
nd[i] = nums2[i] - nums1[i];
}
int tonums2 = 0, tonums1 = 0, x = 0, y = 0;
for(int i = 0; i < n; i ++){
x += pd[i], y += nd[i];
if(x < 0) x = 0;
if(y < 0) y = 0;
tonums2 = max(tonums2, x);
tonums1 = max(tonums1, y);
}
return max(tonums1 + sum1, tonums2 + sum2);
}
};
4.从树中删除边的最小分数
题目链接
思路:首先观察数据范围发现枚举两条删除边的时间复杂度为
1
0
6
10 ^ 6
106,不会超时,所以我们可以采用枚举删除边的方式得到三个连通块。但如果我们注意枚举每个连通块里的值把他们异或起来,则要再乘上
N
N
N 的时间复杂度,总时间复杂度为
1
0
9
10^9
109,超时了。所以我们可以用一个
d
d
d 数组代表以该点为根节点其所有子节点的异或值,当要从该树中删去一颗子树时,只需异或上要删去子树的根节点的
d
d
d值。此时只需分两种情况讨论。
假设
a
l
l
all
all为所有节点的异或值,x为第一条删除边的远离根节点的点,y为第二条删除边远离根节点的点。且如果他们在第二种情况时,x比y更靠近根节点
1.两条删除边不在从根节点出发的同一路径上
三块部分的值分别为all^x, x^y, y
2.两条删除边在从根节点出发的同一路径上
三块部分的值分别为all ^ x ^ y, x, y
那么如何判断x和y是否在同一条到根节点的路径上呢,这里就可以采用时间戳的思想,设置遍历时第一次经过x点的时间为
i
n
[
x
]
in[x]
in[x],设置遍历时退出x点的时间为
o
u
t
[
x
]
out[x]
out[x]。对于dfs序来讲,若一条路径从根节点出发, x点和y点都在其上,且y点在x点下面,则
i
n
[
x
]
<
i
n
[
y
]
,
o
u
t
[
x
]
>
o
u
t
[
y
]
in[x]<in[y], out[x]>out[y]
in[x]<in[y],out[x]>out[y]。这就可以判断x和y是否在同一条从根节点出发的路径上了。
代码:
class Solution {
public:
static const int N = 2e3 + 5;
int in[N], out[N], d[N], h[N], ne[N], to[N], idx = 0, timestamp = 0;
void add(int x, int y){
ne[idx] = h[x]; to[idx] = y; h[x] = idx ++;
}
int dfs(int u, int fa){
in[u] = timestamp ++;
for(int i = h[u]; ~i; i = ne[i]){
int j = to[i];
if(j == fa) continue;
d[u] ^= dfs(j, u);
}
out[u] = timestamp ++;
return d[u];
}
bool isfa(int x, int y){
if(in[x] <= in[y] && out[x] >= out[y]) return true;
return false;
}
int minimumScore(vector<int>& nums, vector<vector<int>>& edges) {
int n = nums.size(), m = edges.size(), all = 0;
for(int i = 0; i < n; i ++) d[i] = nums[i], all ^= nums[i];
memset(h, -1, sizeof h);
for(int i = 0; i < m; i ++){
add(edges[i][0], edges[i][1]);
add(edges[i][1], edges[i][0]);
}
dfs(0, -1);
int res = 0x3f3f3f3f;
int t[4];
for(int i = 0; i < m; i ++){
for(int j = i + 1; j < m; j ++){
int x, y;
if(in[edges[i][0]] < in[edges[i][1]]) x = edges[i][1];
else x = edges[i][0];
if(in[edges[j][0]] < in[edges[j][1]]) y = edges[j][1];
else y = edges[j][0];
if(in[x] > in[y]) swap(x, y);
if(isfa(x, y)){
t[0] = all ^ d[x]; t[1] = d[x] ^ d[y]; t[2] = d[y];
}
else{
t[0] = all ^ d[x] ^ d[y]; t[1] = d[x]; t[2] = d[y];
}
sort(t, t + 3);
res = min(res, t[2] - t[0]);
}
}
return res;
}
};