Olvastam itt egy gyakorlat interjúkban néven érvényesítése bináris kereső fába.
Pontosan hogyan is működik ez? Mi lenne az egyik keres az érvényesítő bináris keresési fa? Írtam egy alap keresési fát, de soha nem hallottam ezt a fogalmat.
Olvastam itt egy gyakorlat interjúkban néven érvényesítése bináris kereső fába.
Pontosan hogyan is működik ez? Mi lenne az egyik keres az érvényesítő bináris keresési fa? Írtam egy alap keresési fát, de soha nem hallottam ezt a fogalmat.
„Ellenőrzés” bináris kereső fába azt jelenti, hogy ellenőrizze, hogy valóban van minden kisebb elemeket a bal oldalon és a nagy tételek a jobb oldalon. Lényegében ez egy csekket, hogy ha egy bináris fa egy bináris keresési fa.
Tulajdonképpen ez a hiba mindenkinél jelent egy interjúban.
Leftchild kell vetni (minLimitof csomópont, node.value)
Rightchild kell vetni (node.value, MaxLimit csomópont)
IsValidBST(root,-infinity,infinity);
bool IsValidBST(BinaryNode node, int MIN, int MAX)
{
if(node == null)
return true;
if(node.element > MIN
&& node.element < MAX
&& IsValidBST(node.left,MIN,node.element)
&& IsValidBST(node.right,node.element,MAX))
return true;
else
return false;
}
A másik megoldás (ha a hely nem kényszer): Készítsen egy inorder bejárása a fa és tárolja a csomópont értékeket egy tömbben. Ha a tömb rendezett sorrendben, annak érvényes BST egyébként nem.
Itt van az én oldat Clojure:
(defstruct BST :val :left :right)
(defn in-order [bst]
(when-let [{:keys [val, left, right]} bst]
(lazy-seq
(concat (in-order left) (list val) (in-order right)))))
(defn is-strictly-sorted? [col]
(every?
(fn `a b` (< a b))
(partition 2 1 col)))
(defn is-valid-BST [bst]
(is-strictly-sorted? (in-order bst)))
„Jobb, hogy meghatározzon egy invariáns először. Itt az invariáns van - bármely két egymást követő eleme a BST az in-order bejárás kell lennie szigorúan növekvő sorrendben való megjelenés (nem lehet egyenlő, mindig egyre in-sorrendben bejárás.) Tehát megoldás is csak egy egyszerű rendű bejárás megjegyezni és az utoljára meglátogatott csomópont és összehasonlítása az aktuális csomópont ellen az utoljára meglátogatott egy a „<” (vagy „>”).”
Iteratív oldatot inorder bejárás.
bool is_bst(Node *root) {
if (!root)
return true;
std::stack<Node*> stack;
bool started = false;
Node *node = root;
int prev_val;
while(true) {
if (node) {
stack.push(node);
node = node->left();
continue;
}
if (stack.empty())
break;
node = stack.top();
stack.pop();
/* beginning of bst check */
if(!started) {
prev_val = node->val();
started = true;
} else {
if (prev_val > node->val())
return false;
prev_val = node->val();
}
/* end of bst check */
node = node->right();
}
return true;
}
Rekurzív oldatot:
isBinary(root)
{
if root == null
return true
else if( root.left == NULL and root.right == NULL)
return true
else if(root.left == NULL)
if(root.right.element > root.element)
rerturn isBInary(root.right)
else if (root.left.element < root.element)
return isBinary(root.left)
else
return isBInary(root.left) and isBinary(root.right)
}
bool BinarySearchTree::validate() {
int minVal = -1;
int maxVal = -1;
return ValidateImpl(root, minVal, maxVal);
}
bool BinarySearchTree::ValidateImpl(Node *currRoot, int &minVal, int &maxVal)
{
int leftMin = -1;
int leftMax = -1;
int rightMin = -1;
int rightMax = -1;
if (currRoot == NULL) return true;
if (currRoot->left) {
if (currRoot->left->value < currRoot->value) {
if (!ValidateImpl(currRoot->left, leftMin, leftMax)) return false;
if (leftMax != currRoot->left->value && currRoot->value < leftMax) return false;
}
else
return false;
} else {
leftMin = leftMax = currRoot->value;
}
if (currRoot->right) {
if (currRoot->right->value > currRoot->value) {
if(!ValidateImpl(currRoot->right, rightMin, rightMax)) return false;
if (rightMin != currRoot->right->value && currRoot->value > rightMin) return false;
}
else return false;
} else {
rightMin = rightMax = currRoot->value;
}
minVal = leftMin < rightMin ? leftMin : rightMin;
maxVal = leftMax > rightMax ? leftMax : rightMax;
return true;
}
// using inorder traverse based Impl
bool BinarySearchTree::validate() {
int val = -1;
return ValidateImpl(root, val);
}
// inorder traverse based Impl
bool BinarySearchTree::ValidateImpl(Node *currRoot, int &val) {
if (currRoot == NULL) return true;
if (currRoot->left) {
if (currRoot->left->value > currRoot->value) return false;
if(!ValidateImpl(currRoot->left, val)) return false;
}
if (val > currRoot->value) return false;
val = currRoot->value;
if (currRoot->right) {
if (currRoot->right->value < currRoot->value) return false;
if(!ValidateImpl(currRoot->right, val)) return false;
}
return true;
}
boolean isBST(Node root) {
if (root == null) { return true; }
return (isBST(root.left) && (isBST(root.right) && (root.left == null || root.left.data <= root.data) && (root.right == null || root.right.data > root.data));
}
Itt az iteratív megoldás használata nélkül extra helyet.
Node{
int value;
Node right, left
}
public boolean ValidateBST(Node root){
Node currNode = root;
Node prevNode = null;
Stack<Node> stack = new Stack<Node>();
while(true){
if(currNode != null){
stack.push(currNode);
currNode = currNode.left;
continue;
}
if(stack.empty()){
return;
}
currNode = stack.pop();
if(prevNode != null){
if(currNode.value < prevNode.value){
return false;
}
}
prevNode = currNode;
currNode = currNode.right;
}
}
bool ValidateBST(Node *pCurrentNode, int nMin = INT_MIN, int nMax = INT_MAX)
{
return
(
pCurrentNode == NULL
)
||
(
(
!pCurrentNode->pLeftNode ||
(
pCurrentNode->pLeftNode->value < pCurrentNode->value &&
pCurrentNode->pLeftNode->value < nMax &&
ValidateBST(pCurrentNode->pLeftNode, nMin, pCurrentNode->value)
)
)
&&
(
!pCurrentNode->pRightNode ||
(
pCurrentNode->pRightNode->value > pCurrentNode->value &&
pCurrentNode->pRightNode->value > nMin &&
ValidateBST(pCurrentNode->pRightNode, pCurrentNode->value, nMax)
)
)
);
}
A legjobb megoldás találtam jelentése O (n), és nem használ extra helyet. Ez hasonló a inorder bejárása, de tárolása helyett, hogy tömböt, majd ellenőrzi, hogy van rendezve vehetünk egy statikus változó, és ellenőrizze, míg inorder áthaladó e tömb rendezve.
static struct node *prev = NULL;
bool isBST(struct node* root)
{
// traverse the tree in inorder fashion and keep track of prev node
if (root)
{
if (!isBST(root->left))
return false;
// Allows only distinct valued nodes
if (prev != NULL && root->data <= prev->data)
return false;
prev = root;
return isBST(root->right);
}
return true;
}
Annak kiderítésére, hogy adott BT BST bármilyen adattípus, akkor kell menni az alábbi megközelítés. 1. Hívás rekurzív függvény végéig levél csomópont segítségével inorder bejárása 2. Építsd meg minimum és maximum értékek magad.
Fa elemnek kevesebb / több, mint operátor által meghatározott.
#define MIN (FirstVal, SecondVal) ((FirstVal) < (SecondVal)) ? (FirstVal):(SecondVal)
#define MAX (FirstVal, SecondVal) ((FirstVal) > (SecondVal)) ? (FirstVal):(SecondVal)
template <class T>
bool IsValidBST (treeNode &root)
{
T min, max;
return IsValidBST (root, &min, &max);
}
template <class T>
bool IsValidBST (treeNode *root, T *MIN , T *MAX)
{
T leftMin, leftMax, rightMin, rightMax;
bool isValidBST;
if (root->leftNode == NULL && root->rightNode == NULL)
{
*MIN = root->element;
*MAX = root->element;
return true;
}
isValidBST = IsValidBST (root->leftNode, &leftMin, &leftMax);
if (isValidBST)
isValidBST = IsValidBST (root->rightNode, &rightMin, &rightMax);
if (isValidBST)
{
*MIN = MIN (leftMIN, rightMIN);
*Max = MAX (rightMax, leftMax);
}
return isValidBST;
}
bool isBST(struct node* root)
{
static struct node *prev = NULL;
// traverse the tree in inorder fashion and keep track of prev node
if (root)
{
if (!isBST(root->left))
return false;
// Allows only distinct valued nodes
if (prev != NULL && root->data <= prev->data)
return false;
prev = root;
return isBST(root->right);
}
return true;
}
Jól működik :)
A rekurzió könnyű, de iteratív megközelítés jobb, van egy iteratív változata fent, de ez túl bonyolult, mint szükséges. Itt a legjobb megoldás c++, amit valaha is találni sehol:
Ez az algoritmus fut O(N)időben, és szüksége van O(lgN)hely.
struct TreeNode
{
int value;
TreeNode* left;
TreeNode* right;
};
bool isBST(TreeNode* root) {
vector<TreeNode*> stack;
TreeNode* prev = nullptr;
while (root || stack.size()) {
if (root) {
stack.push_back(root);
root = root->left;
} else {
if (prev && stack.back()->value <= prev->value)
return false;
prev = stack.back();
root = prev->right;
stack.pop_back();
}
}
return true;
}
Írtam egy megoldást használni inorder bejárás BST és ellenőrizze, hogy a csomópontok növekszik megrendelésének tér O(1)és az idő O(n). TreeNode predecessorvan prev csomópontot. Nem vagyok biztos a megoldás helyes-e vagy sem. Mivel a inorder Bejárás nem határozza meg az egész fa.
public boolean isValidBST(TreeNode root, TreeNode predecessor) {
boolean left = true, right = true;
if (root.left != null) {
left = isValidBST(root.left, predecessor);
}
if (!left)
return false;
if (predecessor.val > root.val)
return false;
predecessor.val = root.val;
if (root.right != null) {
right = isValidBST(root.right, predecessor);
}
if (!right)
return false;
return true;
}
A következőkben a Java megvalósítása BST érvényesítését, ahol utazunk a fa-order DFS és hamis értékkel tér vissza, ha megkapjuk minden szám, amely nagyobb, mint az utolsó szám.
static class BSTValidator {
private boolean lastNumberInitialized = false;
private int lastNumber = -1;
boolean isValidBST(TreeNode node) {
if (node.left != null && !isValidBST(node.left)) return false;
// In-order visiting should never see number less than previous
// in valid BST.
if (lastNumberInitialized && (lastNumber > node.getData())) return false;
if (!lastNumberInitialized) lastNumberInitialized = true;
lastNumber = node.getData();
if (node.right != null && !isValidBST(node.right)) return false;
return true;
}
}
Mivel az in-order bejárás a BST egy nem csökken sorrendben tudtuk használni az ingatlan megítélni, hogy egy bináris fa BST-e vagy sem. Használata Morris bejárás és fenntartása a precsomópont, mi lehetne még oldat O (n) idő és O (1) térben összetettsége. Itt van a kód
public boolean isValidBST(TreeNode root) {
TreeNode pre = null, cur = root, tmp;
while(cur != null) {
if(cur.left == null) {
if(pre != null && pre.val >= cur.val)
return false;
pre = cur;
cur = cur.right;
}
else {
tmp = cur.left;
while(tmp.right != null && tmp.right != cur)
tmp = tmp.right;
if(tmp.right == null) { // left child has not been visited
tmp.right = cur;
cur = cur.left;
}
else { // left child has been visited already
tmp.right = null;
if(pre != null && pre.val >= cur.val)
return false;
pre = cur;
cur = cur.right;
}
}
}
return true;
}
Van ez a kérdés egy telefonos interjú a közelmúltban, és küszködött vele többet, mint kellett volna. Megpróbáltam nyomon követni a minimumok és maximumok a gyermek csomópontok és nem tudtam csomagolja az agyam körül a különböző esetekben nyomása alatt egy interjúban.
Gondolkodás után, míg elalszik este, rájöttem, hogy ez olyan egyszerű, mint a nyomon követése az utolsó csomópont a felkeresett közben inorder bejárása. Java:
public <T extends Comparable<T>> boolean isBst(TreeNode<T> root) {
return isBst(root, null);
}
private <T extends Comparable<T>> boolean isBst(TreeNode<T> node, TreeNode<T> prev) {
if (node == null)
return true;
if (isBst(node.left, prev) && (prev == null || prev.compareTo(node) < 0 ))
return isBst(node.right, node);
return false;
}
Iteratív megoldás.
private static boolean checkBst(bst node) {
Stack<bst> s = new Stack<bst>();
bst temp;
while(node!=null){
s.push(node);
node=node.left;
}
while (!s.isEmpty()){
node = s.pop();
System.out.println(node.val);
temp = node;
if(node.right!=null){
node = node.right;
while(node!=null)
{
//Checking if the current value is lesser than the previous value and ancestor.
if(node.val < temp.val)
return false;
if(!s.isEmpty())
if(node.val>s.peek().val)
return false;
s.push(node);
if(node!=null)
node=node.left;
}
}
}
return true;
}
Ez működik ismétlődéseket.
// time O(n), space O(logn)
// pseudocode
is-bst(node, min = int.min, max = int.max):
if node == null:
return true
if node.value <= min || max < node.value:
return false
return is-bst(node.left, min, node.value)
&& is-bst(node.right, node.value, max)
Ez akkor is működik a int.minés int.maxértékeket Nullabletípusok.
// time O(n), space O(logn)
// pseudocode
is-bst(node, min = null, max = null):
if node == null:
return true
if min != null && node.value <= min
return false
if max != null && max < node.value:
return false
return is-bst(node.left, min, node.value)
&& is-bst(node.right, node.value, max)
Ihlette http://www.jiuzhang.com/solutions/validate-binary-search-tree/
Jelenleg két általános megoldás: bejárás és oszd && uralkodj.
public class validateBinarySearchTree {
public boolean isValidBST(TreeNode root) {
return isBSTTraversal(root) && isBSTDivideAndConquer(root);
}
// Solution 1: Traversal
// The inorder sequence of a BST is a sorted ascending list
private int lastValue = 0; // the init value of it doesn't matter.
private boolean firstNode = true;
public boolean isBSTTraversal(TreeNode root) {
if (root == null) {
return true;
}
if (!isValidBST(root.left)) {
return false;
}
// firstNode is needed because of if firstNode is Integer.MIN_VALUE,
// even if we set lastValue to Integer.MIN_VALUE, it will still return false
if (!firstNode && lastValue >= root.val) {
return false;
}
firstNode = false;
lastValue = root.val;
if (!isValidBST(root.right)) {
return false;
}
return true;
}
// Solution 2: divide && conquer
private class Result {
int min;
int max;
boolean isBST;
Result(int min, int max, boolean isBST) {
this.min = min;
this.max = max;
this.isBST = isBST;
}
}
public boolean isBSTDivideAndConquer(TreeNode root) {
return isBSTHelper(root).isBST;
}
public Result isBSTHelper(TreeNode root) {
// For leaf node's left or right
if (root == null) {
// we set min to Integer.MAX_VALUE and max to Integer.MIN_VALUE
// because of in the previous level which is the leaf level,
// we want to set the min or max to that leaf node's val (in the last return line)
return new Result(Integer.MAX_VALUE, Integer.MIN_VALUE, true);
}
Result left = isBSTHelper(root.left);
Result right = isBSTHelper(root.right);
if (!left.isBST || !right.isBST) {
return new Result(0,0, false);
}
// For non-leaf node
if (root.left != null && left.max >= root.val
&& root.right != null && right.min <= root.val) {
return new Result(0, 0, false);
}
return new Result(Math.min(left.min, root.val),
Math.max(right.max, root.val), true);
}
}
Itt van a rekurzív megoldást írt JavaScript
function isBST(tree) {
if (tree === null) return true;
if (tree.left != undefined && tree.left.value > tree.value) {
return false;
}
if (tree.right != undefined && tree.right.value <= tree.value) {
return false;
}
return isBST(tree.left) && isBST(tree.right);
}
A Java és lehetővé teszi csomópontok ugyanazt az értéket vagy a sub-tree:
public boolean isValid(Node node) {
return isValid(node, Integer.MIN_VALUE, Integer.MAX_VALUE);
}
private boolean isValid(Node node, int minLimit, int maxLimit) {
if (node == null)
return true;
return minLimit <= node.value && node.value <= maxLimit
&& isValid(node.left, minLimit, node.value)
&& isValid(node.right, node.value, maxLimit);
}
private void validateBinarySearchTree(Node node) {
if (node == null) return;
Node left = node.getLeft();
if (left != null) {
if (left.getData() < node.getData()) {
validateBinarySearchTree(left);
} else {
throw new IllegalStateException("Not a valid Binary Search tree");
}
}
Node right = node.getRight();
if (right != null) {
if (right.getData() > node.getData()) {
validateBinarySearchTree(right);
} else {
throw new IllegalStateException("Not a valid Binary Search tree");
}
}
}
Itt van az én válasz python, azt minden sarkon esetben foglalkozni és jól tesztelt hackerrank honlapján
""" Node is defined as
class node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
"""
def checkBST(root):
return checkLeftSubTree(root, root.left) and checkRightSubTree(root, root.right)
def checkLeftSubTree(root, subTree):
if not subTree:
return True
else:
return root.data > subTree.data \
and checkLeftSubTree(root, subTree.left) \
and checkLeftSubTree(root, subTree.right) \
and checkLeftSubTree(subTree, subTree.left) \
and checkRightSubTree(subTree, subTree.right)
def checkRightSubTree(root, subTree):
if not subTree:
return True
else:
return root.data < subTree.data \
and checkRightSubTree(root, subTree.left) \
and checkRightSubTree(root, subTree.right) \
and checkRightSubTree(subTree, subTree.right) \
and checkLeftSubTree(subTree, subTree.left)
Egysoros
bool is_bst(Node *root, int from, int to) {
return (root == NULL) ? true :
root->val >= from && root->val <= to &&
is_bst(root->left, from, root->val) &&
is_bst(root->right, root->val, to);
}
Elég hosszú sort mégis.
Itt egy megoldás a java Sedgewick algoritmus osztályban. Ellenőrizze a teljes BST végrehajtását itt
Én hozzáadtam némi magyarázó megjegyzéseket
private boolean isBST() {
return isBST(root, null, null);
}
private boolean isBST(Node x, Key min, Key max) {
if (x == null) return true;
// when checking right subtree min is key of x's parent
if (min != null && x.key.compareTo(min) <= 0) return false;
// when checking left subtree, max is key of x's parent
if (max != null && x.key.compareTo(max) >= 0) return false;
// check left subtree and right subtree
return isBST(x.left, min, x.key) && isBST(x.right, x.key, max);
}
iterativefunkció ellenőrzi iteratív hogy adott fa bináris kereső fába. recursefunkció ellenőrzi rekurzív hogy adott fa bináris kereső fába, vagy sem. iterativefunkció használom bfs ellenőrzésére BST.recursefunkció használom DFS ellenőrzésére BST.O(n)iterativeoldat előnyhöz recursemegoldás, és ez iterativemegoldást jelent a korai megállás.recursefunkció lehet optimalizálni a korai leállítás globális jelző értéket.És megy összehasonlítjuk a jelenlegi csomópont tartományon belüli értékek. Ha bármelyik csomópont értéke nincs a tartományban, majd vissza False
class Solution:
def isValidBST(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
return self.iterative(root)
# return self.recurse(root, float("inf"), float("-inf"))
def iterative(self, root):
if not root:
return True
level = [[root, -float("inf"), float("inf")]]
while level:
next_level = []
for element in level:
node, min_val, max_val = element
if min_val<node.val<max_val:
if node.left:
next_level.append([node.left, min_val, node.val])
if node.right:
next_level.append([node.right, node.val, max_val])
else:
return False
level = next_level
return True
def recurse(self, root, maxi, mini):
if root is None:
return True
if root.val < mini or root.val > maxi:
return False
return self.recurse(root.left, root.val-1, mini) and self.recurse(root.right, maxi, root.val+1)
Python végrehajtás példa. Ez a példa írja kommentárokat. Azonban mivel Node osztály használ magának azt kell tartalmaznia, mint az első sorban a modul:
from __future__ import annotations
Ellenkező esetben kapsz name 'Node' is not definedhiba. Ez a példa is dataclass példaként. Ha szeretné ellenőrizni, hogy ez BST használja rekurzív ellenőrzésére balra és jobbra csomópontok értékeket.
"""Checks if Binary Search Tree (BST) is balanced"""
from __future__ import annotations
import sys
from dataclasses import dataclass
MAX_KEY = sys.maxsize
MIN_KEY = -sys.maxsize - 1
@dataclass
class Node:
value: int
left: Node
right: Node
@property
def is_leaf(self) -> bool:
"""Check if node is a leaf"""
return not self.left and not self.right
def is_bst(node: Node, min_value: int, max_value: int) -> bool:
if node.value < min_value or max_value < node.value:
return False
elif node.is_leaf:
return True
return is_bst(node.left, min_value, node.value) and is_bst(
node.right, node.value, max_value
)
if __name__ == "__main__":
node5 = Node(5, None, None)
node25 = Node(25, None, None)
node40 = Node(40, None, None)
node10 = Node(10, None, None)
# balanced tree
node30 = Node(30, node25, node40)
root = Node(20, node10, node30)
print(is_bst(root, MIN_KEY, MAX_KEY))
# unbalanced tree
node30 = Node(30, node5, node40)
root = Node(20, node10, node30)
print(is_bst(root, MIN_KEY, MAX_KEY))