有序结构:SortedContainers

有序容器(List/Set/Dict)

Python中的SortedContainerPython中的SortedContainers类似于Java中的Treemap/Treeset,帮你打理好了O(logn)的写查删。

  • SortedSet:有序集合

  • SortedDict:有序字典

  • SortedList:可以看成允许重复元素的OrderedSet。

SortedDict和Ordered比较:

OrderedDict的键按照插入的先后次序排序,SortedDict的键按照它们的自然大小排序。比如说分别插入m[3]=0, m[2]=1, m[1]=1之后,结果分别为:

  • OrderedDict {3: 0, 2: 1, 1: 1},先来后到

  • SortedDict {1: 1, 2: 1, 3: 0},谁小谁先

注意和OrderedDict不一样的,SortedDict和其他SortedContainers一样,是有序数据结构,所以内部不是用哈希表来实现的,而是用平衡搜索树来实现的。

如果不能用类似的库,要么就要手撸平衡二叉树,要么就只能用List结合bisect来进行写查删。不过记住在List中很多操作受到插入和删除的机能,只能做到O(n)的时间复杂度:比如bisect.insort(List, x)list.remove(x)

二叉树简单实现(不含自平衡)

这里我们跳过自平衡。假设自平衡已经实现了(比如用红黑树),那么主要功能和时间复杂度是:

  • insert(val):O(logN)插入一个元素 实现:从根开始根据val的大小遍历,并在第一个空位新建一个节点

  • delete(val):O(logN)删除一个元素 [LC 450] 实现:从根开始根据val的大小遍历。三种情况:

    • 不存在,则返回

    • 存在,没有左儿子或者右儿子,用左儿子或右儿子或None代替自己。

    • 存在,有左儿子和右儿子,用右儿子代替自己。同时把左儿子插到右儿子的最小节点(leftmost node)的左边。

  • findMin():O(logN)找到最小值 实现:返回最左边的节点值

  • findMax():O(logN)找到最大值 实现:返回最右边的节点值

参考代码(维护一个长度为k的有序数组):

除了用前缀和把二维区域和转化成一维数组,这道题的本质是在一位数组中求连续和<=k的最大值。用一位数组s[i]表示前缀和之后,问题就是:

max(sjsi), given sjsiksmallest si>=sjkmax({s_j-s_i}) \text{, given } s_j-s_i\le k \\ ⇒ \text{smallest } s_i >=sj-k

用有序集合来存储之前看到的s[i],就能用O(nlogn)的算法枚举s[j]二分查找s[i]

参考代码:

延伸阅读:Urinal protocol vulnerability

参考代码:

参考代码:

Last updated

Was this helpful?