diff --git a/Arrays/Arrays.ipynb b/Arrays/Arrays.ipynb index cbc2cc1..3c33a1c 100644 --- a/Arrays/Arrays.ipynb +++ b/Arrays/Arrays.ipynb @@ -26,7 +26,7 @@ "metadata": {}, "source": [ "* Array is a data structure used to store homogeneous elements at contiguous locations.\n", - "* One memory block is allocated for the entire array to hold the elements of the array. The array elements can be accessed in constant time by using the index of the parliculnr element as the subscript." + "* One memory block is allocated for the entire array to hold the elements of the array. The array elements can be accessed in constant time by using the index of the particular element as the subscript." ] }, { @@ -348,4 +348,4 @@ }, "nbformat": 4, "nbformat_minor": 2 -} +} \ No newline at end of file diff --git a/Dynamic Programming/LongestDecreasingSubsequence.py b/Dynamic Programming/LongestDecreasingSubsequence.py new file mode 100644 index 0000000..e3381e9 --- /dev/null +++ b/Dynamic Programming/LongestDecreasingSubsequence.py @@ -0,0 +1,27 @@ +def lds(arr, n): + + lds = [0] * n + max = 0 + + # Initialize LDS with 1 for all index + # The minimum LDS starting with any + # element is always 1 + for i in range(n): + lds[i] = 1 + + # Compute LDS from every index + # in bottom up manner + for i in range(1, n): + for j in range(i): + if (arr[i] < arr[j] and + lds[i] < lds[j] + 1): + lds[i] = lds[j] + 1 + + # Select the maximum + # of all the LDS values + for i in range(n): + if (max < lds[i]): + max = lds[i] + + # returns the length of the LDS + return max diff --git a/Dynamic Programming/mincoin.py b/Dynamic Programming/mincoin.py new file mode 100644 index 0000000..da90708 --- /dev/null +++ b/Dynamic Programming/mincoin.py @@ -0,0 +1,29 @@ +import sys + +def min_coins(coins,sum): + + # dp[i] will be storing the minimum + dp = [0 for i in range(sum + 1)] + + # Base case + dp[0] = 0 + + # Initialize values as Infinite + for i in range(1, sum + 1): + dp[i] = sys.maxsize + + # for all values from 1 to sum + for i in range(1, sum + 1): + for j in range(len(coins)): + if (coins[j] <= i): + res = dp[i - coins[j]] + if (res != sys.maxsize and res + 1 < dp[i]): + dp[i] = res + 1 + return dp[sum] + + +if __name__ == "__main__": + coins = [9, 6, 5, 1] + m = len(coins) + amount = 11 + print("Minimum coins:",min_coins(coins,amount)) \ No newline at end of file diff --git a/Queue/CicularQueue.py b/Queue/CicularQueue.py index 43f1086..59785c5 100644 --- a/Queue/CicularQueue.py +++ b/Queue/CicularQueue.py @@ -2,41 +2,49 @@ class CircularQueue(object): def __init__(self, limit = 10): - self.front = None - self.rear = None self.limit = limit - self.queue = [] + self.queue = [None for i in range(limit)] + self.front = self.rear = -1 # for printing the queue def __str__(self): - return ' '.join([str(i) for i in self.queue]) + if (self.rear >= self.front): + return ' '.join([str(self.queue[i]) for i in range(self.front, self.rear + 1)]) + + else: + q1 = ' '.join([str(self.queue[i]) for i in range(self.front, self.limit)]) + q2 = ' '.join([str(self.queue[i]) for i in range(0, self.rear + 1)]) + return q1 + ' ' + q2 # for checking if queue is empty def isEmpty(self): - return self.queue == [] + return self.front == -1 # for checking if the queue is full def isFull(self): - return len(self.queue) == self.limit + return (self.rear + 1) % self.limit == self.front - # for adding an element at the rear end + # for adding an element to the queue def enqueue(self, data): if self.isFull(): print('Queue is Full!') elif self.isEmpty(): - self.front = self.rear = 0 - self.queue.append(data) + self.front = 0 + self.rear = 0 + self.queue[self.rear] = data else: - self.rear += 1 - self.queue.append(data) + self.rear = (self.rear + 1) % self.limit + self.queue[self.rear] = data - # for deleting the deleting an element from front end + # for removing an element from the queue def dequeue(self): if self.isEmpty(): print('Queue is Empty!') + elif (self.front == self.rear): + self.front = -1 + self.rear = -1 else: - self.front += 1 - return self.queue.pop(0) + self.front = (self.front + 1) % self.limit if __name__ == '__main__': myCQ = CircularQueue(5) diff --git a/README.md b/README.md index def3d69..a19c7d8 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ Pune, Maharashtra, India.
* [Fibonacci Series](Dynamic%20Programming/P01_Fibonnaci.py) * [Longest Increasing Subsequence](Dynamic%20Programming/P02_LongestIncreasingSubsequence.py) * [Longest Continuous Odd Subsequence](Dynamic%20Programming/P03_LongestContinuousOddSubsequence.py) +* [Count Minimum Number of Coins](Dynamic%20Programming/mincoin.py) # Donation diff --git a/Sorting/Counting_sort.py b/Sorting/Counting_sort.py new file mode 100644 index 0000000..f537321 --- /dev/null +++ b/Sorting/Counting_sort.py @@ -0,0 +1,32 @@ +def countSort(arr): + + # The output character array that will have sorted arr + output = [0 for i in range(256)] + + # Create a count array to store count of inidividul + # characters and initialize count array as 0 + count = [0 for i in range(256)] + + # For storing the resulting answer since the + # string is immutable + ans = ["" for _ in arr] + + # Store count of each character + for i in arr: + count[ord(i)] += 1 + + # Change count[i] so that count[i] now contains actual + # position of this character in output array + for i in range(256): + count[i] += count[i-1] + + # Build the output character array + for i in range(len(arr)): + output[count[ord(arr[i])]-1] = arr[i] + count[ord(arr[i])] -= 1 + + # Copy the output array to arr, so that arr now + # contains sorted characters + for i in range(len(arr)): + ans[i] = output[i] + return ans diff --git a/Sorting/Radix_Sort.py b/Sorting/Radix_Sort.py new file mode 100644 index 0000000..f0c4184 --- /dev/null +++ b/Sorting/Radix_Sort.py @@ -0,0 +1,43 @@ +# Sorting Type: Radix +# +# Description: Radix sort is a sorting technique that +# sorts the elements by first grouping the individual +# digits of same place value. Then, sort the elements +# according to their increasing/decreasing order. + +from math import log10 +from random import randint + +def get_num(num, base, pos): + return (num // base ** pos) % base + +def prefix_sum(array): + for i in range(1, len(array)): + array[i] = array[i] + array[i-1] + return array + +def radixsort(l, base=10): + passes = int(log10(max(l))+1) + output = [0] * len(l) + + for pos in range(passes): + count = [0] * base + + for i in l: + digit = get_num(i, base, pos) + count[digit] +=1 + + count = prefix_sum(count) + + for i in reversed(l): + digit = get_num(i, base, pos) + count[digit] -= 1 + new_pos = count[digit] + output[new_pos] = i + + l = list(output) + return output + +l = [ randint(1, 99999) for x in range(100) ] +sorted = radixsort(l) +print(sorted) diff --git a/Sorting/heapsort.py b/Sorting/heapsort.py new file mode 100644 index 0000000..37b469c --- /dev/null +++ b/Sorting/heapsort.py @@ -0,0 +1,32 @@ +def heapify(nums, heap_size, root_index): + # Assume the index of the largest element is the root index + largest = root_index + left_child = (2 * root_index) + 1 + right_child = (2 * root_index) + 2 + + if left_child < heap_size and nums[left_child] > nums[largest]: + largest = left_child + + if right_child < heap_size and nums[right_child] > nums[largest]: + largest = right_child + + if largest != root_index: + nums[root_index], nums[largest] = nums[largest], nums[root_index] + # Heapify the new root element to ensure it's the largest + heapify(nums, heap_size, largest) + + +def heap_sort(nums): + n = len(nums) + + for i in range(n, -1, -1): + heapify(nums, n, i) + + # Move the root of the max heap to the end of + for i in range(n - 1, 0, -1): + nums[i], nums[0] = nums[0], nums[i] + heapify(nums, i, 0) + +random_list_of_nums = [35, 12, 43, 8, 51] +heap_sort(random_list_of_nums) +print(random_list_of_nums) diff --git a/Stack/Stack.ipynb b/Stack/Stack.ipynb index d494183..5fb3412 100644 --- a/Stack/Stack.ipynb +++ b/Stack/Stack.ipynb @@ -107,7 +107,7 @@ " \n", " # to check if stack is empty\n", " def isEmpty(self):\n", - " return len(self.stack) == []\n", + " return len(self.stack) == 0\n", " \n", " # for checking the size of stack\n", " def size(self):\n", diff --git a/Trees/BinarySearchTree.py b/Trees/BinarySearchTree.py index 2b6333a..ea0e15a 100644 --- a/Trees/BinarySearchTree.py +++ b/Trees/BinarySearchTree.py @@ -44,23 +44,45 @@ def minValueNode(self, node): return current - def delete(self, data): + def maxValueNode(self, node): + current = node + + # loop down to find the leftmost leaf + while(current.rightChild is not None): + current = current.rightChild + + return current + + + def delete(self, data,root): ''' For deleting the node ''' if self is None: return None # if current node's data is less than that of root node, then only search in left subtree else right subtree if data < self.data: - self.leftChild = self.leftChild.delete(data) + self.leftChild = self.leftChild.delete(data,root) elif data > self.data: - self.rightChild = self.rightChild.delete(data) + self.rightChild = self.rightChild.delete(data,root) else: # deleting node with one child if self.leftChild is None: + + if self == root: + temp = self.minValueNode(self.rightChild) + self.data = temp.data + self.rightChild = self.rightChild.delete(temp.data,root) + temp = self.rightChild self = None return temp elif self.rightChild is None: + + if self == root: + temp = self.maxValueNode(self.leftChild) + self.data = temp.data + self.leftChild = self.leftChild.delete(temp.data,root) + temp = self.leftChild self = None return temp @@ -69,7 +91,7 @@ def delete(self, data): # first get the inorder successor temp = self.minValueNode(self.rightChild) self.data = temp.data - self.rightChild = self.rightChild.delete(temp.data) + self.rightChild = self.rightChild.delete(temp.data,root) return self @@ -128,7 +150,7 @@ def insert(self, data): def delete(self, data): if self.root is not None: - return self.root.delete(data) + return self.root.delete(data,self.root) def find(self, data): if self.root: @@ -189,4 +211,4 @@ def postorder(self): print('\n\nAfter deleting 10') tree.delete(10) tree.inorder() - tree.preorder() + tree.preorder() \ No newline at end of file diff --git a/Trees/zigzagtraversal_iterative.py b/Trees/zigzagtraversal_iterative.py new file mode 100644 index 0000000..fa485b3 --- /dev/null +++ b/Trees/zigzagtraversal_iterative.py @@ -0,0 +1,75 @@ +class Node: + """ + A Node has data variable and pointers to its left and right nodes. + """ + + def __init__(self, data): + self.left = None + self.right = None + self.data = data + +def make_tree() -> Node: + root = Node(1) + root.left = Node(2) + root.right = Node(3) + root.left.left = Node(4) + root.left.right = Node(5) + return root + +def zigzag_iterative(root: Node): + """ + ZigZag traverse by iterative method: Print node left to right and right to left, alternatively. + """ + if root == None: + return + + # two stacks to store alternate levels + s1 = [] # For levels to be printed from right to left + s2 = [] # For levels to be printed from left to right + + # append first level to first stack 's1' + s1.append(root) + + # Keep printing while any of the stacks has some nodes + while not len(s1) == 0 or not len(s2) == 0: + + # Print nodes of current level from s1 and append nodes of next level to s2 + while not len(s1) == 0: + temp = s1[-1] + s1.pop() + print(temp.data, end = " ") + + # Note that is left is appended before right + if temp.left: + s2.append(temp.left) + if temp.right: + s2.append(temp.right) + + # Print nodes of current level from s2 and append nodes of next level to s1 + while not len(s2) == 0: + temp = s2[-1] + s2.pop() + print(temp.data, end = " ") + + # Note that is rightt is appended before left + if temp.right: + s1.append(temp.right) + if temp.left: + s1.append(temp.left) + +def main(): # Main function for testing. + """ + Create binary tree. + """ + root = make_tree() + print("\nZigzag order traversal(iterative) is: ") + zigzag_iterative(root) + print() + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + main() +