How to print if the value inserted in a BST should be inserted in the left or right subtree - binary-search-tree

I'm inserting values in a BST and printing "left" if the value should be inserted in the left subtree or "right" if the value should be inserted in the right subtree but when I'm going to print, several right/left are printed, how can I fix it? I think it's due to recursion but I can't solve it without recursion.
BST insertion code:
Node *insert(Node **root, int key)
{
if(*root == NULL)
{
Node *newNode = (Node*)malloc(sizeof(Node));
if(newNode == NULL)
return NULL;
newNode->key= key;
newNode->left = NULL;
newNode->right = NULL;
(*root) = newNode;
return newNode;
}
if(key < (*root)->key){
printf("left ");
return insert(&((*root)->left),key);
}
else{
printf("right ");
return insert((&(*root)->right),key);
}
}
Example:
Inserting the values: 25 - 20 - 36 - 10 - 22 - 30

What I have got from the expected output is that the "left" or "right" indicates the relative position of the node with respect to its parent node.
If this is so, you can do this:
if(key < (*root)->key){
if ( (*root)->left==NULL)
printf("left ");
return insert(&((*root)->left),key);
}
else{
if ( (*root)->right==NULL)
printf("right ");
return insert((&(*root)->right),key);
}
The logic is, We will get to know whether it is left or right just 1 step before the insertion step. I just checked if the next node we are going to , is NULL or not.

Related

Remove duplicates from an unsorted linked list. I used ArrayList to solve

Given an unsorted linked list of N nodes. The task is to remove duplicate elements from this unsorted Linked List. When a value appears in multiple nodes, the node which appeared first should be kept, all others duplicates are to be removed.
Example 1:
Input:
N = 4
value[] = {5,2,2,4}
Output: 5 2 4
Explanation: Given linked list elements are
5->2->2->4, in which 2 is repeated only.
So, we will delete the extra repeated
elements 2 from the linked list and the
resultant linked list will contain 5->2->4
It's a question on GFG and I passed 405 test cases but on 406th test case it shows 'Time limit exceeded Error'. Is it like ArrayList is taking too long to traverse every element again and again?
Then I tried using HashSet with the same logic and it worked perfectly and passes all test cases.
class Solution
{
//Function to remove duplicates from unsorted linked list.
public Node removeDuplicates(Node head)
{
// Your code here
Node prev = head;
Node temp = head.next;
ArrayList<Integer> val = new ArrayList<>();
val.add(head.data);
while(temp != null){
if(val.contains(temp.data)){
prev.next = temp.next;
temp = temp.next;
}
else{
val.add(temp.data);
temp = temp.next;
prev = prev.next;
}
}
return head;
}
}
While your logic is indeed correct, it is not the most optimal solution.
Consider this example:
Input: 5 -> 2 -> 2 -> 2 -> 2 -> 3
Your Result steps would be:
5 -> 2 -> 2 -> 2 -> 2 -> 3
5 -> 2 -> 2 -> 2 -> 3
5 -> 2 -> 2 -> 3
5 -> 2 -> 3
Instead of doing the pointer writes so many times, you could keep going forward till you encounter the first not-seen-so-far node and make your pointers point to the new node directly.
Moreover, instead of using an ArrayList, you could use a Set. The .contains() method in ArrayList has a time complexity of O(n) where n is the number of elements in the ArrayList. As you do this operation M times for each loop, your order is going to be O(mn). Set has a time complexity of O(1) (Constant lookup time), So if you the do the operation M times, it will be M times O(1) which is whole lot faster.
Perhaps this code might help:
class Solution
{
//Function to remove duplicates from unsorted linked list.
public Node removeDuplicates(Node head)
{
if(head == NULL) { // BASE CASE
return head;
}
Node prev = head;
Node temp = head.next;
boolean shouldDelete = false;
Set<Integer> set = new HashSet<>();
set.add(head.data);
while(temp != null){
if(set.contains(temp.data)){
shouldDelete = true; // Set this to true to make sure any duplicates at the end is also taken care of.
}
else{
shouldDelete = false; // Set this to false as we have encountered a not-seen-so-far node.
set.add(temp.data);
prev.next = temp;
prev = temp;
}
temp = temp.next;
}
if(shouldDelete) { // There is duplicate elements in the end that has not been trimmed because we never encountered a not-seen-so-far element. So set it to NULL
prev.next = NULL;
}
return head;
}
}

Write a kotlin program that prints the number that is repeated the most in a consecutive way

