📜  门| GATE CS 2020 |第 63 题(1)

📅  最后修改于: 2023-12-03 15:12:37.310000             🧑  作者: Mango

GATE CS 2020 | 第 63 题

本题涉及到数据结构的知识,需要掌握二叉搜索树、平衡二叉树以及 AVL 树的相关概念。

题目描述

给定一个平衡二叉树 T 和一个整数 k,找到 T 中和 K 差值最小的元素。

示例

如果平衡二叉树 T 为:

     9
   /   \
  4     17
 / \    / \
3   6  12  22

则当 k=7 时,输出 6,因为 6 和 7 的差值最小(注意这里说的是差值,不是绝对值)。

解题思路

首先,我们可以在平衡二叉树中找到值等于 k 的节点。如果找到了这个节点,那么它就是和 k 差值最小的元素,因为它和 k 的差值等于 0。

如果找不到值等于 k 的节点,那么我们需要找到一个最接近 k 的节点。接下来有以下两种情况:

  • 找到了比 k 大的节点和比 k 小的节点;
  • 没有比 k 大的节点或没有比 k 小的节点。

对于第一种情况,我们需要比较这两个节点和 k 的距离,然后输出距离更小的那个节点。

对于第二种情况,我们需要递归地遍历整棵树,直到找到离 k 最近的节点为止。

我们可以使用 AVL 树来实现这个算法。AVL 树也是一种平衡二叉树,但是相比于普通的平衡二叉树,AVL 树具有更好的平衡性,可以快速地定位到目标节点。

代码实现

下面是一个基于 AVL 树实现的参考代码,实现了给定一个平衡二叉树 T 和一个整数 k,找到 T 中和 K 差值最小的元素的功能:

class Node:
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None
        self.height = 1

class AVLTree:
    def __init__(self):
        self.root = None

    def insert(self, root, key):
        if not root:
            return Node(key)
        elif key < root.val:
            root.left = self.insert(root.left, key)
        else:
            root.right = self.insert(root.right, key)

        root.height = 1 + max(self.getHeight(root.left), self.getHeight(root.right))

        balance = self.getBalance(root)

        if balance > 1 and key < root.left.val:
            return self.rightRotate(root)

        if balance < -1 and key > root.right.val:
            return self.leftRotate(root)

        if balance > 1 and key > root.left.val:
            root.left = self.leftRotate(root.left)
            return self.rightRotate(root)

        if balance < -1 and key < root.right.val:
            root.right = self.rightRotate(root.right)
            return self.leftRotate(root)

        return root

    def leftRotate(self, z):
        y = z.right
        T2 = y.left

        y.left = z
        z.right = T2

        z.height = 1 + max(self.getHeight(z.left), self.getHeight(z.right))
        y.height = 1 + max(self.getHeight(y.left), self.getHeight(y.right))

        return y

    def rightRotate(self, z):
        y = z.left
        T3 = y.right

        y.right = z
        z.left = T3

        z.height = 1 + max(self.getHeight(z.left), self.getHeight(z.right))
        y.height = 1 + max(self.getHeight(y.left), self.getHeight(y.right))

        return y

    def getHeight(self, root):
        if not root:
            return 0

        return root.height

    def getBalance(self, root):
        if not root:
            return 0

        return self.getHeight(root.left) - self.getHeight(root.right)

    def findClosest(self, root, k, minDiff, closest):
        if root is None:
            return closest

        # Check if this node is the closest so far
        if abs(root.val - k) < minDiff:
            minDiff = abs(root.val - k)
            closest = root.val

        # If k is less than node value, go left
        if k < root.val:
            closest = self.findClosest(root.left, k, minDiff, closest)
        
        # If k is greater than node value, go right
        elif k > root.val:
            closest = self.findClosest(root.right, k, minDiff, closest)

        return closest

    def findClosestNode(self, root, k):
        if root is None:
            return None

        # If k is less than node value, go left
        if k < root.val:
            node = root.left
        # If k is greater than node value, go right
        elif k > root.val:
            node = root.right
        # If k is equal to node value, node is found
        else:
            node = root

        # If node is None, return root
        if node is None:
            return root

        # If k is less than node value, check left tree
        if k < node.val:
            closest = self.findClosest(root.left, k, abs(node.val - k), node.val)
        # If k is greater than node value, check right tree
        elif k > node.val:
            closest = self.findClosest(root.right, k, abs(node.val - k), node.val)
        # If k is equal to node value, node is the closest
        else:
            return node.val
        
        return closest

    def findClosestValue(self, root, k):
        node = self.findClosestNode(root, k)
        return node

    def preOrder(self, root):
        if not root:
            return

        print("{0} ".format(root.val), end="")
        self.preOrder(root.left)
        self.preOrder(root.right)

tree = AVLTree()
root = None
keys = [9, 4, 17, 3, 6, 12, 22]

for key in keys:
    root = tree.insert(root, key)

print("The AVL tree is:")
tree.preOrder(root)

k = 7
closest = tree.findClosestValue(root, k)
print("\nThe closest value to {0} in AVL tree is {1}.".format(k, closest))
参考资料