Problem A-判断矩阵经轮转后是否一致
题意: 以 90 度顺时针轮转矩阵 mat
中的元素 若干次,如果mat
矩阵与target
一致,返回true
,否则返回false
思路: 直接模拟就可以了,做这题的时候还费劲写了一个原地算法,y神说了没必要,直接开一个二维数组即可。
代码:
Java中不能直接判断两个二维数组的内容是否相同,恶心!
class Solution {
public boolean findRotation(int[][] mat, int[][] target) {
int n = mat.length, num = 3;
boolean flag = false;
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
if (mat[i][j] != target[i][j]) {
flag = true; break;
}
}
if (flag)break;
}
if (!flag)return true;
while(num-- > 0) {
for(int i=0; i<n/2; i++) {
for(int j=i; j<n-i-1; j++) {
int t = mat[i][j];
mat[i][j] = mat[n-j-1][i];
mat[n-j-1][i] = mat[n-i-1][n-j-1];
mat[n-i-1][n-j-1] = mat[j][n-i-1];
mat[j][n-i-1] = t;
}
}
flag = false;
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
if (mat[i][j] != target[i][j]) {
flag = true; break;
}
}
if (flag)break;
}
if (!flag)return true;
}
return false;
}
}
Problem B-使数组元素相等的减少操作次数
思路: 每个元素a需要经历t个阶段最后变成相等最小值,t就是数组中比元素a小的元素种类和。所以先把数组排序,然后统计(元素前边比他小的元素种类即可)
代码:
class Solution {
public int reductionOperations(int[] nums) {
int len = nums.length;
Arrays.sort(nums);
int pre[] = new int[len + 1];
int count = 0;
pre[0] = 0;
for (int i = 1; i < len; i++) {
if ((nums[i] - nums[i-1]) != 0) {
pre[i] = pre[i - 1] + 1;
} else {
pre[i] = pre[i - 1];
}
}
// 下边的累加可以放在第一个for循环中
int res = 0;
for (int i = 1; i < len; i++) {
res += pre[i];
}
return res;
}
}
Problem C-使二进制字符串字符交替的最少反转次数
思路: 两种类型的操作,让统计第二种类型操作的最少次数。第一种类型操作的特殊性,让我想到将两个原串拼接在一起,然后滑动窗口,取第二种操作的最少次数。最终字符串有两种:“0101010101…”或"1010101010…",比较两串不同元素个数即可。
代码:
class Solution {
public int minFlips(String s) {
int len = s.length(), t = 2, res = Integer.MAX_VALUE;
String time = s + s;
t = 2;
while (t-- > 0) {
int count = 0, j = t;
for (int k = 0; k < len; j ^= 1, k++) {
count += (time.charAt(k) == (j +'0')) ? 0:1;
}
res = Math.min(res, count);
for (int k = len, p = t; k < len*2; j ^= 1, p ^= 1, k++) {
count -= (time.charAt(k - len) == (p +'0')) ? 0:1;
count += (time.charAt(k) == (j +'0')) ? 0:1;
res = Math.min(res, count);
}
}
return res;
}
}
Problem D-装包裹的最小浪费空间
思路: 遍历supplier,让box二分package,计算出该supplier所需要的总容积,最后取最小的容积,减去packages的总和。如果遍历package,让package二分box,会超时。
代码:
class Solution {
final long mod = (long)(1e9 + 7);
final long inf = (long)1e18;
public int minWastedSpace(int[] packages, int[][] boxes) {
int supplierNum = boxes.length, packagesNum = packages.length;
long res = inf, sum = 0;
// 包裹总和
for (int i = 0; i < packagesNum; i++) {
sum += packages[i];
}
Arrays.sort(packages);
for (int i = 0; i < supplierNum; i++) {
int len = boxes[i].length, left = -1, right = packagesNum - 1, last = -1;
long count = -sum;
Arrays.sort(boxes[i], 0, len);
if (packages[packagesNum - 1] > boxes[i][len - 1]) continue;
// 统计box总的容积
for (int j = 0; j < len; j ++) {
left = upperBound(packages, left, right, boxes[i][j]);
if (left == last) continue;
count += ((long)(left - last) * boxes[i][j]);
last = left;
}
res = Math.min(res, count);
}
if (res == inf) return -1;
return (int)(res % mod);
}
public int upperBound(int[] a, int left, int right, int key) {
int mid;
while (left < right) {
mid = (left + right + 1) >> 1;
if (a[mid] > key) {
right = mid - 1;
} else {
left = mid;
}
}
return left;
}
}