目录
1-等价多米诺骨牌对的数量-easy。数组
2-颜色交替的最短路径-medium。BFS、位运算
3-叶值的最小代价生成树-medium。树
4-绝对值表达式的最大值-medium。数学
给你一个由一些多米诺骨牌组成的列表 dominoes
。
如果其中某一张多米诺骨牌可以通过旋转 0
度或 180
度得到另一张多米诺骨牌,我们就认为这两张牌是等价的。
形式上,dominoes[i] = [a, b]
和 dominoes[j] = [c, d]
等价的前提是 a==c
且 b==d
,或是 a==d
且 b==c
。
在 0 <= i < j < dominoes.length
的前提下,找出满足 dominoes[i]
和 dominoes[j]
等价的骨牌对 (i, j)
的数量。
示例:
输入:dominoes = [[1,2],[2,1],[3,4],[5,6]]
输出:1
# DIY
class Solution:
def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
if not dominoes:
return 0
dic = {}
m = len(dominoes)
for i in range(m):
if dominoes[i][0] > dominoes[i][1]:
dominoes[i][0], dominoes[i][1] = dominoes[i][1], dominoes[i][0]
tu_do = tuple(dominoes[i])
dic[tu_do] = dic.get(tu_do, 0) + 1
res = 0
for val in dic.values():
res += val * (val - 1)//2
return res
def equal(self, a, b):
return (a[0] == b[0] and a[1] == b[1]) or (a[0] == b[1] and a[1] == b[0])
# 大神的解法
class Solution:
def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
if not dominoes:
return 0
dic = {}
res = 0
for do in dominoes:
do.sort()
tu_do = tuple(do)
res += dic.get(tu_do, 0)
dic[tu_do] = dic.get(tu_do, 0) + 1
return res
在一个有向图中,节点分别标记为 0, 1, ..., n-1
。这个图中的每条边不是红色就是蓝色,且存在自环或平行边。red_edges
中的每一个 [i, j]
对表示从节点 i
到节点 j
的红色有向边。类似地,blue_edges
中的每一个 [i, j]
对表示从节点 i
到节点 j
的蓝色有向边。返回长度为 n
的数组 answer
,其中 answer[X]
是从节点 0
到节点 X
的最短路径的长度,且路径上红色边和蓝色边交替出现。如果不存在这样的路径,那么 answer[x] = -1
。
示例 1:
输入:n = 3, red_edges = [[0,1],[1,2]], blue_edges = []
输出:[0,1,-1]
示例 2:
输入:n = 3, red_edges = [[0,1]], blue_edges = [[2,1]]
输出:[0,1,-1]
示例 3:
输入:n = 3, red_edges = [[1,0]], blue_edges = [[2,1]]
输出:[0,-1,-1]
示例 4:
输入:n = 3, red_edges = [[0,1]], blue_edges = [[1,2]]
输出:[0,1,2]
示例 5:
输入:n = 3, red_edges = [[0,1],[0,2]], blue_edges = [[1,0]]
输出:[0,1,1]
利用下一跳节点的编号来处理红蓝交替的逻辑,剩下就是BFS更新最短路径的做法
class Solution:
def shortestAlternatingPaths(self, n: int, red_edges: List[List[int]], blue_edges: List[List[int]]) -> List[int]:
# 前n个表示
dis = [-1] * (n*2)
dis[0] = 0
dis[n] = 0
que = [0, n]
blues = [[] for _ in range(n)]
reds = [[] for _ in range(n)]
for red in red_edges:
reds[red[0]].append(red[1] + n)
for blue in blue_edges:
blues[blue[0]].append(blue[1])
while que:
cur = que.pop(0)
edge = reds[cur] if cur < n else blues[cur-n]
for d in edge:
if dis[d] == -1:
dis[d] = dis[cur] + 1
que.append(d)
res = [-1]*n
for i in range(n):
if dis[i] > -1:
res[i] = dis[i]
if dis[i+n] > -1:
res[i] = dis[i+n] if res[i] == -1 else min(res[i], dis[i+n])
return res
给你一个正整数数组 arr
,考虑所有满足以下条件的二叉树:
arr
中的值与树的中序遍历中每个叶节点的值一一对应。(知识回顾:如果一个节点有 0 个子节点,那么该节点为叶节点。)在所有这样的二叉树中,返回每个非叶节点的值的最小可能总和。这个和的值是一个 32 位整数。
示例:
输入:arr = [6,2,4]
输出:32
解释:
有两种可能的树,第一种的非叶节点的总和为 36,第二种非叶节点的总和为 32。
24 24
/ \ / \
12 4 6 8
/ \ / \
6 2 2 4
暂时不懂,把第一名的代码先贴这
const int N_MAX = 105;
const long long LL_INF = (long long) 2e18 + 5;
class Solution {
public:
int n;
vector leaves;
long long dp[N_MAX][N_MAX];
long long solve(int start, int end) {
if (end - start <= 1)
return 0;
long long &answer = dp[start][end];
if (answer >= 0)
return answer;
answer = LL_INF;
for (int i = start + 1; i < end; i++) {
int left = 0, right = 0;
for (int j = start; j < i; j++)
left = max(left, leaves[j]);
for (int j = i; j < end; j++)
right = max(right, leaves[j]);
answer = min(answer, left * right + solve(start, i) + solve(i, end));
}
return answer;
}
int mctFromLeafValues(vector& arr) {
leaves = arr;
n = leaves.size();
memset(dp, -1, sizeof(dp));
return solve(0, n);
}
};
给你两个长度相等的整数数组,返回下面表达式的最大值:|arr1[i] - arr1[j]| + |arr2[i] - arr2[j]| + |i - j|
其中下标 i
,j
满足 0 <= i, j < arr1.length
。
示例 1:
输入:arr1 = [1,2,3,4], arr2 = [-1,4,5,6]
输出:13
示例 2:
输入:arr1 = [1,-2,-5,0,10], arr2 = [0,-2,-1,-7,-4]
输出:20
这道题的关键点在于把要优化的求最大值的表达式拆解开来,拆解开就是对应4种情况,i>j。然后把i和j分别写一起,就可以看出,求的是i和j两部分的最大和
arr1[i] - arr1[j] + arr2[i] - arr2[j] + i - j
arr1[i] - arr1[j] - arr2[i] + arr2[j] + i - j
-arr1[i] + arr1[j] + arr2[i] - arr2[j] + i - j
-arr1[i] + arr1[j] - arr2[i] + arr2[j] + i - j
# 大神的解法1
class Solution:
def maxAbsValExpr(self, arr1: List[int], arr2: List[int]) -> int:
if not arr1 or not arr2:
return 0
m = len(arr1)
n = len(arr2)
assert m == n
res = float('-inf')
for sign1 in [-1, 1]:
for sign2 in [-1, 1]:
tmp = []
for i in range(m):
tmp.append(arr1[i]*sign1 + arr2[i]*sign2 + i)
res = max(res, max(tmp) - min(tmp))
return res
# 大神的解法2
class Solution:
def maxAbsValExpr(self, arr1: List[int], arr2: List[int]) -> int:
if not arr1 or not arr2:
return 0
m = len(arr1)
n = len(arr2)
assert m == n
res = float('-inf')
best1 = best2 = best3 = best4 = float('-inf')
for i in range(m):
res = max(res, best1 + arr1[i] + arr2[i] + i)
res = max(res, best2 + arr1[i] - arr2[i] + i)
res = max(res, best3 - arr1[i] + arr2[i] + i)
res = max(res, best4 - arr1[i] - arr2[i] + i)
best1 = max(best1, -arr1[i] - arr2[i] - i)
best2 = max(best2, -arr1[i] + arr2[i] - i)
best3 = max(best3, arr1[i] - arr2[i] - i)
best4 = max(best4, arr1[i] + arr2[i] - i)
return res