ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[Leetcode Weekly Contest]295

2022-07-04 21:01:22  阅读:181  来源: 互联网

标签:ch String 删除 nums int Contest new 295 Leetcode


链接:LeetCode

[Leetcode]2287. 重排字符形成目标字符串

给你两个下标从 0 开始的字符串 s 和 target 。你可以从 s 取出一些字符并将其重排,得到若干新的字符串。

从 s 中取出字符并重新排列,返回可以形成 target 的 最大 副本数。

遍历即可。

class Solution {
    public int rearrangeCharacters(String s, String target) {
        HashMap<Character, Integer> sCounter = new HashMap<>();
        HashMap<Character, Integer> targetCounter = new HashMap<>();
        for(var ch:s.toCharArray()) {
            sCounter.put(ch, sCounter.getOrDefault(ch, 0)+1);
        }
        for(var ch:target.toCharArray()) {
            targetCounter.put(ch, targetCounter.getOrDefault(ch, 0)+1);
        }
        int res = s.length();
        for(var ch:targetCounter.keySet()) {
            res = Math.min(res, sCounter.getOrDefault(ch,0)/targetCounter.get(ch));
        }
        return res;
    }
}

[Leetcode]2288. 价格减免

句子 是由若干个单词组成的字符串,单词之间用单个空格分隔,其中每个单词可以包含数字、小写字母、和美元符号 '$' 。如果单词的形式为美元符号后跟着一个非负实数,那么这个单词就表示一个价格。
例如 "$100"、"$23" 和 "$6.75" 表示价格,而 "100"、"$" 和 "2$3" 不是。
注意:本题输入中的价格均为整数。

给你一个字符串 sentence 和一个整数 discount 。对于每个表示价格的单词,都在价格的基础上减免 discount% ,并 更新 该单词到句子中。所有更新后的价格应该表示为一个 恰好保留小数点后两位 的数字。
返回表示修改后句子的字符串。

分隔每个单词,判断是否符合要求,减去折扣,把字符串拼回来。

class Solution {
    public String discountPrices(String sentence, int discount) {
        String[] words = sentence.split(" ");
        for(int i=0;i<words.length;++i) {
            if(isPrice(words[i])) words[i] = getDisocunt(words[i], discount);
        }
        String res = "";
        for(int i=0;i<words.length;++i) {
            res += words[i];
            if(i!=words.length-1) res += " ";
        }
        return res;
    }

    public boolean isPrice(String word) {
        int n = word.length();
        if(word.charAt(0) != '$' || n < 2) return false;
        for(int i=1;i<n;i++) {
            if(word.charAt(i) > '9' || word.charAt(i) < '0') return false;
        }
        return true;
    }

    public String getDisocunt(String word, int discount) {
        long price = 0;
        for(int i=1;i<word.length();i++) {
            price  = price * 10 + (word.charAt(i)-'0');
        }
        return String.format("$%.2f", price/100.0*(100-discount));
    }
}

[Leetcode]2289. 使数组按非递减顺序排列

给你一个下标从 0 开始的整数数组 nums 。在一步操作中,移除所有满足 nums[i - 1] > nums[i] 的 nums[i] ,其中 0 < i < nums.length 。

重复执行步骤,直到 nums 变为 非递减 数组,返回所需执行的操作数。

单调栈。
对于每个 \(nums[i]\),如果它被消除,其要么是被 左侧第一个更大的元素 \(nums[j]\) 消除的,要么是下面的情况。
这种情况是当 \(nums[j]\) 消除 \(nums[i]\) 之前,\(nums[j]\) 自身已经被 \(nums[k] (k < j)\) 消除。但是这种情况下,相当于 \(nums[k]\) 代替了 \(nums[j]\) 的位置,无论这种替换发生了多少次,都不会影响最终答案。因此 仍然只需考虑左侧第一大元素 \(nums[j]\) 即可。

我们可以用 单调栈 求左侧第一个更大元素。(如果找不到左侧第一个更大元素,那么它永远不会被消除)

设 \(nums[i]\) 被 \(nums[j](j < i)\) 消除。那么,位于 j 和 i 之间的元素一定被首先消除,使得 \(nums[j]\) 和 \(nums[i]\) 相邻,然后再是 \(nums[j]\) 消除 \(nums[i]\)。设 \(f[i]\) 为 \(nums[i]\) 被消除所需的轮数,那么 \(f[i] = \displaystyle{\max(f[j+1]\dots f[i-1]) + 1}\) 可以在更新单调栈时同时统计。

