0
点赞
收藏
分享

微信扫一扫

【每日一题见微知著】BFS和DP——力扣第70场双周赛

2144. 打折购买糖果的最小开销

一家商店正在打折销售糖果。每购买 两个 糖果,商店会 免费 送一个糖果。

免费送的糖果唯一的限制是:它的价格需要小于等于购买的两个糖果价格的 较小值

  • 比方说,总共有 4 个糖果,价格分别为 1234 ,一位顾客买了价格为 23 的糖果,那么他可以免费获得价格为 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]

同时给你两个整数 lowerupper ,它们表示隐藏数组中所有数字的值都在 区间 [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 步。

同时给你一个整数数组 pricingstart ,其中 pricing = [low, high]start = [row, col] ,表示你开始位置为 (row, col) ,同时你只对物品价格在 闭区间 [low, high] 之内的物品感兴趣。同时给你一个整数 k

你想知道给定范围 排名最高k 件物品的 位置 。排名按照优先级从高到低的以下规则制定:

  1. 距离:定义为从 start 到一件物品的最短路径需要的步数(较近 距离的排名更高)。
  2. 价格:较低 价格的物品有更高优先级,但只考虑在给定范围之内的价格。
  3. 行坐标:较小 行坐标的有更高优先级。
  4. 列坐标:较小 列坐标的有更高优先级。

请你返回给定价格内排名最高的 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 - 1i 之间(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;
    }
}

结尾

举报

相关推荐

0 条评论