Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
REFFERED FROM
GeeksforGeeks
(http://www.geeksforgeeks.org/)
printLevelorder(tree) 1) Create an empty queue q 2) temp_node = root /*start from root*/ 3) Loop while temp_node is not NULL a) print temp_node->data. b) Enqueue temp_nodes children (first left then right children) to q c) Dequeue a node from q and assign its value to temp_node
printGivenLevel(tree, level, ltr) if tree is NULL then return; if level is 1, then print(tree->data); else if level greater than 1, then if(rtl) printGivenLevel(tree->right, level-1, ltr); printGivenLevel(tree->left, level-1, ltr); else printGivenLevel(tree->left, level-1, ltr); printGivenLevel(tree->right, level-1, ltr);
*/ while (k < m && l < n) { /* Print the first row from the remaining rows */ for (i = l; i < n; ++i) { printf("%d ", a[k][i]); } k++; /* Print the last column from the remaining columns */ for (i = k; i < m; ++i) { printf("%d ", a[i][n-1]); } n--; /* Print the last row from the remaining rows */ if ( k < m) { for (i = n-1; i >= l; --i) { printf("%d ", a[m-1][i]); } m--; } /* Print the first column from the remaining columns */ if (l < n) { for (i = m-1; i >= k; --i) { printf("%d ", a[i][l]); }
l++; } } }
/* A binary tree and a pointer struct node { int data; struct node* struct node* };
left; right;
struct node* newNode(int ); /* Function to find least comman ancestor of n1 and n2 */ int leastCommanAncestor(struct node* root, int n1, int n2) { /* If we have reached a leaf node then LCA doesn't exist If root->data is equal to any of the inputs then input is not valid. For example 20, 22 in the given figure */ if(root == NULL || root->data == n1 || root->data == n2) return -1; /* If any of the input nodes is child of the current node we have reached the LCA. For example, in the above figure if we want to calculate LCA of 12 and 14, recursion should terminate when we reach 8*/ if((root->right != NULL) && (root->right->data == n1 || root->right->data == n2)) return root->data; if((root->left != NULL) && (root->left->data == n1 || root->left->data == n2)) return root->data;
if(root->data > n1 && root->data < n2) return root->data; if(root->data > n1 && root->data > n2) return leastCommanAncestor(root->left, n1, n2); if(root->data < n1 && root->data < n2) return leastCommanAncestor(root->right, n1, n2); }
/* Function to reverse the linked list */ static void reverse(struct node** head_ref) { struct node* prev = NULL; struct node* current = *head_ref; struct node* next; while (current != NULL) { next = current->next; current->next = prev; prev = current; current = next; } *head_ref = prev; }
Recursive Method: 1) Divide the list in two parts - first node and rest of the linked list. 2) Call reverse for the rest of the linked list. 3) Link rest to first. 4) Fix head pointer
void recursiveReverse(struct node** head_ref) { struct node* first; struct node* rest; /* empty list */ if (*head_ref == NULL) return; /* suppose first = {1, 2, 3}, rest = {2, 3} */ first = *head_ref; rest = first->next;
/* List has only one node */ if (rest == NULL) return; /* reverse the rest list and put the first element at the end */ recursiveReverse(&rest); first->next->next = first; /* tricky step -- see the diagram */ first->next = NULL; /* fix the head pointer */ *head_ref = rest; }
enQueue(q, x) 1) While stack1 is not empty, push everything from satck1 to stack2. 2) Push x to stack1 (assuming size of stacks is unlimited). 3) Push everything back to stack1. dnQueue(q) 1) If stack1 is empty then error 2) Pop an item from stack1 and return it
Method 2 (By making deQueue operation costly) In this method, in en-queue operation, the new element is entered at the top of stack1. In de-queue operation, if stack2 is empty then all the elements are moved to stack2 and finally top of stack2 is returned.
enQueue(q, x) 1) Push x to stack1 (assuming size of stacks is unlimited). deQueue(q) 1) If both stacks are empty then error. 2) If stack2 is empty
9
While stack1 is not empty, push everything from satck1 to stack2. 3) Pop the element from stack2 and return it.
Method 2 is definitely better than method 1. Method 1 moves all the elements twice in enQueue operation, while method 2 (in deQueue operation) moves the elements once and moves elements only if stack2 empty
void insertAtBottom(struct sNode** top_ref, int item) { int temp; if(isEmpty(*top_ref)) { push(top_ref, item); } else { /* Hold all items in Function Call Stack until we reach end of the stack. When the stack becomes empty, the isEmpty(*top_ref) becomes true, the above if part is executed and the item is inserted at the bottom */ temp = pop(top_ref); insertAtBottom(top_ref, item); /* Once the item is inserted at the bottom, push all the items held in Function Call Stack */ push(top_ref, temp); } }
//Below is the function that reverses the given stack using insertAtBottom()
10
void reverse(struct sNode** top_ref) { int temp; if(!isEmpty(*top_ref)) { /* Hold all items in Function Call Stack until we reach end of the stack */ temp = pop(top_ref); reverse(top_ref); /* Insert all the items (held in Function Call Stack) one by one from the bottom to top. Every item is inserted at the bottom */ insertAtBottom(top_ref, temp); }
1) Get the Middle of the linked list and make it root. 2) Recursively do same for left half and right half. a) Get the middle of left half and make it left child of the root created in step 1. b) Get the middle of right half and make it right child of the root created in step 1.
Time complexity: O(nLogn) where n is the number of nodes in Linked List. Method 2 (Tricky) The method 1 constructs the tree from root to leaves. In this method, we construct from leaves to root. The idea is to insert nodes in BST in the same order as the appear in Doubly Linked List, so that the tree can be
11
constructed in O(n) time complexity. We first count the number of nodes in the given Linked List. Let the count be n. After counting nodes, we take left n/2 nodes and recursively construct the left subtree. After left subtree is constructed, we assign middle node to root and link the left subtree with root. Finally, we recursively construct the right subtree and link it with root. While constructing the BST, we also keep moving the list head pointer to next so that we have the appropriate pointer in each recursive call.
A O(n) time and O(1) extra space solution: The idea is similar to method 2 of this post. Let the two odd occurring numbers be x and y. We use bitwise XOR to get x and y. The first step is to do XOR of all elements present in array. XOR of all elements gives us XOR of x and y because of the following properties of XOR operation. 1) XOR of any number n with itself gives us 0, i.e., n ^ n = 0 2) XOR of any number n with 0 gives us n, i.e., n ^ 0 = n
12
3) XOR is cumulative and associative. So we have XOR of x and y after the first step. Let the value of XOR be xor2. Every set bit in xor2 indicates that the corresponding bits in x and y have values different from each other. For example, if x = 6 (0110) and y is 15 (1111), then xor2 will be (1001), the two set bits in xor2 indicate that the corresponding bits in x and y are different. In the second step, we pick a set bit of xor2 and divide array elements in two groups. Both x and y will go to different groups. In the following code, the rightmost set bit of xor2 is picked as it is easy to get rightmost set bit of a number. If we do XOR of all those elements of array which have the corresponding bit set (or 1), then we get the first odd number. And if we do XOR of all those elements which have the corresponding bit 0, then we get the other odd occurring number. This step works because of the same properties of XOR. All the occurrences of a number will go in same set. XOR of all occurrences of a number which occur even number number of times will result in 0 in its set. And the xor of a set will be one of the odd occurring elements
13
Hashing can also be used to solve this problem. Create an empty hash table HT. Traverse the array, use array elements as hash keys and enter them in HT. Traverse the array again look for value n + arr[i] in HT. Please write comments if you find any of the above codes/algorithms incorrect, or find other ways to solve the same problem.
14
min_ending_here is always 1 or some negative product ending with arr[i] */ for (int i = 0; i < n; i++) { /* If this element is positive, update max_ending_here. Update min_ending_here only if min_ending_here is negative */ if (arr[i] > 0) { max_ending_here = max_ending_here*arr[i]; min_ending_here = min (min_ending_here * arr[i],1); } /* If this element is 0, then the maximum product cannot end here, make both max_ending_here and min_ending_here 0 Assumption: Output is alway greater than or equal to 1. */ else if (arr[i] == 0) { max_ending_here = 1; min_ending_here = 1; }
/* If element is negative. This is tricky max_ending_here can either be 1 or positive. min_ending_here can either be 1 or negative. next min_ending_here will always be prev. max_ending_here * arr[i] next max_ending_here will be 1 if prev min_ending_here is 1, otherwise next max_ending_here will be prev min_ending_here * arr[i] */ else { int temp = max_ending_here; max_ending_here = max (min_ending_here * arr[i],1); min_ending_here = temp * arr[i]; } // update max_so_far, if needed if (max_so_far < max_ending_here) max_so_far = max_ending_here; } return max_so_far; }
15
Initialize: max_so_far = 0 max_ending_here = 0 Loop for each element of the array (a) max_ending_here = max_ending_here + a[i] (b) if(max_ending_here < 0) max_ending_here = 0 (c) if(max_so_far < max_ending_here) max_so_far = max_ending_here return max_so_far
Lets take the example: {-2, -3, 4, -1, -2, 1, 5, -3} max_so_far = max_ending_here = 0
16
for i=0, a[0] = -2 max_ending_here = max_ending_here + (-2) Set max_ending_here = 0 because max_ending_here < 0 for i=1, a[1] = -3 max_ending_here = max_ending_here + (-3) Set max_ending_here = 0 because max_ending_here < 0 for i=2, a[2] = 4 max_ending_here = max_ending_here + (4) max_ending_here = 4 max_so_far is updated to 4 because max_ending_here greater than max_so_far which was 0 till now for i=3, a[3] = -1 max_ending_here = max_ending_here + (-1) max_ending_here = 3 for i=4, a[4] = -2 max_ending_here = max_ending_here + (-2) max_ending_here = 1 for i=5, a[5] = 1 max_ending_here = max_ending_here + (1) max_ending_here = 2 for i=6, a[6] = 5 max_ending_here = max_ending_here + (5) max_ending_here = 7 max_so_far is updated to 7 because max_ending_here is greater than max_so_far for i=7, a[7] = -3 max_ending_here = max_ending_here + (-3) max_ending_here = 4
17
15)Find the maximum element in an array which is first increasing and then decreasing
Method 1 (Linear Search) We can traverse the array and keep track of maximum and element. And finally return the maximum element.
#include <stdio.h> int findMaximum(int arr[], int low, int high) { int max = arr[low]; int i; for (i = low; i <= high; i++)
18
{ if (arr[i] > max) max = arr[i]; } return max; } /* Driver program to check above functions */ int main() { int arr[] = {1, 30, 40, 50, 60, 70, 23, 20}; int n = sizeof(arr)/sizeof(arr[0]); printf("The maximum element is %d", findMaximum(arr, 0, n1)); getchar(); return 0; }
Time Complexity: O(n) Method 2 (Binary Search) We can modify the standard Binary Search algorithm for the given type of arrays. i) If the mid element is greater than both of its adjacent elements, then mid is the maximum. ii) If mid element is greater than its next element and smaller than the previous element then maximum lies on left side of mid. Example array: {3, 50, 10, 9, 7, 6} iii) If mid element is smaller than its next element and greater than the previous element then maximum lies on right side of mid. Example array: {2, 4, 6, 8, 10, 3, 1}
19