![](/img/trans.png)
[英]how to find the number of nodes at level x of the binary search tree ( with restrictions )
[英]How to find swapped nodes in a binary search tree?
這是一道面試題。
給出了一個二叉搜索樹並且兩個節點的值已經交換。 問題是如何在樹的單次遍歷中找到節點和交換的值?
我試圖使用下面的代碼解決這個問題,但我無法停止遞歸,所以我遇到了分段錯誤。 幫助我如何停止遞歸。
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <stdlib.h>
/* A binary tree node has data, pointer to left child
and a pointer to right child */
struct node
{
int data;
struct node* left;
struct node* right;
};
/* Helper function that allocates a new node with the
given data and NULL left and right pointers. */
struct node* newNode(int data)
{
struct node* node = (struct node*)
malloc(sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return(node);
}
void modifiedInorder(struct node *root, struct node **nextNode)
{
static int nextdata=INT_MAX;
if(root)
{
modifiedInorder(root->right, nextNode);
if(root->data > nextdata)
return;
*nextNode = root;
nextdata = root->data;
modifiedInorder(root->left, nextNode);
}
}
void inorder(struct node *root, struct node *copyroot, struct node **prevNode)
{
static int prevdata = INT_MIN;
if(root)
{
inorder(root->left, copyroot, prevNode);
if(root->data < prevdata)
{
struct node *nextNode = NULL;
modifiedInorder(copyroot, &nextNode);
int data = nextNode->data;
nextNode->data = (*prevNode)->data;
(*prevNode)->data = data;
return;
}
*prevNode = root;
prevdata = root->data;
inorder(root->right, copyroot, prevNode);
}
}
/* Given a binary tree, print its nodes in inorder*/
void printInorder(struct node* node)
{
if (node == NULL)
return;
/* first recur on left child */
printInorder(node->left);
/* then print the data of node */
printf("%d ", node->data);
/* now recur on right child */
printInorder(node->right);
}
int main()
{
/* 4
/ \
2 3
/ \
1 5
*/
struct node *root = newNode(1); // newNode will return a node.
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);
printf("Inorder Traversal of the original tree\n ");
printInorder(root);
struct node *prevNode=NULL;
inorder(root, root, &prevNode);
printf("\nInorder Traversal of the fixed tree \n");
printInorder(root);
return 0;
}
使用中序遍歷走到樹。 通過使用它,您將對所有元素進行排序,並交換比周圍元素大的一個元素。
例如考慮下面的二叉樹
_ 20 _
/ \
15 30
/ \ / \
10 17 25 33
/ | / \ / \ | \
9 16 12 18 22 26 31 34
首先,我們將其線性化為一個數組,我們得到
9 10 16 15 12 17 18 20 22 25 26 30 31 33 34
現在您可以注意到 16 大於其周圍的元素,而 12 小於它們。 這立即告訴我們 12 和 16 交換了。
以下函數通過在收緊邊界的同時遞歸迭代左右子樹來驗證樹是否為 BST。
我相信可以通過修改它來實現上述任務
編輯:我們需要區分遞歸函數返回 true 與指向交換節點的指針
這假設問題定義中提到的只有兩個這樣的值
bool validate_bst(tnode *temp, int min, int max)
{
if(temp == NULL)
return true;
if(temp->data > min && temp->data < max)
{
if( validate_bst(temp->left, min, temp->data) &&
validate_bst(temp->right, temp->data, max) )
return true;
}
return false;
}
主要會像這樣調用上面的api
validate_bst(root, -1, 100); // Basically we pass -1 as min and 100 as max in
// this instance
我們可以在 O(n) 時間內解決這個問題,並且只需遍歷給定的 BST。 由於 BST 的中序遍歷始終是排序數組,因此問題可以簡化為排序數組的兩個元素交換的問題。 我們需要處理兩種情況:
6
/ \
10 2
/ \ / \
1 3 7 12
1.交換節點在BST的中序遍歷中不相鄰。
例如,節點 10 和 2 在 {1 10 3 6 7 2 12} 中交換。 給定樹的中序遍歷是 1 10 3 6 7 2 12
如果仔細觀察,在中序遍歷過程中,我們發現節點3比上一個訪問過的節點10小。這里保存節點10(上一個節點)的上下文。 再次,我們發現節點 2 比之前的節點 7 小。這一次,我們保存了節點 2(當前節點)的上下文。 最后交換兩個節點的值。
2.交換節點在BST的中序遍歷中是相鄰的。
6
/ \
10 8
/ \ / \
1 3 7 12
例如,節點 10 和 2 在 {1 10 3 6 7 8 12} 中交換。 給定樹的中序遍歷是 1 10 3 6 7 8 12 與情況 #1 不同,這里只存在一個節點值小於前一個節點值的點。 例如,節點 10 小於節點 36。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
void recoverTreeUtil(TreeNode *root, TreeNode **first, TreeNode **middle, TreeNode **last, TreeNode **prev) {
if (root) {
recoverTreeUtil(root->left, first, middle, last, prev);
if (*prev && (*prev)->val > root->val) {
if (!(*first)) {
*first = *prev;
*middle = root;
} else *last = root;
}
*prev = root;
recoverTreeUtil(root->right, first, middle, last, prev);
}
}
void recoverTree(TreeNode* root) {
TreeNode *first, *middle, *last, *prev;
first = middle = last = prev = nullptr;
recoverTreeUtil(root, &first, &middle, &last, &prev);
if (first && last) swap(first->val, last->val);
else if (first && middle) swap(first->val, middle->val);
}
};
我在 Geeksforgeeks.com 上找到了這個問題的另一種解決方案.........伙計們,你可以查看這個線程以獲得對以下代碼的更多解釋http://www.geeksforgeeks.org/archives/ 23616
// Two nodes in the BST's swapped, correct the BST.
#include <stdio.h>
#include <stdlib.h>
/* A binary tree node has data, pointer to left child
and a pointer to right child */
struct node
{
int data;
struct node *left, *right;
};
// A utility function to swap two integers
void swap( int* a, int* b )
{
int t = *a;
*a = *b;
*b = t;
}
/* Helper function that allocates a new node with the
given data and NULL left and right pointers. */
struct node* newNode(int data)
{
struct node* node = (struct node *)malloc(sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return(node);
}
// This function does inorder traversal to find out the two swapped nodes.
// It sets three pointers, first, middle and last. If the swapped nodes are
// adjacent to each other, then first and middle contain the resultant nodes
// Else, first and last contain the resultant nodes
void correctBSTUtil( struct node* root, struct node** first,
struct node** middle, struct node** last,
struct node** prev )
{
if( root )
{
// Recur for the left subtree
correctBSTUtil( root->left, first, middle, last, prev );
// If this node is smaller than the previous node, it's violating
// the BST rule.
if (*prev && root->data < (*prev)->data)
{
// If this is first violation, mark these two nodes as
// 'first' and 'middle'
if ( !*first )
{
*first = *prev;
*middle = root;
}
// If this is second violation, mark this node as last
else
*last = root;
}
// Mark this node as previous
*prev = root;
// Recur for the right subtree
correctBSTUtil( root->right, first, middle, last, prev );
}
}
// A function to fix a given BST where two nodes are swapped. This
// function uses correctBSTUtil() to find out two nodes and swaps the
// nodes to fix the BST
void correctBST( struct node* root )
{
// Initialize pointers needed for correctBSTUtil()
struct node *first, *middle, *last, *prev;
first = middle = last = prev = NULL;
// Set the poiters to find out two nodes
correctBSTUtil( root, &first, &middle, &last, &prev );
// Fix (or correct) the tree
if( first && last )
swap( &(first->data), &(last->data) );
else if( first && middle ) // Adjacent nodes swapped
swap( &(first->data), &(middle->data) );
// else nodes have not been swapped, passed tree is really BST.
}
/* A utility function to print Inoder traversal */
void printInorder(struct node* node)
{
if (node == NULL)
return;
printInorder(node->left);
printf("%d ", node->data);
printInorder(node->right);
}
/* Driver program to test above functions*/
int main()
{
/* 6
/ \
10 2
/ \ / \
1 3 7 12
10 and 2 are swapped
*/
struct node *root = newNode(6);
root->left = newNode(10);
root->right = newNode(2);
root->left->left = newNode(1);
root->left->right = newNode(3);
root->right->right = newNode(12);
root->right->left = newNode(7);
printf("Inorder Traversal of the original tree \n");
printInorder(root);
correctBST(root);
printf("\nInorder Traversal of the fixed tree \n");
printInorder(root);
return 0;
}
Output:
Inorder Traversal of the original tree
1 10 3 6 7 2 12
Inorder Traversal of the fixed tree
1 2 3 6 7 10 12
Time Complexity: O(n)
更多測試案例請參考此鏈接http://ideone.com/uNlPx
我的 C++ 解決方案:
struct node *correctBST( struct node* root )
{
//add code here.
if(!root)return root;
struct node* r = root;
stack<struct node*>st;
// cout<<"1"<<endl;
struct node* first = NULL;
struct node* middle = NULL;
struct node* last = NULL;
struct node* prev = NULL;
while(root || !st.empty()){
while(root){
st.push(root);
root = root->left;
}
root = st.top();
st.pop();
if(prev && prev->data > root->data){
if(!first){
first = prev;
middle = root;
}
else{
last = root;
}
}
prev = root;
root = root->right;
}
if(first && last){
swap(first->data,last->data);
}
else{
swap(first->data,middle->data);
}
return r;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.