我应该为范围最小查询使用什么使用 O(n) 存储和 O(log n) 查询时间的数据结构?

2024-02-27

我被算法课的以下作业问题难住了:

Suppose that we are given a sequence of n values x1, x2 ... xn, and seek to quickly answer repeated queries of the form: given i and j, find the smallest value in xi... xj

设计一个使用 O(n) 的数据结构 空间并在 O(log n) 中回答查询 时间。

首先,我不确定是否sequence指的是排序集或未排序集 - 但因为它没有说明否则我会假设sequence意思是未排序。

所以,我意识到,如果我们谈论的是 O(log N) 查找时间,这显然必须涉及二叉树。所以基本上,我想,你有一套S,然后将每个元素插入S成二叉树。问题是,这个问题基本上希望我想出一种方法来回答查询,在该方法中我得到了一系列索引unsorted设置 - 然后在 O(log N) 时间内确定该范围内的最低值。这怎么可能?即使集合中的每个数字都插入到树中,我能做的最好的事情就是在 O(log N) 时间内查找任何特定数字。这不允许我找到未排序的数字范围中的最低值S.

有什么建议么?


如果集合已排序,则不需要树。 [i,j] 范围内的最小元素的索引为 i。

因此,假设序列的元素按照索引的顺序存储在树的叶子上。您可以存储任何附加信息吗(ahem,也许是每个内部节点的某种最小值和最大值)以方便您的查询?

如果是这样,那么如果树是平衡的,并且如果您可以通过仅查看从根到 {i,j} 处的两个元素的两条路径来回答您的查询,那么您将实现 O(log N) 查找成本。由于具有 N 个叶子的平衡二叉树总共包含 (2N-1) 个节点,因此您还将满足 O(N) 存储限制。


更多细节:考虑计算 [i,j] 范围内的最小值。

在树的每个内部节点 A 处,保留其下方所有叶子的最小值。这可以在树首次构建时自下而上计算。

现在从叶 i 开始。沿着树向上走,将 i 处的值或已知位于 i 右侧和 j 左侧的任何值保留为候选最小值。停止 i 和 j 共同祖先下方的一个节点。

从叶 j 处重新开始。沿着树向上走,再次将 j 处的值或已知位于 j 左侧和 i 右侧的任何值保留为候选最小值。

[i,j] 的最小值就是您计算的两个值中的最小值。计算最大值是类似的。总存储需求是每个内部节点 2 个值加上每个内部节点两个指针加上每个叶子一个值,对于完整的树来说是 N + 4(N-1)。

你走过的路up从叶子 i 开始的树,与您要走的路径相同down如果您正在寻找叶子 i,则为树。


用于搜索的 C# 代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RangeSearch
{
    public class RangeSearch
    {
        int[] tree;
        int N;

        int LeafLocation(int leafNumber) { return leafNumber + N - 1; }
        int LeafValue(int leafNumber) { return tree[ LeafLocation(leafNumber)]; }
        int LeftChild(int x) { return 2*x + 1; }
        int RightChild(int x) { return 2*x + 2; }
        int Parent(int x) { return (x-1)/2; }
        bool IsPowerOf2(int x) { while (x > 0) { if (x == 1) return true; if ((x & 1) == 1 ) return false; x = x >> 1; } return false; }
        bool IsAncestorOf( int x, int y ) { if( x>y ) return false;  return x==y || IsAncestorOf(LeftChild(x), y) || IsAncestorOf(RightChild(x),y); } // note: violating time bound for legibility, can fix by storing min/max descendant index at each node

        public RangeSearch(params int[] vals)
        {
            if (!IsPowerOf2(vals.Length))
                throw new ArgumentException("this implementation restricted to N being power of 2");
            N = vals.Length;
            tree = new int[2 * N - 1];
            // the right half of the array contains the leaves
            vals.CopyTo(tree, N - 1);
            // the left half of the array contains the interior nodes, each of which holds the minimum of all its children
            for (int i = N - 2; i >= 0; i--)
                tree[i] = Math.Min(tree[LeftChild(i)], tree[RightChild(i)]);           
        }

        public int FindMin(int a, int b)
        {
            if( a>b )
                throw new ArgumentException( "FindMin expects a range [a,b] with a<=b" );
            int x = Walk( a, true, b);
            int y = Walk( b, false, a);
            return Math.Min(x, y);
        }

        int Walk( int leafNumber, bool leftSide, int otherLeafNumber )
        {
            int minSoFar =  LeafValue(leafNumber);
            int leafLocation = LeafLocation(leafNumber);
            int otherLeafLocation = LeafLocation(otherLeafNumber);
            int parent = Parent(leafLocation);
            bool cameFromLeft = (leafLocation == LeftChild(parent));
            return Walk2(minSoFar, parent, cameFromLeft, leftSide, otherLeafLocation);
        }
        int Walk2(int minSoFar, int node, bool cameFromLeft, bool leftSide, int otherLeafLocation)
        {
            if (IsAncestorOf(node, otherLeafLocation))
                return minSoFar;
            if (leftSide)
                minSoFar = !cameFromLeft ? minSoFar : Math.Min(minSoFar, tree[RightChild(node)]);
            else
                minSoFar = cameFromLeft ? minSoFar : Math.Min(minSoFar, tree[LeftChild(node)]);
            return Walk2(minSoFar, Parent(node), node == LeftChild(Parent(node)), leftSide, otherLeafLocation);
        }
    }
}

