Motivation: Given an array of N numbers, you need to support two operations. Operation 1: find-min(i, j) = return the minimum value in array[i ... j]. Operation 2: update(i, v) = update the value at array[i] to v. Solve the problem for N <= 10^6, number of operations <= 10^6.
To solve the above problem, both the operations need to run in O(log N) time, but using an naive array gives O(N) run-time for operation 1 (and O(1) run-time for operation 2). So how do you solve the problem? Read on. :)
Video tutorial: This is a superb tutorial, giving the motivation, walking through example, and going step-by-step through the pseudocode.
Computers can only do a limited number of operations in a given time, usually about a billion operations per second. Here, by an individual operation, we mean addition, multiplication, assigning a value to a variable, etc. Hence, if we want our algorithm to finish executing in a second or so, then we need to make sure that the total number of operations we are asking it to do is less than 1 billion.
Estimating the exact run-time of an algorithm without implementing and executing it is very tough since it depends on so many factors - including the programming language being used, the compiler, the hardware of the computer itself, and more. Instead, what we'd like to do most of the time, is to estimate the run-time approximately.
Rate of growth
In algorithms, we focus on estimating the execution ...
Binary search: Video tutorial, Python code and extensions
In its simplest form, binary search is a method for quickly finding a specific target value in a sorted array. It begins by comparing the target value to the middle element of the array. Because the array is sorted, the comparison allows us to determine one-half of the array in which the target cannot lie. The search continues on the remaining half. By doing this repeatedly, we will eventually be left with a search space consisting of a single element, the target value.
No. The insertion first checks if the element is lesser than or greater than the root at each level. In short, if its in left sub-tree, it must have been smaller than the root. Irrespective of whether it ends up in left or right sub-tree.
Quick-sort: Video tutorial, pseudo-code (and in-place sorting)
We want to sort an array with n elements. Quick-sort does this by breaking up the array into non-overlapping segments, sorting them separately and then combining the results.
For instance, suppose we have a box with slips of paper with numbers between 100 and 300 to be sorted. We could first separate the slips into two bunches: those with values below 200 and those with values above 200. We can sort these bunches separately. Since all the values in the second bunch are larger than those in the first bunch, we can combine them easily into a single sorted bunch. (See Sorting | Online Study Material - IARCS for a great resource on this.)
Since examples are the best way to go understand dynamic programming, here are three more classic dynamic programming problems. Make sure you either solve the each problem or try at least for a few hours before reading the solution.
Counting paths in a grid
You have a rectangular grid of points with n rows and n columns. You start at the bottom left corner. At each step, you can either go up to the next point in the same column or right to the next point in the same row. How many such paths are there from the bottom left corner to the top right corner?
What if some points are deleted (that is, no path ca...