【问题标题】:max. distance of a number greater than a given number in array最大限度。数组中大于给定数字的数字的距离
【发布时间】:2020-02-01 06:39:49
【问题描述】:

我正在处理一个面试问题..并且想出了需要找到的逻辑:

为大于a[i](与j < i)的元素a[j] 查找索引j,使得(i-j) 最大。我想为数组中的每个索引i 找到这个j,在O(n)O(n log n) 时间与O(n) 额外空间。`

到目前为止我做了什么:

1) O(n^2) 使用简单的for loops

2) 构建平衡的 B.S.T.当我们从左到右扫描元素时,对于i'th 元素,找到大于它的元素索引。但我意识到它可以很容易地是 O(n) 用于单个元素,因此 O(n^2) 用于整个数组。

我想知道是否可以在O(n)O(n log n) 中进行。如果是,请给出一些提示。

编辑:我想我无法解释我的问题。让我清楚地解释一下: 我想要arr[j]arr[i] 的左侧,这样(i-j) 是最大的可能,arr[j]>arr[i] 并为所有索引找到它,即for(i=0 to n-1).

编辑 2:示例 - {2,3,1,6,0}
for 2 , ans=-1
for 3 , ans=-1
for 1 , ans=2 (i-j)==(2-0)
for 6 , ans=-1
@987654348 @ (i-j)==(4-0)

【问题讨论】:

  • 能举个输入输出数据的例子吗?
  • 我不太明白这个问题,是否要为数组中的每个元素找到比当前元素大的最左边的元素?
  • 我不确定我是否理解正确,但不是要在数组中找到minmax 然后进行比较吗?即:[1. Find min]; [2. Find max]; [3. For given i-th element compare which is farther - min or max]. 就是这样。根据线性顺序的定义,没有什么比这更远了。
  • arr[i]
  • @all i-j should be maximum not arr[i]-arr[j]

标签: arrays algorithm


【解决方案1】:

创建一个最大值的辅助数组,设为maxs,它将基本上包含数组上直到当前索引的最大值。

正式:maxs[i] = max { arr[0], arr[1], ..., arr[i] }

请注意,这是可以在O(n) 中完成的预处理步骤

现在对于每个元素 i,您正在寻找 maxs 中大于 arr[i] 的第一个元素。这可以使用二分搜索来完成,每个操作是 O(logn)

总共为您提供O(nlogn) 时间和O(n) 额外空间。

【讨论】:

  • 您的解决方案有两点不清楚:1. 您如何在 O(logn) 时间内对最大数组应用二进制搜索?它可能看起来像 [10, 10, 18, 24, 24, 24, 24, 24, 24] 2.您的算法不完整 - 在寻找第一个最大元素后,您需要存储 i - j 的值(沿与索引)某处(另一个数组)并在最后找到该数组的最大值(或者沿着最大数组执行此操作)
  • @Bond 二进制搜索非常适合这样的数组,它已排序,并且您可以保证在O(logn) 时间内找到最接近的相等/更高的元素。重复的条目不会使数组“未排序”,因此二进制搜索的条件仍然适用。从二进制搜索中检索到的值是每个i 的请求元素。您也可以通过查找具有此值的第一个条目来获取相关索引,但据我了解,它不是必需的,并且无论如何不会改变时间复杂度。
  • @amit 你错了,因为你只找到 max{arr[0],......arr[i-1]} 但我们必须找到 max(i-j)
  • @anon 因为它是一个最大值数组,所以可以保证我们找到的元素是第一个大于 arr[i] 的元素 - 这意味着它也最大化了 i-j,因为没有元素比 j 小的元素比 arr[i] 高。
  • @amit 我明白你想解释什么。我无法分析二进制搜索。你的意思是这样的吗?我假设在 maxs[i] = 最大元素的索引中,不是最大元素,目标是 arr[i]。 bin_srch(start,end) { if(endtarget) return start if(arr[mid]>target && mid- 1>0 && arr[mid-1]>target) bin_srch(start,mid-1) else if(arr[mid]>target) return mid else return bin_srch(mid+1,end) }
【解决方案2】:

对于尚未找到解决方案的数组索引,您可以在 O(n) 时间内完成此操作。它可以实现为最多 n 个元素的数组。

从左到右遍历输入数组,从最后一个元素开始:

  • 从堆栈中弹出数组元素小于当前元素的所有索引。将当前元素的索引标记为您弹出的每个索引的解决方案。
  • 将当前元素的索引压入栈中。

不变量:栈中索引对应的数组项总是升序排列,最少的项在最上。

当你到达输入的开头时,用 -1 标记任何仍然留在堆栈中的项目;对他们来说没有答案。

每个数组索引只被压入堆栈一次,最多弹出一次,因此该算法运行时间为 O(n)。

Python 中的一个例子:

def solution(arr):
    stack = []
    out = [-1]*len(arr)
    for i in xrange(len(arr)-1, -1, -1):
        while len(stack) > 0 and arr[stack[-1]] < arr[i]:
            out[stack.pop()] = i
        stack.append(i);
    return out

注意输入[2, 4, 1, 5, 3]的正确答案是[-1, -1, 1, -1, 3]:对于固定的i,j最大时j-i的差值最大,所以你要寻找最左的索引j,这最小化距离。 (当 j

【讨论】:

  • 哦,是的。刚刚意识到“最大j-i”不是最大距离,而是最小距离。这需要用 OP 来澄清,不管他是真的想要最大的距离还是真正最大的 j-i
  • 对不起,这是我编辑帖子时的错误。真正的问题是“最大的 i-j”。真的很抱歉给您带来麻烦。
【解决方案3】:

我能想到的最快的解决方案是分配第二个数组并从左到右扫描数组。当您遍历数组并扫描每个元素时,如果 arr[index] 大于第二个数组的最右边的元素,则将该元素的索引附加到第二个数组。这是每个追加的 O(1) 时间,最多 n 个追加,所以 O(n)。

最后,一旦你的阵列完成,再通过你的阵列。对于每个元素,使用二分搜索扫描第二个数组(这是可能的,因为它是隐式排序的)并找到数组中最左边(最早插入)的索引 j,使得 arr[j] > arr[i]。

为此,您必须对二分搜索进行修改。如果你找到一个索引 j 使得 arr[j] > arr[i],你仍然需要检查左边是否有任何索引 k 使得 arr[k] > arr[i]。您必须这样做,直到找到最左边的索引。

认为这是每个二进制搜索的 O(log n),您必须搜索 n 个元素。所以总时间复杂度将接近 O(n log n),但我不确定这一点。对此答案的任何 cmets/建议将不胜感激。

【讨论】:

  • 您将arr[index] 的值与第二个数组中最右边的元素进行比较,其中包含一个索引。所以你是在比较一个元素和一个索引?还是您的意思是与第二个数组中最右边的元素指向的元素进行比较?
【解决方案4】:

这是我在 C++ 中的解决方案
我们保持不断增加的数组。将当前元素与数组后面的元素进行比较。 如果它大于或等于到目前为止的最大元素,则将此元素附加到数组中,返回-1,它的左边没有更小的元素。

如果没有,我们使用二分查找,找到索引并返回差值。 (我们仍然需要将 vec.back() 附加到数组中,因为我们无法更改索引)

int findIdx(vector<int>& vec, int target){
    auto it = upper_bound(vec.begin(), vec.end(), target);
    int idx = int(it-vec.begin());
    return idx;
}

vector<int> farestBig(vector<int>& arr){
    vector<int> ans{-1};
    vector<int> vec{arr[0]};
    int n = (int)arr.size();
    for(int i=1; i<n; i++){
        if(arr[i] >= vec.back()){
            ans.push_back(-1);
            vec.push_back(arr[i]);
        }
        else{
            int idx = findIdx(vec, arr[i]);
            ans.push_back(i-idx);
            vec.push_back(vec.back());
        }
    }
    return ans;
}

【讨论】:

    猜你喜欢
    • 2010-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-17
    • 1970-01-01
    相关资源
    最近更新 更多