Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 用于反转log(n)中的子阵列的数据结构_Algorithm_Data Structures_Binary Tree_Binary Search Tree - Fatal编程技术网

Algorithm 用于反转log(n)中的子阵列的数据结构

Algorithm 用于反转log(n)中的子阵列的数据结构,algorithm,data-structures,binary-tree,binary-search-tree,Algorithm,Data Structures,Binary Tree,Binary Search Tree,构建具有以下功能的数据结构: set(arr,n)-使用长度为n的数组arr初始化结构。时间O(n) fetch(i)-fetcharr[i]。时间O(log(n)) invert(k,j)-(当0以下是我们如何设计这种数据结构的方法。 事实上,使用平衡二叉搜索树是一个好主意 首先,让我们成对存储数组元素(索引,值)。 自然地,元素是按索引排序的,因此树的顺序遍历将按其原始顺序生成数组 现在,如果我们保持一个平衡的二叉搜索树,并将子树的大小存储在每个节点中,我们就可以在O(logn)中执行fet

构建具有以下功能的数据结构:

set(arr,n)
-使用长度为
n
的数组
arr
初始化结构。时间
O(n)

fetch(i)
-fetch
arr[i]
。时间
O(log(n))


invert(k,j)
-(当
0以下是我们如何设计这种数据结构的方法。
事实上,使用平衡二叉搜索树是一个好主意

首先,让我们成对存储数组元素
(索引,值)
。 自然地,元素是按索引排序的,因此树的顺序遍历将按其原始顺序生成数组

现在,如果我们保持一个平衡的二叉搜索树,并将子树的大小存储在每个节点中,我们就可以在
O(logn)
中执行fetch

接下来,让我们假设我们存储索引。 相反,我们仍然像对待
(索引,值)
对那样排列元素,但只存储值。
索引
现在隐式存储,可以按如下方式计算。 从根节点开始,向下到目标节点。 每当我们移动到左子树时,
索引
不会改变。 移动到右子树时,将左子树的大小加上一(当前顶点的大小)添加到
索引中

此时我们得到的是一个存储在平衡二叉搜索树中的定长数组。它需要
O(logn)
来访问(读或写)任何元素,而不是普通定长数组的
O(1)
,因此现在是时候从所有麻烦中获得一些好处了

下一步是设计一种方法,
O(logn)
中,根据左侧部分所需的大小,将数组拆分为左侧部分和右侧部分,并通过串联合并两个数组。 这一步引入了对我们选择的平衡二叉搜索树的依赖性。 是显而易见的候选者,因为它构建在拆分合并原语之上,所以这种改进是免费的。 也许在
O(logn)
中拆分a或a也是可能的(尽管我承认我自己并没有试图弄清楚细节)

目前,该结构已经比数组更强大:它允许在
O(logn)
中拆分和串联“数组”,尽管元素访问速度也和
O(logn)
一样慢。 请注意,如果此时仍显式存储
索引
,这将是不可能的,因为索引将在拆分合并操作的右侧部分断开

最后,是时候引入反转操作了。 让我们在每个节点中存储一个标志,以指示是否必须反转该节点的整个子树。 此标志将延迟传播:无论何时访问节点,在执行任何操作之前,请检查标志是否为
true
。 如果是这种情况,请交换左右子树,在两个子树的根节点中切换(
true-false
)标志,并将当前节点中的标志设置为
false

现在,当我们要反转子阵列时:

  • 通过两次拆分操作将阵列拆分为三部分(子阵列之前、子阵列本身以及子阵列之后)
  • 切换(
    true-false
    )中间(子阵列)部分根中的标志
  • 然后通过两个合并操作将三个部分按原始顺序合并