1.魔术操作
给一个包含n个整数元素的集合a,一个包含m个整数元素的集合b。 定义magic操作为,从一个集合中取出一个元素,放到另一个集合里,且操作过后每个集合的平均值都大于操作前。 注意以下两点: 1)不可以把一个集合的元素取空,这样就没有平均值了 2)值为x的元素从集合b取出放入集合a,但集合a中已经有值为x的元素,则a的 平均值不变(因为集合元素不会重复),b的平均值可能会改变(因为x被取出了) 问最多可以进行多少次操作
思想:要使取完一个数后 两个集合的平均值都变大 则只能取两个平均值之间的数字。
// 请保证arr1无重复值、arr2中无重复值,且arr1和arr2肯定有数字
public static int maxOps(int[] arr1, int[] arr2) {
double sum1 = 0;
for (int i = 0; i < arr1.length; i++) {
sum1 += (double) arr1[i];
}
double sum2 = 0;
for (int i = 0; i < arr2.length; i++) {
sum2 += (double) arr2[i];
}
//判断两个集合的平均值是否一样 如果一样 则不能取 怎么取都要使其中一个变小
if (avg(sum1, arr1.length) == avg(sum2, arr2.length))
return 0;
//下面操作就是进行重定位 重新赋值一下 方便整理
int[] arrMore = null;
int[] arrLess = null;
double sumMore = 0;
double sumLess = 0;
if (avg(sum1, arr1.length) > avg(sum2, arr2.length)) {
arrMore = arr1;
sumMore = sum1;
arrLess = arr2;
sumLess = sum2;
} else {
arrMore = arr2;
sumMore = sum2;
arrLess = arr1;
sumLess = sum1;
}
//排序大的数组 为什么不排序小的数组呢?因为只能从大数组当中取数据
Arrays.sort(arrMore);
HashSet<Integer> setLess = new HashSet<>();
for (int num : arrLess) setLess.add(num);
int moreSize = arrMore.length;
int lessSize = arrLess.length;
int ops = 0;
for (int i = 0; i < arrMore.length; i++) {
double cur = (double) arrMore[i];
//当前值小于大数组平均值&&大于小数组的平均值&&小数组当中没有该元素 则把该数字放到小数组当中
if (cur < avg(sumMore, moreSize) && cur > avg(sumLess, lessSize)
&& !setLess.contains(arrMore[i])) {
sumMore -= cur;
moreSize--;
sumLess += cur;
lessSize++;
setLess.add(arrMore[i]);
ops++;
}
}
return ops;
}
public static double avg(double sum, int size) {
return sum / (double) (size);
}
2.超级洗衣机
public int findMinMoves(int[] machines) {
int size = machines.length;
int sum = 0;
for (int i = 0; i < size; i++)
sum += machines[i];//计算出总共的衣服
if (sum % size != 0) return -1;//如果每台机器不能均分 直接返回-1
int avg = sum / size;//获得每台机器应该是多少个
int leftSum = 0;//左边衣服和
int ans = 0;
for (int i = 0; i < machines.length; i++) {
//获得左边已经有的衣服和需要衣服之差 如果差为+代表左边衣服太多了需要吐出来 否则需要收衣服
int L = leftSum - avg*i ;
//获得右边已经有的衣服和需要衣服之差 如果差为+代表左边衣服太多了需要吐出来 否则需要收衣服
int R = (sum - leftSum - machines[i])-(size - i - 1) * avg ;
//如果当前位置两边都是负数 则当前位置必须吐衣服给两边 由于每次只能吐一件 则需要|L+R|次
if (L < 0 && R < 0)
ans = Math.max(ans, Math.abs(L+R));
//否则 一正一负 或者 两个都为正 都是下面这个 为什么呢?
//一正一负 题目虽然说了 每台只能吐或者收 但是不同机器可以连续工作 你是一正一负 则可以变成一条线 需要的次数就是最大的那个数
//eg: +6 2 -4 6往右边吐的时候 2也可以往-4那吐 但是6必须吐完 则需要6次 当为 +6 2 +7 则必须吐7次
else
ans = Math.max(ans, Math.max(Math.abs(L), Math.abs(R)));
leftSum += machines[i];//每次计算完 左边和累加
}
return ans;
}
3.螺旋打印矩阵
public int[] spiralOrder(int[][] matrix) {
if(matrix.length==0||matrix[0].length==0) return new int[0];
int[] res=new int[matrix.length*matrix[0].length];//需要的数组大小
int x1=0,y1=0,x2=matrix.length-1,y2=matrix[0].length-1;//两个坐标的位置
//当两个坐标的位置错开了 就说明打印完成了 不理解可以画个图
while (x1 <= x2 && y1<=y2)
print(matrix,x1++,y1++,x2--,y2--,res);
return res;
}
//打印模板 每次是那一个圈中的两个点 左上角和右下角的点 每次只打印那一圈
//根据传过来的两个坐标 顺时针打印2个点连成的矩阵
int index=0;
public void print(int[][] matrix, int x1, int y1, int x2, int y2, int[] list){
//如果两个坐标一条横线上 则直接横线打印
if(x1==x2)
for (int i = y1; i <=y2 ; i++)
list[index++]=matrix[x1][i];
//如果两个坐标一条竖线上 则直接竖线打印
else if(y1==y2)
for (int i = x1; i <=x2 ; i++)
list[index++]=matrix[i][y1];
else{
//否则说明两个坐标构成了矩形 则顺时针打印
for (int i = y1; i <y2 ; i++)
list[index++]=matrix[x1][i];
for (int i = x1; i <x2 ; i++)
list[index++]=matrix[i][y2];
for (int i = y2; i >y1 ; i--)
list[index++]=matrix[x2][i];
for (int i = x2; i >x1 ; i--)
list[index++]=matrix[i][y1];
}
}
4.旋转矩阵
力扣地址:跟上面那个螺旋打印矩阵类似 定义一个模板方法 只操作这一圈的数据
public void rotate(int[][] matrix) {
int x1=0,y1=0,x2=matrix.length-1,y2=matrix[0].length-1;//两个坐标的位置
//当两个坐标的位置错开了 就说明旋转完成了 不理解可以画个图
while (x1 <= x2 && y1<=y2)
xunzhuan(matrix,x1++,y1++,x2--,y2--);
}
//旋转模板 每次是那一个圈中的两个点 左上角和右下角的点
//根据传过来的两个坐标 旋转就行
public void xunzhuan(int[][] matrix, int x1, int y1, int x2, int y2){
//由于是n*n的矩阵 则不存在像打印螺旋矩阵那种需要判断是否是一根线
//x2 - x1 代表每次那一圈需要操作几次
for (int i = 0; i < x2 - x1; i++) {
//每次交换那四个数的值
int temp=matrix[x1+i][y2];
matrix[x1+i][y2]=matrix[x1][y1+i];
matrix[x1][y1+i]=matrix[x2-i][y1];
matrix[x2-i][y1]=matrix[x2][y2-i];
matrix[x2][y2-i]=temp;
}
}
5.实现一个最小栈
class MinStack {
private Stack<Integer> minStack;//存放最小值的栈
private Stack