I'm kind of stuck, I don't know how to make the second loop to start 1 position above the first loop in Kotlin.
I have an array (named myArray) with 10 elements, I need to Write a Kotlin program that prints the number that has the most consecutive repeated number in the array and also prints the number of times it appears in the sequence.
The program must parse the array from left to right so that if two numbers meet the condition, the one that appears first from left to right will be printed.
Longest: 3
Number: 8
fun main() {
val myArray: IntArray = intArrayOf(1,2,2,4,5,6,7,8,8,8)
for((index , value) in myArray.withIndex()){
var inx = index + 1
var count = 0
var longest = 0
var number = 0
for((inx,element) in myArray.withIndex()) {
if(value == element ){
count+=
}
}
if(longest < count){
longest = count
number = value
}
}
}
I'm against just dropping answers, but it is quite late for me, so I'll leave this answer here and edit it tomorrow with more info on how each part works. I hope that maybe in the meanwhile it will help you to gain some idea to where you might be going wrong.
val results = mutableMapOf<Int, Int>()
(0..myArray.size - 2).forEach { index ->
val current = myArray[index]
if (current == myArray[index + 1]) {
results[current] = (results[current] ?: 1) + 1
}
}
val (max, occurrences) = results.maxByOrNull { it.value } ?: run { println("No multiple occurrences"); return }
println("Most common consecutive number $max, with $occurrences occurrences")
Alternatively if the intArray would be a list, or if we allowed to change it to a list myArray.toList(), you could replace the whole forEach loop with a zipWithNext. But I'm pretty sure that this is a HW question, so I doubt this is the expected way of solving it.
myList.zipWithNext { a, b ->
if (a == b) results[a] = (results[a] ?: 1) + 1
}

Deleting the maximum element in BST

Some of the code below seems too obvious, traversing the tree using its right most branch since that is where all the max values are.However, I don't understand a few things about this code I saw in Robert Sedgewick's Algorithms book.
public void deleteMax() {
if (isEmpty()) throw new NoSuchElementException("");
root = deleteMax(root);
assert check();
}
private Node deleteMax(Node x) {
if (x.right == null) return x.left;
x.right = deleteMax(x.right);
x.size = size(x.left) + size(x.right) + 1;
return x;
}
In the private method why do we return the left element if the right child of x is null ?From my understanding x would be the maximum if x has no right children and is the right most node we could go to.Also I don't understand when do we return x in the last line of the 2nd method.
If x doesn't have a right child then x is the maximum node. We "delete" it by returning x.left (the new max node). We return x after we've modified its right subtree.

get the number of parents that equal to the sum of children

i have a problem with the below code. i need to get the number of parents that it's value = to the sum of it's 2 children. example if parent value = 10 and its children are 2 and 8.
then i have to count this parent as 1. i need to check for all nodes in the tree.
this is what i tried to do: could you please advise:
int BinaryTree::numberOfSum (){
return numberOfSumImpl (root);
}
int BinaryTree::numberOfSumImpl (BTNode *rootNode, int el){
if(rootNode ==0) return 0;
int count=0;
if(rootNode->hasTwoChildren() || rootNode->isLeaf())
else if{
if (rootNode->info==el) return count=1;
return count + numberOfSumImpl(el,rootNode->left) + numberOfSumImpl(el,rootNode->right);
}
}
Many Thanks,
There seem to be a few problems with the call to numberOfSumImpl, as in the main function it is only called with one parameter, and in the recursive function it is called with two parameters, but with the order inversed. This code does not even compile!
Besides, the condition rootNode->hasTwoChildren() || rootNode->isLeaf()) looks strange and, having its body empty even more strange.
You did not post the definition of the BTNode, but looks like you are looking for something as
int BinaryTree::numberOfSumImpl (BTNode* p) {
if (not p) return 0;
int count;
if (p->hasTwoChildren() and p->info == p->left->info + p->right->info) {
count = 1;
} else {
count = 0;
}
return count + numberOfSumImpl(p->left) + numberOfSumImpl(p->right);
}
And this function would possibly be static.

Merge two Binary trees

public int merge(BNode node, int array[], int i) {
if (node == null)
return i;
//Flatten left subtree
i = merge(node.left, array, i);
//Get data from the current node
array[i] = node.value;
//Flatten right subtree
i = merge(node.right, array, i + 1);
return i;
}
I'm trying to merge two binary trees and retain the BST property.
The approach im using is to flatten the trees and store them in arrays.
The function above flattens my first tree and stores it in the array[] .
I want a function which would take the rootnode and blank array[] as input and RETURNS me a flattened tree with all the nodes into an array.
As you are doing, if you want to merge 2 binary search tree, the best way is:
1)Flatten trees into sorted lists.
2)Merge lists.
3)Transform the merged list to a BST.
You can implement the function you are looking for easily this way:
BinarySearchTree* arrayToTree(int arr[], int start, int end) {
if (start > end) return NULL;
int mid = start + (end - start) / 2;
BinarySearchTree *node = new BinarySearchTree(arr[mid]);
node->left = arrayToTree(arr, start, mid-1);
node->right = arrayToTree(arr, mid+1, end);
return node;
}
BinarySearchTree* arrayToTree(int arr[], int n) {
return arrayToTree(arr, 0, n-1);
}