系统设计类题目汇总五

40 一道lc上的优化

40.1 lc230. 二叉搜索树中第K小的元素

给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 个最小元素(从 1 开始计数)。

原答案:

class Solution {
    public int kthSmallest(TreeNode root, int k) {
        this.k=k;
        getKthMin(root);
        return res;
        
    }
    int res=-1;
    int k;
    void getKthMin(TreeNode root){
        if(root==null||res!=-1)return;

        getKthMin(root.left);
        k--;

        if(k==0){
            res=root.val;
            return;
        }
        getKthMin(root.right);
        

    }
}

40.2 进阶:如果二叉搜索树经常被修改(插入/删除操作)并且你需要频繁地查找第 k 小的值,你将如何优化算法?

二叉搜索树(BST)是一种特殊的二叉树,其每个节点都满足以下性质:

  1. 节点的左子树只包含小于节点的数。
  2. 节点的右子树只包含大于节点的数。
  3. 左右子树也分别为二叉搜索树。

要查找二叉搜索树中的第k小元素,可以使用中序遍历的方法,因为中序遍历BST会按照升序访问所有的节点。算法如下:

  1. 对BST进行中序遍历。
  2. 在遍历过程中,维护一个计数器,记录访问的节点数。
  3. 当计数器等于k时,停止遍历,返回当前节点的值。

这个算法的时间复杂度为O(k),空间复杂度为O(h),其中h是树的高度。

如果BST经常被修改,并且需要频繁地查找第k小的值,可以考虑以下优化策略:

  1. 增加额外的信息:在每个节点中存储以该节点为根的子树中有多少个节点。这样,就可以在O(h)时间内找到第k小的元素,其中h是树的高度。

  2. 平衡二叉搜索树:使用AVL树或红黑树等平衡二叉搜索树,保持树的平衡,使得树的高度保持在O(logN),从而加快查找速度。

  3. 缓存:如果对于相同的k值进行了多次查询,可以缓存上一次查询的结果,从而避免重复计算。

  4. 分块+二分搜索:如果k的值不是很大,可以考虑将元素分块存储,并在每个块内维护一个有序数组。查找时先二分搜索确定在哪个块中,然后在块内进行二分搜索。这样可以将时间复杂度降低到O(logN + logK)。

40.2.1 增加额外的信息

在每个节点中存储一个额外的信息size,表示以该节点为根的子树中有多少个节点(包括该节点自身)。在进行查找时,从根节点开始,进行如下操作:

  • 设当前节点为nodeleftSize为其左子树的节点数(如果左子树为空,则leftSize为0)。
  • 如果k == leftSize + 1,则找到了第k小的元素,返回node的值。
  • 如果k <= leftSize,则第k小的元素在左子树中,更新node为其左子节点,重复上述操作。
  • 如果k > leftSize + 1,则第k小的元素在右子树中,更新kk - leftSize - 1,更新node为其右子节点,重复上述操作。
    这个过程的时间复杂度为O(h),其中h是树的高度。

40.2.2 平衡二叉搜索树

使用AVL树或红黑树等平衡二叉搜索树作为数据结构。查找第k小的元素的过程与上述过程类似,区别在于平衡二叉搜索树在插入和删除操作后会进行平衡操作,确保树的高度始终保持在O(logN)。因此,查找第k小元素的时间复杂度为O(logN)。

在AVL树或红黑树这样的平衡二叉搜索树中,每个节点通常不存储子树的大小信息,因此直接计算子树中的节点数量确实是困难的。不过,我们可以在每个节点中增加一个额外的字段来存储以该节点为根的子树的大小(包括节点本身)。

当然,这样做需要在插入、删除和旋转操作时维护这个额外的信息。具体来说:

  1. 插入操作:在插入新节点时,沿着插入路径向上更新每个节点的子树大小。

  2. 删除操作:在删除节点时,同样需要沿着删除路径向上更新每个节点的子树大小。

  3. 旋转操作:在进行AVL树的平衡旋转时,也需要正确更新被旋转节点的子树大小。

通过这种方式,我们可以在O(logN)的时间内找到第k小的元素,其中N是树中节点的数量。这是因为平衡二叉搜索树的高度是O(logN),并且在每个节点上,我们可以在常数时间内得到子树的大小,从而确定第k小的元素是在左子树、右子树还是当前节点。

总的来说,通过在每个节点中存储子树的大小信息,我们可以在平衡二叉搜索树上高效地支持查找第k小元素的操作。

40.2.3 分块+二分搜索

将元素分块存储,并在每个块内维护一个有序数组。查找第k小的元素时,可以使用二分搜索快速确定元素所在的块,然后在块内进行二分搜索找到确切的元素。具体过程如下:

  • 使用二分搜索在块的元数据中查找,确定元素所在的块。块的元数据可以是每个块中的最大元素或者每个块中的元素个数。
  • 在确定的块内使用二分搜索查找第k小的元素。
    这个过程的时间复杂度为O(logN + logK),其中N是块的个数,K是块内元素的个数。

你可能感兴趣的:(数据结构,java,面经,java,系统设计)