阿里笔试325
我没参赛,看你们的题目,不知道写的代码能不能AC
第一题用dp[n][3] 表示第i列选择第j个值能得到的最小绝对值差的和。
public static void minN(int[][] nums){ int c = nums[0].length; int[][] dp = new int[c][3]; // 第i列 for (int i = 1; i < c; i++) { //本次选择第j个数,第j行 for (int j = 0; j < 3; j++) { //前一次选择第k个数的最小值 for (int k = 0; k < 3; k++) { //没填充大值,用第一个数填充一下 if (k==0){ dp[i][j] = Math.abs(nums[j][i]-nums[k][i-1])+dp[i-1][k]; }else { dp[i][j] = Math.min(Math.abs(nums[j][i]-nums[k][i-1])+dp[i-1][k], dp[i][j]); } } } } System.out.println(Math.min(dp[c-1][0], Math.min(dp[c-1][1],dp[c-1][2]))); }
第二题就是循环按行列补充,直到没有新的值出现,没有检查该位置确实为0的情况,其实只需要看对应行列是否修改过就行。
public static void solve(int[][] nums){ int r = nums.length, c = nums[0].length; boolean[] flag = new boolean[r+c]; while (rowSolve(nums,flag)||colunm(nums,flag)){ } } public static boolean rowSolve(int[][] nums, boolean[]flag){ int r = nums.length, c = nums[0].length; boolean f = false; for (int i = 0; i < r; i++) { if (!flag[i]){ int[] pre = new int[2]; for (int j = 0; j < c; j++) { if (nums[i][j]!=0&&pre[1]!=0){ int dif = (nums[i][j] - pre[1])/(j - pre[0]); for (int k = j+1; k < c; k++) { nums[i][k] = nums[i][k-1] + dif; } for (int k = j-1; k >= 0; k--) { nums[i][k] = nums[i][k+1] - dif; } flag[i] = true; f = true; break; }else if (nums[i][j]!=0){ pre[0] = j; pre[1] = nums[i][j]; } } } } return f; } public static boolean colunm(int[][] nums, boolean[] flag){ int r = nums.length, c = nums[0].length; boolean f = false; for (int j = 0; j < c; j++) { if (!flag[r+j]){ int[]pre = new int[2]; for (int i = 0; i < r; i++) { if (nums[i][j]!=0&&pre[1]!=0){ int dif = (nums[i][j] - pre[1])/(i - pre[0]); for (int k = i+1; k < r; k++) { nums[k][j] = nums[k-1][j]+dif; } for (int k = i-1; k >= 0; k--) { nums[k][j] = nums[k+1][j]-dif; } f = true; flag[r+j]=true; break; }else if (nums[i][j]!=0){ pre[0] = i; pre[1] = nums[i][j]; } } } } return f; }