LeetCode刷题记153-975. 奇偶跳

6 篇文章 0 订阅

LeetCode刷题记153

975. 奇偶跳

题目
在这里插入图片描述

class Solution {
    public int oddEvenJumps(int[] A) {
        if (A.length == 0) return 0;
        // 记录每个数值出现在哪些下标中
        List<Integer>[] ind = new ArrayList[100005]; // 记录下标
        for (int i = 0; i < A.length; i ++) {
            if (ind[A[i]] == null) {
                ind[A[i]] = new ArrayList<Integer>();
            }
            ind[A[i]].add(i); 
        }
        // 记录出现过的数字的下一个比他大的数字
        int[] nt_max = new int[100005]; // 记录下一个大的数字
        int[] nt_min = new int[100005]; // 记录下一个小的数字
        Arrays.fill(nt_max, -1);
        Arrays.fill(nt_min, -1);
        int pre = -1;
        for (int i = 0; i < 100001; i ++) {
            if (ind[i] != null) {
                if (pre != -1) {
                    nt_max[pre] = i;
                    nt_min[i] = pre;
                } 
                pre = i;
            }
        }
        // 记录从一个位置跳到下一个位置的下标
        int[] nt_odd = new int[A.length]; // 记录奇数跳到下一个的位置
        int[] nt_even = new int[A.length]; // 记录偶数跳到下一个的位置
        Arrays.fill(nt_odd, -1);
        Arrays.fill(nt_even, -1);
        for (int i = 0; i < A.length; i ++) {
            ind[A[i]].remove(0); // 删除自己的下标
            if (ind[A[i]].size() > 0) { // 和自己一样的还有
                nt_even[i] = nt_odd[i] = ind[A[i]].get(0);
            } else {
                while (nt_max[A[i]] != -1 && ind[nt_max[A[i]]].size() == 0) {
                    nt_max[A[i]] = nt_max[nt_max[A[i]]]; // 下一个大的没有下标了,跳到下下个
                }
                if (nt_max[A[i]] != -1 && ind[nt_max[A[i]]].size() >= 0 ) {
                    nt_odd[i] = ind[nt_max[A[i]]].get(0); // 奇数跳到下一个的位置
                }

                while (nt_min[A[i]] != -1 && ind[nt_min[A[i]]].size() == 0) {
                    nt_min[A[i]] = nt_min[nt_min[A[i]]]; // 下一个小的没有下标了,跳到下下个
                }
                if (nt_min[A[i]] != -1 && ind[nt_min[A[i]]].size() >= 0 ) {
                    nt_even[i] = ind[nt_min[A[i]]].get(0); // 偶数跳到下一个的位置
                }
            }
        }
        // 记录从某一点能否跳到终点
        boolean[] odd = new boolean[A.length]; // 记录从i开始奇数跳能否到达终点
        boolean[] even = new boolean[A.length]; // 记录从i开始偶数跳能否到达终点
        odd[A.length - 1] = even[A.length - 1] = true;
        int ans = 1; // 最后一个点一定是的
        for (int i = A.length - 2; i >= 0; i --) {
            // 下一个奇数跳跳过去的点,再进行一次偶数跳可以跳到终点
            // 那么从这个点开始进行奇数跳就可以到达终点
            if (nt_odd[i] != -1 && even[nt_odd[i]]) {
                odd[i] = true;
                ans ++; // 因为一开始是奇数跳,如果可以跳到最后,那么这个点就可以是一个答案
            }
            // 下一个偶数跳跳过去的点,再进行一次奇数跳可以跳到终点
            // 那么从这个点开始进行偶数跳就可以到达终点
            if (nt_even[i] != - 1 && odd[nt_even[i]]) {
                even[i] = true; // 偶数跳开始可以跳到终点,但是不能算入答案
            }
        }
        return ans;
    }
}

题解都在代码注释里了,就是这个题目是栈的标签,但是我给做成了一个模拟题的感觉。
下面是官方的题解,没有我的快,哈哈哈哈哈,我上面的时间击败了100%,这个只有41.77%

class Solution {
    public int oddEvenJumps(int[] A) {
        int N = A.length;
        if (N <= 1) return N;
        boolean[] odd = new boolean[N];
        boolean[] even = new boolean[N];
        odd[N-1] = even[N-1] = true;

        TreeMap<Integer, Integer> vals = new TreeMap();
        vals.put(A[N-1], N-1);
        for (int i = N-2; i >= 0; --i) {
            int v = A[i];
            if (vals.containsKey(v)) {
                odd[i] = even[vals.get(v)];
                even[i] = odd[vals.get(v)];
            } else {
                Integer lower = vals.lowerKey(v);
                Integer higher = vals.higherKey(v);

                if (lower != null)
                    even[i] = odd[vals.get(lower)];
                if (higher != null) {
                    odd[i] = even[vals.get(higher)];
                }
            }
            vals.put(v, i);
        }

        int ans = 0;
        for (boolean b: odd)
            if (b) ans++;
        return ans;
    }
}

作者:LeetCode
链接:https://leetcode-cn.com/problems/odd-even-jump/solution/qi-ou-tiao-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

但是感觉这个TreeMap很实用啊,TreeMap的用法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值