2144. 打折购买糖果的最小开销
一家商店正在打折销售糖果。每购买 两个 糖果,商店会 免费 送一个糖果。
免费送的糖果唯一的限制是:它的价格需要小于等于购买的两个糖果价格的 较小值 。
- 比方说,总共有
4
个糖果,价格分别为1
,2
,3
和4
,一位顾客买了价格为2
和3
的糖果,那么他可以免费获得价格为1
的糖果,但不能获得价格为4
的糖果。
给你一个下标从 0 开始的整数数组 cost
,其中 cost[i]
表示第 i
个糖果的价格,请你返回获得 所有 糖果的 最小 总开销。
class Solution {
public int minimumCost(int[] cost) {
Arrays.sort(cost);
int i=cost.length-1;
int sum=0;
while(i>=0){
sum+=cost[i--];
if(i>=0)
sum+=cost[i--];
if(i>=0){
i--;
}
}
return sum;
}
}
2145. 统计隐藏数组数目-Mid
给你一个下标从 0 开始且长度为 n
的整数数组 differences
,它表示一个长度为 n + 1
的 隐藏 数组 相邻 元素之间的 差值 。更正式的表述为:我们将隐藏数组记作 hidden
,那么 differences[i] = hidden[i + 1] - hidden[i]
。
同时给你两个整数 lower
和 upper
,它们表示隐藏数组中所有数字的值都在 闭 区间 [lower, upper]
之间。
-
比方说,
differences = [1, -3, 4]
,
lower = 1
,
upper = 6
,那么隐藏数组是一个长度为
4
且所有值都在
1
和
6
(包含两者)之间的数组。
[3, 4, 1, 5]
和[4, 5, 2, 6]
都是符合要求的隐藏数组。[5, 6, 3, 7]
不符合要求,因为它包含大于6
的元素。[1, 2, 3, 4]
不符合要求,因为相邻元素的差值不符合给定数据。
请你返回 符合 要求的隐藏数组的数目。如果没有符合要求的隐藏数组,请返回 0
。
class Solution {
public int numberOfArrays(int[] differences, int lower, int upper) {
int max=0;
int min=0;
int dp=0;
for(int i:differences){
dp+=i;
if(dp<min){
min=dp;
}
if(dp>max){
max=dp;
}
//剪枝,不然有可能越界
if(upper-lower-(max-min)+1<0){
return 0;
}
}
return upper-lower-(max-min)+1<0?0:upper-lower-(max-min)+1;
}
}
2146. 价格范围内最高排名的 K 样物品-Mid
给你一个下标从 0 开始的二维整数数组 grid
,它的大小为 m x n
,表示一个商店中物品的分布图。数组中的整数含义为:
0
表示无法穿越的一堵墙。1
表示可以自由通过的一个空格子。- 所有其他正整数表示该格子内的一样物品的价格。你可以自由经过这些格子。
从一个格子走到上下左右相邻格子花费 1
步。
同时给你一个整数数组 pricing
和 start
,其中 pricing = [low, high]
且 start = [row, col]
,表示你开始位置为 (row, col)
,同时你只对物品价格在 闭区间 [low, high]
之内的物品感兴趣。同时给你一个整数 k
。
你想知道给定范围 内 且 排名最高 的 k
件物品的 位置 。排名按照优先级从高到低的以下规则制定:
- 距离:定义为从
start
到一件物品的最短路径需要的步数(较近 距离的排名更高)。 - 价格:较低 价格的物品有更高优先级,但只考虑在给定范围之内的价格。
- 行坐标:较小 行坐标的有更高优先级。
- 列坐标:较小 列坐标的有更高优先级。
请你返回给定价格内排名最高的 k
件物品的坐标,将它们按照排名排序后返回。如果给定价格内少于 k
件物品,那么请将它们的坐标 全部 返回。
class Solution {
public List<List<Integer>> highestRankedKItems(int[][] grid, int[] pricing, int[] start, int k) {
List<int[]> listAns=new ArrayList<>();
List<int[]> listCur=new ArrayList<>();
int countCur=0;
int countAns=0;
int m=grid.length;
int n=grid[0].length;
int[][] d=new int[][]{{-1,0},{1,0},{0,-1},{0,1}};
int p=grid[start[0]][start[1]];
if(p<=pricing[1]&&p>=pricing[0]){
listAns.add(new int[]{0,p,start[0],start[1]});
countAns++;
}
grid[start[0]][start[1]]=0;
listCur.add(new int[]{start[0],start[1]});
countCur++;
int step=0;
while(!listCur.isEmpty()){
//countCur当前步数需要历遍的节点数,listCur保存节点
step++;
int midCount=countCur;
countCur=0;
while(midCount-->0){
int[] curPoint=listCur.remove(0);
for(int[] i:d){
int x=curPoint[0]+i[0];
int y=curPoint[1]+i[1];
if(x<0||x>=m||y<0||y>=n){
continue;
}
int price=grid[x][y];
if(price==0){
continue;
}
if(price>=pricing[0]&&price<=pricing[1]){
listAns.add(new int[]{step,price,x,y});
countAns++;
}
grid[x][y]=0;
listCur.add(new int[]{x,y});
countCur++;
}
}
if(countAns>=k){
break;
}
}
int[][] listA=new int[listAns.size()][4];
for(int i=0;i<listAns.size();i++){
listA[i]=listAns.get(i);
}
Arrays.sort(listA,new MyComparator());
List<List<Integer>> ans=new ArrayList<>();
int need=0;
for(int[] i:listA){
List<Integer> mid=new ArrayList<>();
mid.add(i[2]);
mid.add(i[3]);
ans.add(mid);
if(++need>=k){
break;
}
}
return ans;
}
class MyComparator implements Comparator<int[]>{
public int compare(int[] a, int[] b) {
if(a[0]>b[0]){
return 1;
}
else if(a[0]==b[0]){
if(a[1]>b[1]){
return 1;
}
else if(a[1]==b[1]){
if(a[2]>b[2]){
return 1;
}
else if(a[2]==b[2]){
if(a[3]>b[3]){
return 1;
}
}
}
}
return -1;
}
}
}
2147. 分隔长廊的方案数-Hard
在一个图书馆的长廊里,有一些座位和装饰植物排成一列。给你一个下标从 0 开始,长度为 n
的字符串 corridor
,它包含字母 'S'
和 'P'
,其中每个 'S'
表示一个座位,每个 'P'
表示一株植物。
在下标 0
的左边和下标 n - 1
的右边 已经 分别各放了一个屏风。你还需要额外放置一些屏风。每一个位置 i - 1
和 i
之间(1 <= i <= n - 1
),至多能放一个屏风。
请你将走廊用屏风划分为若干段,且每一段内都 恰好有两个座位 ,而每一段内植物的数目没有要求。可能有多种划分方案,如果两个方案中有任何一个屏风的位置不同,那么它们被视为 不同 方案。
请你返回划分走廊的方案数。由于答案可能很大,请你返回它对 109 + 7
取余 的结果。如果没有任何方案,请返回 0
。
class Solution {
public int numberOfWays(String corridor) {
int i=0;
int midCountP=-1;
long ans=1;
while(i<corridor.length()){
//查找两个椅子
int midCountTwoC=0;
while(midCountTwoC!=2&&i<corridor.length()){
if(corridor.charAt(i)=='S'){
midCountTwoC++;
}
i++;
}
//如果不够两个,说明不是双数,不可能分成功,或没有椅子,分法都为0
if(midCountTwoC!=2){
return 0;
}
//统计当前位置之前的分法
if(midCountP!=-1)
ans=(ans*(midCountP+1))%1000000007;
midCountP=0;
//统计该位置之后有多少个连续的植物,插入屏风的位置+1
while(i<corridor.length()){
if(corridor.charAt(i)=='P'){
midCountP++;
i++;
}
else{
break;
}
}
}
return (int)ans;
}
}