leetcode每日一题(20241212)今天啥都不想干,在不情愿的状态下去看今天的每日一题了,第一次困难题一次过,哈哈哈,简单一点的困难题,看题:
2931 购买物品的最大开销 题目描述:
给你一个下标从 0 开始大小为 m * n 的整数矩阵 values ,表示 m 个不同商店里 m * n 件不同的物品。每个商店有 n 件物品,第 i 个商店的第 j 件物品的价值为 values[i][j] 。除此以外,第 i 个商店的物品已经按照价值非递增排好序了,也就是说对于所有 0 <= j < n - 1 都有 values[i][j] >= values[i][j + 1] 。
每一天,你可以在一个商店里购买一件物品。具体来说,在第 d 天,你可以:
选择商店 i 。
购买数组中最右边的物品 j ,开销为 values[i][j] * d 。换句话说,选择该商店中还没购买过的物品中最大的下标 j ,并且花费 values[i][j] * d 去购买。
注意,所有物品都视为不同的物品。比方说如果你已经从商店 1 购买了物品 0 ,你还可以在别的商店里购买其他商店的物品 0 。
请你返回购买所有 m * n 件物品需要的 最大开销 。
我看完题目就一个念头就是模拟维护一个列表,列表中放的是当前可以取到的物品,然后每次从一个列表中拿一个出来后就可以再去从这个values 数组 中取出剩余的消耗掉这一行最后面的一个放到当前列表中,每次从列表中取最小的。
涉及排序动态变化,我就想到了大/小堆根,接下来看代码:
第一版:
class Solution {
public long maxSpending(int[][] values) {
PriorityQueue<Integer> priorityQueue=new PriorityQueue<>();
int m=values.length;
int n=values[0].length;
int[] indexArr=new int[m];
for(int i=0;i<m;i++){
indexArr[i]=n-1;
}
long res=0L;
long day=1L;
do{
for(int i=0;i<m;i++){
if(indexArr[i]>=0){
priorityQueue.offer(values[i][indexArr[i]]);
indexArr[i]=indexArr[i]-1;
}
}
res+=day*priorityQueue.poll();
day++;
}while(day<=n);
while(!priorityQueue.isEmpty()){
res+=day*priorityQueue.poll();
day++;
}
return res;
}
}
第二版(因为每次消耗完一个数字只能再放进一个数字的,我第一版貌似有问题的,但是不知道为啥也过了。,看了解题后的):
class Solution {
public long maxSpending(int[][] values) {
PriorityQueue<int[]> priorityQueue=
new PriorityQueue<>((o1,o2)->{return values[o1[0]][o1[1]]-values[o2[0]][o2[1]];});
int m=values.length;
int n=values[0].length;
for(int i=0;i<m;i++){
priorityQueue.offer(new int[]{i,n-1});
}
long res=0L;
for(int i=1;i<=m*n;i++){
int[] temp=priorityQueue.poll();
int row=temp[0];
int col=temp[1];
res+=(long)values[row][col]*i;
if(col>0){
priorityQueue.offer(new int[]{row,col-1});
}
}
return res;
}
}
别人的代码真的太优雅了!!羡慕
加油!!