我们只需要统计 \([i+1,j-1]\) 中 仍然在单调栈里的元素 的步数中的最大值即可。因为那些不在单调栈里的元素,当它们被 pop 之后,一定会 push 进一个比他们的最大值 max 还大 1 的元素,因此这个被 push 进的元素可以 “代表” 所有被 pop 的元素。

最终的答案就是 \(\max(f[i])\)。

class Solution {
    /**
    * [9   1   2   4    3    5    5]
    *
    * 9
    * -----------------------------6
    * ------------------------5
    * -------------4
    * -------------------3
    * --------2
    * ----1
    *
    *---------------------------------
    * 单调递减队列
    *到 1 的时候 9 在队列中 所以 1是 需要被删除的 时间点为 1
    *到 2 的时候 9 1 在队列中,要删除2需要先删除1, 时间点为 1 t(1)+1
    *到 4 的时候 9 2 在队列中,要删除4需要先删除2, 时间点为 2 t(2)+1
    *到 3 的时候 9 4 在队列中,要删除3不需要先删除其他的值,所以删除3的时间点为1
    *到 5 的时候 9 4 3 在队列中,要删除5 需要先删除 4,3,所以删除5的时间点为t(4)+1
    *到 6 的时候 9 5 在队列中,要删除6 需要先删除 5,所以删除6的时间点为t(5)+1
    */
    public int totalSteps(int[] nums) {
        int ans = 0;
        ArrayDeque<int[]> stack = new ArrayDeque<>();
        for (int num : nums) {
            //要删除当前num 的时间点
            int maxT = 0;
            //单调递减队列
            while (!stack.isEmpty() && stack.peek()[0] <= num) {
                //左边小于等于num的值都需要在num被删除之前删掉,此时maxT 为删掉左边这些小与等于num的数的最大时间
                maxT = Math.max(maxT, stack.pop()[1]);
            }
            //如果stack 不为空,所有还有左边还有比num值大的情况,表示num需要被删除,如果为空,说明num不用删除
            if (!stack.isEmpty()) {
                maxT++;
            }
            stack.push(new int[]{num, maxT});
            ans = Math.max(ans, maxT);
        }
        return ans;
    }
}

[Leetcode]2290. 到达角落需要移除障碍物的最小数目

给你一个下标从 0 开始的二维整数数组 grid ,数组大小为 m x n 。每个单元格都是两个值之一:

  • 0 表示一个 空 单元格,
  • 1 表示一个可以移除的 障碍物 。

你可以向上、下、左、右移动,从一个空单元格移动到另一个空单元格。
现在你需要从左上角 (0, 0) 移动到右下角 (m - 1, n - 1) ,返回需要移除的障碍物的 最小 数目。

BFS。
把障碍物当作可以经过的单元格,经过它的代价为 1,空单元格经过的代价为 0。我们可以用 Dijkstra,但还可以用 0-1 BFS 来将时间复杂度优化至 \(O(mn)\)。

class Solution {
    public int minimumObstacles(int[][] grid) {
        int n = grid.length, m = grid[0].length;
        int[][] res = new int[n][m];
        for(int i=0;i<n;++i){
            for(int j=0;j<m;++j){
                res[i][j] = Integer.MAX_VALUE;
            }
        }
        res[0][0] = 0;
        //Queue<int[]> queue = new PriorityQueue<int[]>((a,b) -> res[a[0]][a[1]]-res[b[0]][b[1]]);
        ArrayDeque<int[]> queue = new ArrayDeque<>();
        queue.add(new int[] {0,0});
        while(!queue.isEmpty()) {
            int[] q = queue.pollFirst();
            int x = q[0], y = q[1];
            for(int i=0;i<4;++i) {
                int new_x = x, new_y = y;
                if(i==0) new_x--;
                else if(i==1) new_x++;
                else if(i==2) new_y--;
                else if(i==3) new_y++;
                if(new_x>=0 && new_x <=n-1 && new_y>=0&&new_y<=m-1 && (res[x][y]+grid[new_x][new_y] < res[new_x][new_y])) {
                    if(grid[new_x][new_y] == 0) queue.offerFirst(new int[]{new_x,new_y});
                    else queue.offerLast(new int[]{new_x,new_y});
                    res[new_x][new_y] = res[x][y]+grid[new_x][new_y];
                }
            }
        }
        return res[n-1][m-1];
    }
}

参考:
LeetCode
LeetCode

标签:ch,String,删除,nums,int,Contest,new,295,Leetcode
来源: https://www.cnblogs.com/hellojamest/p/16444415.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有