Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Leetcode 2612. Minimum Reverse Operations #231

Open
Woodyiiiiiii opened this issue Apr 2, 2023 · 0 comments
Open

Leetcode 2612. Minimum Reverse Operations #231

Woodyiiiiiii opened this issue Apr 2, 2023 · 0 comments

Comments

@Woodyiiiiiii
Copy link
Owner

Woodyiiiiiii commented Apr 2, 2023

看完题目,首先想到的是在数组中使用BFS。

观察规律,结合k,可以发现扩散范围跟奇偶有关。接着就很容易写出BFS题解。但发现TLE了,说明最坏情况下时间复杂度是O(nk)。然后我就不知道如何优化。

赛后,这个卡点的解决方法是利用平衡树来取数,可以使时间复杂度缩减为O(n+nlgn)。提前存好奇偶索引,两个TreeSet,然后利用**ceilling(E e)**方法(该方法取大于等于e参数的最小值),如此可以优化取数算法。TreeSet内置就是个优化的链表+红黑树的结构。这种写法算是取数的一种黑科技了。

同时要注意界定取数时的最小值和最大值。如果没超出时间范围还好说,如果超出了,就需要从0或n-1开始计算k大小的范围内的索引变化了。这也算是个小卡点。

class Solution {
    public int[] minReverseOperations(int n, int p, int[] banned, int k) {
        int[] res = new int[n];
        boolean[] visited = new boolean[n];
        for (int j : banned) {
            res[j] = -1;
            visited[j] = true;
        }
        visited[p] = true;

        TreeSet<Integer> even = new TreeSet<>(), odd = new TreeSet<>();
        for (int i = 0; i < n; ++i) {
            if (visited[i]) continue;
            if (i % 2 == 0) even.add(i);
            else odd.add(i);
        }

        Queue<Integer> q = new ArrayDeque<>();
        q.add(p);
        int steps = 1;
        TreeSet<Integer> set = new TreeSet<>();
        int min, max, mCurrent;
        while (!q.isEmpty()) {
            int sz = q.size();
            while (sz-- > 0) {
                int cur = q.poll();
                if (k % 2 == 0) {
                    if (cur + 1 < n) {
                        set = (cur + 1) % 2 == 0 ? even : odd;
                    } else if (cur - 1 >= 0) {
                        set = (cur - 1) % 2 == 0 ? even : odd;
                    }
                } else {
                    set = cur % 2 == 0 ? even : odd;
                }

                // calculate min index
                if (cur < k - 1) {
                    min = (k - 1) - cur;
                }else {
                    min = cur - k + 1;
                }

                // calculate max index
                if (cur + k - 1 >= n) {
                    max = (n - k) + (n - cur - 1);
                }else {
                    max = cur + k - 1;
                }

                Integer mid = set.ceiling(min);
                while (mid != null && mid <= max) {
                    if (visited[mid]) {
                        set.remove(mid);
                        min += 2;
                        mid = set.ceiling(min);
                        continue;
                    }
                    visited[mid] = true;
                    q.add(mid);
                    res[mid] = steps;
                    set.remove(mid);
                    min += 2;
                    mid = set.ceiling(min);
                }
            }
            ++steps;
        }
        for (int i = 0; i < n; ++i) {
            if (res[i] == 0 && i != p) res[i] = -1;
        }
        return res;
    }
}

还有个并查集的写法,这里我不写了XD,可以看参考资料。

类似题目:


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant