代码随想录算法训练营第三十四天|LeetCode860,406,452

代码随想录算法训练营第三十四天|LeetCode860,406,452

860.柠檬水找零

第一思路:

5美元直接收下,10美元的找5美元的,20美元的先找10美元的,再找5美元的

20美元就是贪心的地方。

设置两个变量,分别记录5美元与10美元的数量,找零过程中有一个小于0那就代表找零失败

public static boolean lemonadeChange(int[] bills) {
        int count5 = 0;
        int count10 = 0;
        for (int bill:bills){
            switch (bill){
                case 5:
                    count5++;
                    break;
                case 10:
                    count5--;
                    if (count5<0){
                        return false;
                    }
                    count10++;
                    break;
                case 20:
                    count10--;
                    if (count10<0){
                        count10++;
                        count5 -= 3;
                        if (count5 < 0)
                            return false;
                    }else{
                        count5--;
                        if (count5<0){
                            return false;
                        }
                    }
                    break;
            }
        }
        return true;

406.根据身高重建队列 (*)

二维数组的排序怎么做?重写Arrays.sort里的compare

遇到两个维度权衡的时候,一定要先确定一个维度,再确定另一个维度。

如果两个维度一起考虑一定会顾此失彼,

要优先考虑哪个维度,一定是这个维度确定后,已经符合题目要求了,这就再去考虑另外一个维度

本题相信大家困惑的点是先确定k还是先确定h呢,也就是究竟先按h排序呢,还是先按照k排序呢?

如果按照k来从小到大排序,排完之后,会发现k的排列并不符合条件,身高也不符合条件,两个维度哪一个都没确定下来。

那么按照身高h来排序呢,身高一定是从大到小排(身高相同的话则k小的站前面),让高个子在前面。

此时我们可以确定一个维度了,就是身高,前面的节点一定都比本节点高!

而昨天分糖果的题,看上去从哪边开始比较都没有问题。

拍完身高以后怎么处理第二个值呢

那么只需要按照k为下标重新插入队列就可以了,为什么呢?

以图中{5,2} 为例:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zDA4skbd-1677658706547)(note.assets/20201216201851982.png)]

按照身高排序之后,优先按身高高的people的k来插入,后序插入节点也不会影响前面已经插入的节点,最终按照k的规则完成了队列。

所以在按照身高从大到小排序后:

局部最优:优先按身高高的people的k来插入。插入操作过后的people满足队列属性

全局最优:最后都做完插入操作,整个队列满足题目队列属性

  public int[][] reconstructQueue(int[][] people) {
        //身高从大到小排
        Arrays.sort(people, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                //如果两人身高一样,则k值较小的排在前面
                if (o1[0] == o2[0]){
                    return o1[1] - o2[1];
                }
                //正常情况下身高高的排在前面
                return o2[0] - o1[0];
            }
        });

        LinkedList<int[]> que = new LinkedList<>();
        //根据k值进行插入
        for (int[]p:people){
            que.add(p[1],p);
        }
        return que.toArray(new int[people.length][]);


    }

452. 用最少数量的箭引爆气球 (*)

我的思路:

根据points的start对数组进行排序,然后遍历这个数组,使用一个数组range记录第一个气球的直径

如果当前的start落到了range的范围内,则继续判断下一个气球,当气球的起点不在range内的时候,就用这个气球的直径替换掉range,count值再加加

遍历完数组,返回值。

第一次错误:

没有考虑气球中出现了[0,6] [0,9] 这种起点范围一样的情况,这种情况下,将范围较小的气球排在前面,比如这种情况下就将[0,6] 排到[0,9]前面

第二次错误:

range实际上是在不断的发生改变的。每次找到一个符合条件的,range就要进行相应的收缩。

这样的话就不用考虑第一次错误进行的处理了,因为range会进行收缩的。

参考题解:直接在point上进行判断,时间复杂度要低一点。有重叠的就把points[i][1]换成最小值如果气球重叠了,重叠气球中右边边界的最小值 之前的区间一定需要一个弓箭

    public static int findMinArrowShots(int[][] points) {

        int count = 1;

        Arrays.sort(points,(a,b)->{
            if (a[0] < b[0]){
                return -1;
            }
            if (a[0] == b[0]){
                if (a[1] < b[1]){
                    return -1;
                }
            }
            return 1;
        });
        int[] range = points[0];
        for (int i  = 1; i<points.length;i ++ ){
            //下一个气球的起点落到了范围内
            if (points[i][0] >= range[0] && points[i][0] <= range[1]){
                range[0] = points[i][0];
                range[1] = Math.min(range[1],points[i][1]);
                continue;
            }
            //下一个起点不在范围内
            if(points[i][0] > range[1]){
                range = points[i];
                count++;
            }
        }
        return count;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第二十二算法训练营主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小的子数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小的子数组,使得子数组的和大于等于给定的目标值。这里可以使用滑动窗口的方法来解决问题。使用两个指针来表示滑动窗口的左边界和右边界,通过移动指针来调整滑动窗口的大小,使得滑动窗口中的元素的和满足题目要求。具体实现的代码如下: ```python def minSubArrayLen(self, target: int, nums: List[int]) -> int: left = 0 right = 0 ans = float('inf') total = 0 while right < len(nums): total += nums[right] while total >= target: ans = min(ans, right - left + 1) total -= nums[left] left += 1 right += 1 return ans if ans != float('inf') else 0 ``` 以上就是第二十二算法训练营的内容。通过这些题目的练习,可以提升对双指针和滑动窗口等算法的理解和应用能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值