算法好题分享

本文详细介绍了如何解决两个算法问题:一是通过最少跳跃到达数组末尾,二是根据身高重建队列。对于跳跃游戏,关键在于找到每次跳跃能覆盖的最大范围,逐步更新可达范围并计算跳跃次数。对于队列重建,采用了身高降序排列并考虑k值来确定正确位置。这两个问题均展示了有效的数组处理和排序策略。
摘要由CSDN通过智能技术生成

题目描述如下:力扣

给定一个非负整数数组,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

你的目标是使用最少的跳跃次数到达数组的最后一个位置。

示例:

  • 输入: [2,3,1,1,4]
  • 输出: 2
  • 解释: 跳到最后一个位置的最小跳跃数是 2。从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。

说明: 假设你总是可以到达数组的最后一个位置。

拿到这道题时,我的思路是:判断当前可到达的最大范围是否能到达数组的最后一个位置,若不能,则遍历这个范围,寻找在这个范围里可到达的最大范围,并从最大范围遍历,也就是每一次都选取跳的最远的距离,但是我忽略了一件事情,就是跳的最远虽然次数最少,但不代表这种跳法一定能跳到终点,所以我改变了思路,初始化当前最远为第一个元素的值,并在该范围内求取最大距离,若最大距离可到达终点,则直接输出结果,若不能,则遍历当前最大范围内的所有元素,保存当前最大范围内的下一次最大范围,当遍历的i达到当前最大范围时,更新当前最大范围,次数加1,下面直接上代码:

    public int jump(int[] nums) {
        //判断数组长度,若为1,则直接返回0
        int len = nums.length;
        if (len == 1) return 0;
        //初始化当前最大范围为第一个元素值
        int cur = nums[0];
        //如果当前最大范围可直接到达终点,则直接返回1
        if (cur >= len - 1) return 1;
        //如果当前最大范围无法直接到达终点,则最少要跳1次
        int result = 1;
        //初始化下一次最大范围
        int next = nums[0];
        //遍历每一个元素
        for (int i = 1; i < len; i++) {
            //更新下一步覆盖最远距离下标,若下一步覆盖了终点,则直接返回结果
            next = Math.max(nums[i] + i, next);
            if (next >= len - 1) return ++result;
            //如果走到当前最大范围,且尚未到达终点则次数加1,并更新当前最大范围
            if (i == cur) {
                result++;
                cur = next;
            }
        }
        return result;
    }

算法题-根据身高重建队列力扣

假设有打乱顺序的一群人站成一个队列,数组 people 表示队列中一些人的属性(不一定按顺序)。每个 people[i] = [hi, ki] 表示第 i 个人的身高为 hi ,前面 正好 有 ki 个身高大于或等于 hi 的人。

请你重新构造并返回输入数组 people 所表示的队列。返回的队列应该格式化为数组 queue ,其中 queue[j] = [hj, kj] 是队列中第 j 个人的属性(queue[0] 是排在队列前面的人)。

 public int[][] reconstructQueue(int[][] people) {
        //身高从大到小排(身高相同,k小的站前面)
        Arrays.sort(people, (a, b) -> {
            if (a[0] == b[0]) return a[1] - b[1];
            //身高不同时按身高降序排
            return b[0] - a[0];
        });

        LinkedList<int[]> que = new LinkedList<>();
        //void add(int index, Object element)
        //此方法再列表中的指定索引处插入元素,它将当前位于该位置的元素(如果有)和任何后续元素右移,然后在其索引处增加一个
        for (int[] person : people) {
            que.add(person[1],person);
        }
        return que.toArray(new int[people.length][]);
    }

算法题-用最少数量的箭引爆气球力扣

有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points ,其中points[i] = [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。

一支弓箭可以沿着 x 轴从不同点 完全垂直 地射出。在坐标 x 处射出一支箭,若有一个气球的直径的开始和结束坐标为 xstart,xend, 且满足  xstart ≤ x ≤ xend,则该气球会被 引爆 。可以射出的弓箭的数量 没有限制 。 弓箭一旦被射出之后,可以无限地前进。

给你一个数组 points ,返回引爆所有气球所必须射出的 最小 弓箭数 。

    public int findMinArrowShots(int[][] points) {
        //按照气球的起始位置排序
        Arrays.sort(points, Comparator.comparingInt(a -> a[0]));
        //初始化箭的数量为1只
        int number = 1;
        //初始化右边界为第一个气球的右边界
        int right = points[0][1];
        for (int[] p : points) {
            //如果该气球的起始位置超过了上一个气球的结束位置,则需要多一箭
            if (p[0] > right) {
                right = p[1];
                number++;
                //如果开始位置在上一个气球的结束位置内,则判断结束位置是否变小
            } else {
                if (p[1] < right)  right = p[1];
            }
        }
        return number;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值