https://leetcode-cn.com/contest/weekly-contest-146
这次周赛,因为有事没有参加,今天写完代码
题1
等价多米诺骨牌对的数量
肯定不能一个个遍历,题目给了提示,数字都是从1到9,总共也就9*9=81个可能嘛
public int numEquivDominoPairs(int[][] dominoes) {
int[][] ans = new int[10][10];
for (int i = 0; i < dominoes.length; i++) {
ans[dominoes[i][0]][dominoes[i][1]]++;
}
int res = 0;
for (int i = 1; i <= 9; i++) {
for (int j = i + 1; j <= 9; j++) {
//防止重复计算,从i+1开始
//这是在计算反转后一致的
res += ans[i][j] * ans[j][i];
}
for (int j = 1; j <= 9; j++) {
//这是计算,不反转一致的
res += ans[i][j] * (ans[i][j] - 1) / 2;
}
}
return res;
}
题2
颜色交替的最短路径
这个不能呢按最优规划算,有点类似挖地雷
public int[] shortestAlternatingPaths(int n, int[][] red_edges, int[][] blue_edges) {
Map> redMap = new HashMap<>();
Map> blueMap = new HashMap<>();
for (int i = 0; i < red_edges.length; i++) {
Set set = redMap.get(red_edges[i][0]);
if (set == null) {
set = new HashSet<>();
redMap.put(red_edges[i][0], set);
}
set.add(red_edges[i][1]);
}
for (int i = 0; i < blue_edges.length; i++) {
Set set = blueMap.get(blue_edges[i][0]);
if (set == null) {
set = new HashSet<>();
blueMap.put(blue_edges[i][0], set);
}
set.add(blue_edges[i][1]);
}
int[] ans = new int[n];
ans[0] = 0;
for (int i = 1; i < n; i++) {
ans[i] = -1;
}
Set pathA = new HashSet<>();
Set pathB = new HashSet<>();
Set allA = new HashSet<>();
Set allB = new HashSet<>();
pathA.add(0);
pathB.add(0);
int k = 0;
while (pathA.size() > 0 || pathB.size() > 0) {
k++;
List pA = new ArrayList<>(pathA);
List pB = new ArrayList<>(pathB);
pathA.clear();
pathB.clear();
for (Integer p : pA) {
Set set = redMap.get(p);
if (set != null) {
for (Integer i : set) {
if (!allB.contains(i)) {
pathB.add(i);
allB.add(i);
if (ans[i] == -1) {
ans[i] = k;
}
}
}
}
}
for (Integer p : pB) {
Set set = blueMap.get(p);
if (set != null) {
for (Integer i : set) {
if (!allA.contains(i)) {
pathA.add(i);
allA.add(i);
if (ans[i] == -1) {
ans[i] = k;
}
}
}
}
}
}
return null;
}
题3
叶值的最小代价生成树
这个有点最优规划的意思,但是不想想太多,弄for,直接按递归写了
int[][][] dp;
public int mctFromLeafValues(int[] arr) {
dp = new int[arr.length][arr.length][2];
return max(arr, 0, arr.length - 1)[0];
}
private int[] max(int[] arr, int sta, int end) {
if (dp[sta][end][1] > 0) {
return dp[sta][end];
}
if (sta == end) {
return new int[]{0, arr[sta]};
}
int ans = Integer.MAX_VALUE;
int max = 0;
for (int i = sta; i < end; i++) {
int[] m1 = max(arr, sta, i);
int[] m2 = max(arr, i + 1, end);
ans = Math.min(ans, m1[0] + m2[0] + m1[1] * m2[1]);
max = Math.max(m1[1], m2[1]);
}
dp[sta][end] = new int[]{ans, max};
return dp[sta][end];
}
题4
绝对值表达式的最大值
这道题有点脑经急转弯的意思,我就区分讨论,按照值的正负,拆绝对值
public int maxAbsValExpr(int[] arr1, int[] arr2) {
int len = arr1.length;
int max1 = Integer.MIN_VALUE;
int max2 = Integer.MIN_VALUE;
int max3 = Integer.MIN_VALUE;
int max4 = Integer.MIN_VALUE;
int max5 = Integer.MIN_VALUE;
int max6 = Integer.MIN_VALUE;
int max7 = Integer.MIN_VALUE;
int max8 = Integer.MIN_VALUE;
for (int i = 0; i < len; i++) {
max1 = Math.max(arr1[i] + arr2[i] + i, max1);
max2 = Math.max(arr1[i] + arr2[i] - i, max2);
max3 = Math.max(0 - arr1[i] + arr2[i] + i, max3);
max4 = Math.max(0 - arr1[i] + arr2[i] - i, max4);
max5 = Math.max(arr1[i] - arr2[i] + i, max5);
max6 = Math.max(arr1[i] - arr2[i] - i, max6);
max7 = Math.max(-arr1[i] - arr2[i] + i, max7);
max8 = Math.max(-arr1[i] - arr2[i] - i, max8);
}
return Math.max(Math.max(max1 + max8, max2 + max7), Math.max(max3 + max6, max4 + max5));
}