leetcode题解-55. Jump Game && 56. Merge Intervals

55, 题目:

Given an array of non-negative integers, you are initially positioned at the first index of the array.

Each element in the array represents your maximum jump length at that position.

Determine if you are able to reach the last index.

For example:
A = [2,3,1,1,4], return true.

A = [3,2,1,0,4], return false.

本题是为了判断是否可以达到数组的最后一个元素,其中数组的每个元素代表该步的最大跳数。其实题目的核心在于发现元素为0的点是否可以被成功跳过。如果不可以,则无法到达最后一个元素。一种最直观的思路就是使用一个变量记录当前可以到达的最远距离,在元素为0时判断该变量值是否大于其索引。代码入下:

    public boolean canJump(int[] nums) {
        int max_right=0;
        for(int i=0; i<nums.length; i++){
            if(nums[i] == 0 && max_right <= i && i != nums.length-1)
                return false;
            max_right = Math.max(max_right, i+nums[i]);
        }
        return true;
    }

后来看别人的代码发现,上面if语句的限制条件可以简化为max_right < i即可。另外一种思路就是,从后向前遍历数组,当遇到零时,开始向前索引,判断是否可以将其跳过。代码如下:

    public boolean canJump1(int[] nums) {
        if(nums.length < 2) return true;

        for(int curr = nums.length-2; curr>=0;curr--){
            if(nums[curr] == 0){
                int neededJumps = 1;
                while(neededJumps > nums[curr]){
                    neededJumps++;
                    curr--;
                    if(curr < 0) return false;
                }
            }
        }
        return true;
    }

56, 题目:

Given a collection of intervals, merge all overlapping intervals.

For example,
Given [1,3],[2,6],[8,10],[15,18],
return [1,6],[8,10],[15,18].

题意很简单,将数组进行整合。最关键的地方在于我们需要将题目给的链表先按照开始的下标进行排序,所以这里要定义一个比较方法。这也是第一次使用这个方法,在这里着重强调一下。对于list链表类型,如果里面保存的是我们自定义的数据类型,想要对其排序时,需要自己重写一下排序函数。将链表排序之后我们就可以按照前后元素的start和end之间的关系进行合并。代码入下:

    public static List<Interval> merge(List<Interval> intervals) {
        if(intervals.size() <= 1)
            return intervals;
        //第二个参数就是排序的依据,
        Collections.sort(intervals, new Comparator<Interval>() {
            @Override
            public int compare(Interval o1, Interval o2) {
                if(o1.start != o2.start)
                    return o1.start - o2.start;
                return o1.end - o2.end;
            }
        });
        Iterator<Interval> it = intervals.iterator();
        Interval tmp = it.next();
        while(it.hasNext()){
            Interval next = it.next();
            if(tmp.end <= next.start){
                tmp = next;
                continue;
            }else{
                tmp.end = Math.max(tmp.end, next.end);
                it.remove();
            }
        }
        return intervals;
    }

另外一种更好的方法就是使用两个数组分别保存start和end信息,然后将两个数组排序,这样可以节省很多时间。然后遍历数组,按照start和end之间的关系将结果写入到res。可以击败97%的用户。代码入下:

    public List<Interval> merge1(List<Interval> intervals) {
        // sort start&end
        int n = intervals.size();
        int[] starts = new int[n];
        int[] ends = new int[n];
        for (int i = 0; i < n; i++) {
            starts[i] = intervals.get(i).start;
            ends[i] = intervals.get(i).end;
        }
        Arrays.sort(starts);
        Arrays.sort(ends);
        // loop through
        List<Interval> res = new ArrayList<Interval>();
        for (int i = 0, j = 0; i < n; i++) { // j is start of interval.
            if (i == n - 1 || starts[i + 1] > ends[i]) {
                res.add(new Interval(starts[j], ends[i]));
                j = i + 1;
            }
        }
        return res;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值