algorithm - 线性时间解决方案

标签 algorithm language-agnostic

我在面试的时候被问到这个问题。

你站在 0 点,你必须到达位置 X。你可以跳到 D(1 到 D)。如果 X > D,很明显你无法在初始跳跃时到达位置 X。

现在从 1 到 N 每秒都有瓦片出现在随机位置。这是一个零索引数组 A[k],其中 A[k] 表示瓦片在第 k 秒出现的位置。你必须找出,在哪一秒你有可能到达(或穿越)目的地 X。

如果在初始或 A[0] 之后可能,则返回 0,或返回最小秒数。如果在所有拼贴之后仍然不可能,则返回 -1。

约束: 1 <= N <= 100,000

1 <= D <= 100,000

1 <= X <= 100,000

1 <= A[i] <= X

例如。

X = 7, D = 3

A = {1,3,1,4,2,5}

那么答案是 3。因为在第 3 秒时方 block 出现在位置 4 并且有可能达到 X=7。在那之前的任何一秒都不可能。

我知道这是一个措辞过多的问题,但如果我不能很好地沟通,我绝对可以解决任何问题。

要注意的是,预期时间复杂度为 O(N),您可以使用额外空间 O(X)。

我找到了一个 O(n * log n * log n) 的解决方案。即二分查找 second 得到 first [1..mid] 元素,按位置排序并验证解决方案。它似乎通过了测试用例,但它不是线性的。

我努力尝试但找不到任何 O(N) 解决方案。你能帮我么?

最佳答案

线性是指瓷砖数量的线性,对吧?

如果是这样,此解决方案(在 Java 中)仅迭代切片数组一次。

在每次迭代中,它还需要迭代 D 和 X 次,但它与瓦片数组的大小成线性关系。

如果它听起来与您正在寻找的相似,请告诉我。

注意:为简化起见,我假设位置“0”处的图 block 在第二个数字“0”时可用,因此有效地将第二个“0”视为您所站的图 block 出现的时间,然后其他图 block 出现在第 1、2 秒等处。

    public class TestTiles {

        public static int calculateSecond(Integer x, Integer d, int[] tiles) {
            // start by making all positions unreachable (false)
            boolean[] posReachable = new boolean[x+1];
            // iterate each second only once
            for (int second = 0; second < tiles.length; second++) {
                int tile = tiles[second];  // this tile is available now
                // so mark all positions from "tile" to "tile + d" reachable
                for (int pos = tile; (pos <= tile + d) && pos <= x; pos++) {
                    posReachable[pos] = true;
                }
                // are all positions reachable now? if so, this is the second to return
                boolean reachable = true;
                for (int pos = 0; pos <= x; pos++) {
                    reachable &= posReachable[pos];
                }
                if (reachable) return second;
            }
            // we can't reach the position
            return -1;
        }

        public static void main(String[] args) {
            System.out.println(calculateSecond(7, 3, new int[]{0,1,3,1,4,2,5}));
            System.out.println(calculateSecond(20, 3, new int[]{0,1,3,1,4,2,5}));
            System.out.println(calculateSecond(2, 3, new int[]{0,1,3,1,4,2,5}));
            System.out.println(calculateSecond(4, 3, new int[]{0,1,3,1,4,2,5}));
            System.out.println(calculateSecond(15, 3, new int[]{0,12,3,9,6}));
        }

    }

关于algorithm - 线性时间解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32663336/

相关文章:

algorithm - 对于给定的 n,如何从 1..n 中取数字的异或? (例如 1^2^3^...^n)?

algorithm - 近似最近邻时间复杂度

java - 使用递归统计嵌套列表中奇数长度或偶数长度的列表数量

language-agnostic - 与语言无关的基本编程问题

language-agnostic - 这个随机双生成器能工作吗?

python - 计算彼此之间具有最小和最大差异的唯一正整数的组合数?

language-agnostic - 当涉及到您的长期项目时,您如何保持以用户为导向?

unit-testing - 你会把这个(来自书 "Code Complete")称为单元测试、集成测试或其他什么吗?

language-agnostic - 自修改代码?

algorithm - 有没有办法避免不必要的递归?