给定一个双调数组和数组中的元素 x,在 2log(n) 时间内找到 x 的索引

2024-01-31

首先,这个问题的双调数组被定义为对于某些索引K在长度数组中N where 0 < K < N - 10到K是单调递增的整数序列,K到N-1是单调递减的整数序列。

例子:[1, 3, 4, 6, 9, 14, 11, 7, 2, -4, -9]。它从 1 单调增加到 14,然后从 14 减少到 -9。

这个问题的前提是解决它3log(n),这要容易得多。一种改变的二分搜索查找最大值的索引,然后分别进行 0 到 K 和 K + 1 到 N - 1 的两次二分搜索。

我认为解决方案是2log(n)要求您在不找到最大值索引的情况下解决问题。我考虑过重叠二进制搜索,但除此之外,我不确定如何继续前进。


其他答案中提出的算法(this https://stackoverflow.com/a/21697488/509868 and this https://stackoverflow.com/a/19373178/509868) 不幸的是不正确,它们不是 O(logN) !

递归公式 f(L) = f(L/2) + log(L/2) + c 不会导致 f(L) = O(log(N)) 但会导致 f(L) =O((log(N))^2) !

事实上,假设 k = log(L),则 log(2^(k-1)) + log(2^(k-2)) + ... + log(2^1) = log(2)*( k-1 + k-2 + ... + 1) = O(k^2)。因此,log(L/2) + log(L/4) + ... + log(2) = O((log(L)^2))。

在时间 ~ 2log(N) 内解决问题的正确方法是按如下方式进行(假设数组首先按升序排列,然后按降序排列):

  1. 取数组的中间部分
  2. 将中间元素与其相邻元素之一进行比较,看看最大值是在右侧还是左侧
  3. 将中间元素与所需值进行比较
  4. 如果中间元素小于所需值并且最大值在左侧,则对左子数组进行双调搜索(我们确定该值不在右子数组中)
  5. 如果中间元素小于所需值并且最大值在右侧,则在右侧子数组上进行双调搜索
  6. 如果中间元素大于所需值,则对右子数组进行降序二分查找,对左子数组进行升序二分查找。

在最后一种情况下,对可能是双调的子数组进行二分搜索可能会令人惊讶,但它实际上有效,因为我们知道顺序不正确的元素都大于所需的值。例如,对数组 [2, 4, 5, 6, 9, 8, 7] 中的值 5 进行升序二分搜索将会起作用,因为 7 和 8 大于所需值 5。

这是双音时间搜索的完整工作实现(用 C++ 实现)~2logN:

#include <iostream>

using namespace std;

const int N = 10;

void descending_binary_search(int (&array) [N], int left, int right, int value)
{
  // cout << "descending_binary_search: " << left << " " << right << endl;

  // empty interval
  if (left == right) {
    return;
  }

  // look at the middle of the interval
  int mid = (right+left)/2;
  if (array[mid] == value) {
    cout << "value found" << endl;
    return;
  }

  // interval is not splittable
  if (left+1 == right) {
    return;
  }

  if (value < array[mid]) {
    descending_binary_search(array, mid+1, right, value);
  }
  else {
    descending_binary_search(array, left, mid, value);
  }
}

void ascending_binary_search(int (&array) [N], int left, int right, int value)
{
  // cout << "ascending_binary_search: " << left << " " << right << endl;

  // empty interval
  if (left == right) {
    return;
  }

  // look at the middle of the interval
  int mid = (right+left)/2;
  if (array[mid] == value) {
    cout << "value found" << endl;
    return;
  }

  // interval is not splittable
  if (left+1 == right) {
    return;
  }

  if (value > array[mid]) {
    ascending_binary_search(array, mid+1, right, value);
  }
  else {
    ascending_binary_search(array, left, mid, value);
  }
}

void bitonic_search(int (&array) [N], int left, int right, int value)
{
  // cout << "bitonic_search: " << left << " " << right << endl;

  // empty interval
  if (left == right) {
    return;
  }

  int mid = (right+left)/2;
  if (array[mid] == value) {
    cout << "value found" << endl;
    return;
  }

  // not splittable interval
  if (left+1 == right) {
    return;
  }

  if(array[mid] > array[mid-1]) {
    if (value > array[mid]) {
      return bitonic_search(array, mid+1, right, value);
    }
    else {
      ascending_binary_search(array, left, mid, value);
      descending_binary_search(array, mid+1, right, value);
    }
  }

  else {
    if (value > array[mid]) {
      bitonic_search(array, left, mid, value);
    }
    else {
      ascending_binary_search(array, left, mid, value);
      descending_binary_search(array, mid+1, right, value);
    }
  }
}

int main()
{
  int array[N] = {2, 3, 5, 7, 9, 11, 13, 4, 1, 0};
  int value = 4;

  int left = 0;
  int right = N;

  // print "value found" is the desired value is in the bitonic array
  bitonic_search(array, left, right, value);

  return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

给定一个双调数组和数组中的元素 x,在 2log(n) 时间内找到 x 的索引 的相关文章

  • 分而治之算法找到两个有序元素之间的最大差异

    给定一个整数数组 arr 找出任意两个元素之间的差异 使得较大的元素出现在 arr 中较小的数字之后 Max Difference Max arr x arr y x gt y 例子 如果数组是 2 3 10 6 4 8 1 7 那么返回值
  • 在任意时间范围内找到最佳日/月/年间隔的算法?

    如果您有时间表 请说 March 19 2009 July 15 2011 是否有一种算法可以将该时间范围分解为 March 19 2009 March 31 2009 complete days April 1 2009 December
  • 如何将多边形放入另一个多边形内[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有两个多边形 如下图所示 左边是 粗多边形 右边是 最终多边形 现在 我正在寻找算法来将 最终多边形 拟合到 粗糙多边形 内 并具有
  • 什么是“朴素”算法,什么是“封闭式”解决方案?

    我有一些关于描述算法时使用的术语语义的问题 首先 朴素 算法是什么意思 这与给定问题的其他解决方案有何不同 解决方案还可以采取哪些其他形式 其次 我听到很多人提到 封闭式 解决方案 我也不知道这意味着什么 但在尝试解决递归关系时经常会出现
  • 如何在 C# 中以编程方式创建柔和的颜色?

    根据所需的颜色数量均匀分布地生成它们 如果指定的计数为 8 则看起来像这样 List
  • heapq.nlargest 的时间复杂度是多少?

    我在看演讲者说 获得t列表中最大的元素n元素可以在O t n 这怎么可能 我的理解是创建堆将是O n 但是复杂度是多少nlargest本身就是O n t or O t 实际的算法是什么 在这种情况下 说话者是错误的 实际成本是O n log
  • 这个函数(for循环)空间复杂度是O(1)还是O(n)?

    public void check 10 for string i list Integer a hashtable get i if a gt 10 hashtable remove i 这是 O 1 还是 O n 我猜测 O n 但不是
  • 为什么这个算法的Big-O复杂度是O(n^2)?

    我知道这个算法的大O复杂度是O n 2 但我不明白为什么 int sum 0 int i 1 j n n while i lt j sum 即使我们设定了j n n一开始 我们在每次迭代期间递增 i 并递减 j 因此最终的迭代次数不应该比n
  • 优化计算中使用的 # 个线程的算法

    我正在执行一个操作 我们将其称为CalculateSomeData CalculateSomeData 在连续的 代 中运行 编号为 1 x 整个运行中的代数由CalculateSomeData 的输入参数固定 并且是先验已知的 完成一次生
  • 使用什么算法来确定使系统达到“零”状态所需的最小操作数?

    这是一种更通用的问题 不是特定于语言的 有关要使用的想法和算法的更多信息 系统如下 它登记朋友群体之间的小额贷款 Alice and Bill要去吃午饭 比尔的卡坏了 所以爱丽丝支付了他的餐费 10 美元 第二天Bill and Charl
  • 在一个区域中拟合二维多边形的算法?

    这有标准吗 算法名称 说 我有 10 个不同大小的多边形 我有一个特定大小的区域 我想知道如何填充该区域中的最多多边形 以及它们是如何拟合的 笔记 多边形可以根据限制集进行旋转 一个可能的名称是包装问题 http en wikipedia
  • 颜色变换器功能上的堆栈溢出错误

    我有两种颜色 红色 和 鲑鱼色 我需要动态创建面板以及面板背景颜色 这些颜色必须介于两种颜色之间 红色 public Color x y protected void Page Load object sender EventArgs e
  • 你能用 C# 编写一个同样优雅的排列函数吗?

    我非常喜欢这个 6 行解决方案 并尝试在 C 中复制它 基本上 它会排列数组的元素 def permute xs pre if len xs 0 yield pre for i x in enumerate xs for y in perm
  • 分离并重新附加“tools:rstudio”

    又名玩火 以下不起作用 rstd obj lt as environment tools rstudio detach tools rstudio attach rstd obj name tools rstudio 好吧 它似乎有效 但随
  • 整个应用程序中的全局“搜索功能”

    在我的整个应用程序中 我希望搜索按钮执行单独的操作Activity 即 当我按下搜索按钮时 从应用程序中的任何位置调用一个单独的活动 有什么方法可以代替定义onSearchRequested 在每项活动中 我只是在一个地方配置它 例如Man
  • 从二叉堆中查找第 k 个最小元素的 O(klogk) 时间算法

    我们有一个 n 节点二叉堆 其中包含n不同的项目 根部的最小项目 为一个k lt n 发现O klogk 时间算法选择kth堆中的最小元素 O klogn 很明显 但无法找出O klogk 一 也许我们可以使用第二个堆 但不确定 好吧 你的
  • 在 Python 中从 Excel 复制 YEARFRAC() 函数

    因此 我使用 python 来自动执行一些必须在 Excel 中执行的重复任务 我需要做的计算之一需要使用yearfrac 这在Python中被复制了吗 I found this https lists oasis open org arc
  • 如何以最低的价格优化购物车?

    我有一个我想买的物品清单 这些商品由不同的商店提供 价格也不同 商店有单独的送货费用 我正在寻找一种最佳的购物策略 以及支持它的java库 以最低的总价购买所有商品 Example 商品 1 在 Shop1 的售价为 100 美元 在 Sh
  • 确定一组日期的事件重复模式

    我正在寻找一种模式 算法或库 它将采用一组日期并在退出时返回重复的描述 即集合 11 01 2010 11 08 2010 11 15 2010 11 22 2010 11 29 2010 会产生类似 十一月的每个星期一 的结果 有没有人以
  • 从列表中选择项目以求和

    我有一个包含数值的项目列表 我需要使用这些项目求和 我需要你的帮助来构建这样的算法 下面是一个用 C 编写的示例 描述了我的问题 int sum 21 List

随机推荐