用于测试它的 C# 代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RangeSearch
{
    class Program
    {
        static void Main(string[] args)
        {
            RangeSearch rngA = new RangeSearch(9, 3, 7, 1);
            System.Diagnostics.Trace.Assert(3 == rngA.FindMin(0, 2) );
            System.Diagnostics.Trace.Assert(1 == rngA.FindMin(0, 3));
            System.Diagnostics.Trace.Assert(1 == rngA.FindMin(1, 3));

            RangeSearch rngB = new RangeSearch(1, 7, 3, 9);
            System.Diagnostics.Trace.Assert(3 == rngB.FindMin(1, 3));
            System.Diagnostics.Trace.Assert(1 == rngB.FindMin(0, 3));
            System.Diagnostics.Trace.Assert(1 == rngB.FindMin(0, 2));

            RangeSearch rngC = new RangeSearch(17, 21, 77, 70, 58, 79, 79, 89);
            System.Diagnostics.Trace.Assert(21 == rngC.FindMin(1, 7));

            RangeSearch rngD = new RangeSearch(94, 78, 88, 72, 95, 97, 89, 83);
            System.Diagnostics.Trace.Assert(72 == rngD.FindMin(1, 6));

            RangeSearch rngE = new RangeSearch(0, 66, 6, 43, 34, 34, 63, 49);
            System.Diagnostics.Trace.Assert(34 == rngE.FindMin(3, 4));

            Random rnd = new Random();
            for (int i = 0; i < 1000000; i++)
            {
                int[] tmp = new int[64];
                for (int j = 0; j < tmp.Length; j++)
                    tmp[j] = rnd.Next(0, 100);
                int a = rnd.Next(0, tmp.Length);
                int b = rnd.Next(a, tmp.Length);
                RangeSearch rng = new RangeSearch(tmp);
                System.Diagnostics.Trace.Assert(Min(tmp, a, b) == rng.FindMin(a, b));
            }
        }

        static int Min(int[] ar, int a, int b)
        {
            int x = ar[a];
            for (int i = a + 1; i <= b; i++)
                x = Math.Min(x, ar[i]);
            return x;
        }

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

我应该为范围最小查询使用什么使用 O(n) 存储和 O(log n) 查询时间的数据结构? 的相关文章

  • 字符串 c 的二叉树

    我正在尝试实现一个能够在 c 中保存字符串的二叉树 在让代码适用于整数之后 我尝试稍微修改它以处理字符数组 现在我似乎完全破解了代码 但不知道如何破解 任何帮助表示赞赏 include
  • 当给定块大小时反转单链表

    有一个单连接链表 并给出了块大小 例如 如果我的链表是1 gt 2 gt 3 gt 4 gt 5 gt 6 gt 7 gt 8 NULL我的块大小是4然后反转第一个4元素 然后是第二个 4 个元素 问题的输出应该是4 gt 3 gt 2 g
  • 重写修改后的 goto 语义的算法

    我有一大堆使用旧的自行设计的脚本语言编写的遗留代码 我们将它们编译 翻译成 javascript 该语言有条件跳转 跳转到标签 与普通 goto 语句的区别在于 不可能向后跳转 该语言中没有嵌套的 if 语句或循环 由于 javascrip
  • 我应该对算法使用递归还是记忆化?

    如果我可以选择使用递归或记忆来解决问题 我应该使用哪一个 换句话说 如果它们都是可行的解决方案 因为它们提供了正确的输出并且可以在我正在使用的代码中合理地表达 那么我什么时候会使用其中一个而不是另一个 它们并不相互排斥 您可以同时使用它们
  • 求先递增后递减列表的最大值和最小值

    我尝试用谷歌搜索这个问题 但没有取得太大成功 我确信这个问题或类似问题有一个技术名称 但我似乎找不到答案 给定一个列表L整数 即严格递增 然后严格递减 找到该列表的最大值和最小值 例如 L可能 1 2 3 4 5 4 3 2 or 2 4
  • 在树结构的 Big-O 表示法中:为什么有些来源引用 O(logN),有些来源引用 O(h)?

    在研究遍历二叉搜索树的任何算法的复杂性时 我看到两种不同的方式来表达同一件事 版本 1 最坏情况下的遍历算法对树的每个高度进行一次比较 因此复杂度是O h 版本 2 最坏情况下的遍历算法对树的每个高度进行一次比较 因此复杂度是O logN
  • 颜色逻辑算法

    我们正在构建一个体育应用程序 并希望将团队颜色融入到应用程序的各个部分 现在 每个团队都可以使用几种不同的颜色来表示 我想做的是执行检查以验证两个团队颜色是否在彼此一定的范围内 这样我就不会显示两个相似的颜色 因此 如果团队 1 的主要团队
  • 使用什么算法来确定使系统达到“零”状态所需的最小操作数?

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

    这有标准吗 算法名称 说 我有 10 个不同大小的多边形 我有一个特定大小的区域 我想知道如何填充该区域中的最多多边形 以及它们是如何拟合的 笔记 多边形可以根据限制集进行旋转 一个可能的名称是包装问题 http en wikipedia
  • 连接红黑树

    OCaml 标准库有一个很棒的Set使用非常有效的分而治之算法来计算的实现union两套 我相信它会从一组中获取整个子树 而不仅仅是单个元素 并将它们插入到另一组中 并在必要时重新平衡 我想知道这是否需要 OCaml 使用的 AVL 树中保
  • 面试题:三个数组,O(N*N)

    假设我们有three长度数组N其中包含任意数量的类型long 然后我们得到一个数字M 相同类型 我们的任务是选择三个数字A B and C每个数组中的一个 换句话说A should从第一个数组中选取 B从第二个开始和C从第三个 所以总和A
  • 用于查找最近邻居的空间划分算法如何工作?

    为了找到最近的邻居 空间分区 http en wikipedia org wiki Nearest neighbor search Space partitioning是算法之一 它是如何工作的 假设我有一组 2D 点 x 和 y 坐标 并
  • String.contains() 的时间复杂度

    String contains 的时间复杂度是多少 假设 n 是与另一个长度为 k 的字符串进行比较的字符串的长度 如果不知道您感兴趣的 String contains 的实际实现 就没有答案 或者你打算使用什么算法 一个完全幼稚的实现可能
  • 密文窃取算法 - 哪一种是正确的?

    网络上提出了两种算法 在这两种算法中 第一部分是相同的 1 Pad the last partial plaintext block with 0 2 Encrypt the whole padded plaintext using the
  • 实时战略战争游戏人工智能算法

    我正在设计一款实时策略战争游戏 其中 AI 将负责控制大型六边形地图上的大量单位 可能超过 1000 个 一个单位有许多行动点 可以用于移动 攻击敌方单位或各种特殊行动 例如建造新单位 例如 一辆拥有 5 个行动点的坦克可以花费 3 个行动
  • 高度并行化的Levenshtein距离算法

    实际上 我必须实现一个字符串比较 最后得到匹配百分比 不仅仅是布尔结果匹配 不匹配 为此 我找到了 Levenstein 距离算法 但现在的问题是性能 例如 我有 1k 个字符串需要相互比较 现在大约需要 10 分钟 对于每个算法 我已经并
  • 相当于字典的数据结构?

    我正在使用 JavaScript 工作 希望保留一份设置的公里 英里 小时近似值列表 我无法以编程方式进行转换 我正在使用需要某些值的外部 API 因此它确实必须是等效的字典 目前我正在使用一个对象 var KM MPH 10 16 12
  • 使用递归返回嵌套列表中第二小的数字

    我必须归还第二小的使用递归的 python 列表中的数字 以及no loops 我所做的是创建一个辅助函数 它返回列表中 最小 第二小的 值的元组 然后我只取tuple 1 in my second smallest func def s
  • 有向未加权图中的最长非循环路径

    什么算法可用于找到未加权有向无环图中的最长路径 动态规划 http en wikipedia org wiki Dynamic programming 它也被引用于最长路径问题 http en wikipedia org wiki Long
  • pandas DataFrame.join 的运行时间是多少(大“O”顺序)?

    这个问题更具概念性 理论性 与非常大的数据集的运行时间有关 所以我很抱歉没有一个最小的例子来展示 我有一堆来自两个不同传感器的数据帧 我需要最终将它们连接成两个very来自两个不同传感器的大数据帧 df snsr1 and df snsr2

随机推荐

  • 使用numpy.数字或替代数组上的binary_repr - Python

    使用以下代码我尝试将数字列表转换为二进制数但出现错误 import numpy as np lis np array 1 2 3 4 5 6 7 8 9 a np binary repr lis width 32 运行程序后的错误是 回溯
  • r 包插入符号-使用并行时打印迭代

    无论如何 我们可以在使用时打印迭代caret train并行功能 我知道有一个名为 verbose 的选项 但如果我使用多核 它似乎不会打印任何内容 我找到了解决方案 我们需要的只是通过 makeCluster 函数注册核心 library
  • C# 中的 System.Threading.Timer 似乎不起作用。每3秒运行速度非常快

    我有一个计时器对象 我希望它每分钟运行一次 具体来说 它应该运行一个OnCallBack方法并在 a 时变得不活动OnCallBack方法正在运行 一旦OnCallBack方法完成后 它 aOnCallBack 重新启动计时器 这是我现在所
  • 如何在cmake中使用调试符号构建依赖共享库?

    我的代码是这样组织的 cpp main cpp 从调用代码dataStructures and common CMakeLists txt topmostCMakeLists 文件 build common CMakeLists txt 应
  • Android Java - 创建 Cronjob

    我想要制作一个在后端运行的 Cronjob 并启动一个方法 30 分钟 如果函数返回 true 或其他 Cronjob 将创建一个状态栏通知 在 Android 中这可能吗 如果是的话 用哪个函数 非常感谢 安卓系统报警管理器 http d
  • 如何让 CreateProcess/CreateProcessW 在路径 > MAX_PATH 字符中执行进程

    我试图让 CreateProcess 或 CreateProcessW 执行名称 http msdn microsoft com en us library ms682425 aspx http msdn microsoft com en
  • 限制可排序的容器/父级

    好的 我又来了 和 RubaXa 一起玩Sortable http rubaxa github io Sortable 插件 希望他就在这附近 因为这个插件相当复杂 一些发现 我花了一些时间才完全理解这个机制 但我认为我是对的 Case 1
  • Windows 命令提示符中的别名

    我已经添加了notepad exe到我的环境变量中的路径 现在在命令提示符下 notepad exe filename txt打开filename txt 但我想做的只是np filename txt打开文件 我尝试使用DOSKEY np
  • intel avx2 中是否有 movemask 指令的逆指令?

    movemask 指令采用 m256i 并返回 int32 其中每个位 前 4 8 或所有 32 位 具体取决于输入向量元素类型 是相应向量元素的最高有效位 我想做相反的事情 取 32 其中只有 4 8 或 32 个最低有效位有意义 并获得
  • 冒泡排序有什么用? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何自定义App Designer人物的背景?

    我想附加徽标或更改应用程序设计器的整个背景uifigure 如何才能做到这一点 如果你想设置一个整个图的纯色背景色 那里存在有记录的方式 https www mathworks com help matlab ref uifigureapp
  • 验证在部分视图中不起作用

    我有一个索引页面 其中有两个部分视图 登录和注册 我正在使用数据模型验证 登录 cshtml model Project ViewModel UserModel div using Html BeginForm Login account
  • 从 Ada 访问 c 常量

    我有一个带有这样类型定义的头文件 ifndef SETSIZE define SETSIZE 32 endif typedef struct set unsigned array SETSIZE set t 要使用相应的 C 函数 我需要在
  • jquery 获取之前输入的文本

    我有以下 html div class active string div
  • 将大文件作为流发送到 process.getOutputStream

    我在 Windows 机器中使用 gzip 实用程序 我压缩了一个文件并作为 blob 存储在数据库中 当我想使用 gzip 实用程序解压缩此文件时 我将此字节流写入 process getOutputStream 但超过30KB后 就无法
  • Android 绘制点

    如何用画布绘制完整的圆或点 我使用画布和路径 绘画类 my code Override public boolean onTouchEvent MotionEvent event float eventX event getX float
  • 如何向谷歌图表中的图例添加工具提示

    使用最新版本的 Google Charts API 我有一个简单的条形图 我想在将鼠标悬停在图例中的元素上时显示一个工具提示 解释图例中的每个项目是什么 我仍然希望栏上的工具提示保持不变并显示其标签和值
  • 使用 GSM 调制解调器接收短信

    我读到 GSM 调制解调器每分钟最多只能接收 30 条短信 如果您需要收到更多 您会怎么做 还有其他技术吗 我认为您可能想要与列出的答案不同的东西构建短信服务器的最佳实践是什么 https stackoverflow com questio
  • 多态关联

    如果您具有多态belongs to关联 那么引用将添加所需的两列 create table products do t t references attachment polymorphic gt default gt Photo end
  • 我应该为范围最小查询使用什么使用 O(n) 存储和 O(log n) 查询时间的数据结构?

    我被算法课的以下作业问题难住了 Suppose that we are given a sequence of n values x1 x2 xn and seek to quickly answer repeated queries of