A visualization of an algorithm gives you a better understanding of its complexity and the steps involved in achieving a goal. When we talk about the best algorithms, best practice or performance of the program is everything based on the program’s execution time. And ultimate aim for every program is that it reduces is the execution of the program.

So, when we will say that this is the best algorithm for this process. It’s simple the algorithm that gives the result in a short time in all the cases. That is the suitable algorithm for that process.

So the next question is how to visualize the execution of the program?

Table of Contents

## Visualize the Execution Time

Let’s take this simple code.

class Main { public static void main(String[] args) { long startTime = System.currentTimeMillis(); System.out.println("Hello world!"); int a = 10; System.out.println(a); long endTime = System.currentTimeMillis(); System.out.println("Time is : " + (endTime-startTime) + " ms"); } }

Here, I’m just printing the numbers from 1 to 10000. That’s it. If you do not understand this code don’t worry. Just understand the logic I have written here. If I execute this code, this will pin the numbers from 1 to 10000. That’s it.

Now we want to understand that the execution time of this code.

`System.out.println("Time is : " + (endTime-startTime) + " ms");`

This line of code will give us the total execution time for this program. In the `startTime`

variable, I just captured the time when this method starts to execute.

And similarly, I’m just capturing the time when this program finished its execution,

Finally, by subtracting execution end time with start time, we will get the total time of the program execution. `System.currentTimeMillis()`

is the preferred method in Java to get the system time. Like this, in javascript, we can use `performance.now()`

. Similarly, your favorite language also will have some method or function to get the system time. You can use that to find the execution time of the program.

Now, we will take one problem statement and we will try to figure out the best algorithm for that problem.

## Problem Statement

Let’s take, we want to find out the number from some collection of numbers. So, for example, we have a number from 1 to 10000000. From this number collection, we have to find out 9999996. We knew that surely this number will be present between 1 to 10000000. But we just wanted to check by using our program.

## Solution #1

### Algorithm #1 to find the number

class Algorithm1 { public static void main(String[] args) { long startTime = System.currentTimeMillis(); int n = 10000000; int x = 9999996; int count = 0; for(int i = 1; i<= n; i++){ count++; if(i == x){ System.out.println("We found the value at " + count + " try"); } } long endTime = System.currentTimeMillis(); System.out.println("Time is : " + (endTime-startTime) + " ms"); } }

Here, my idea is I’m going to check the numbers one by one from this collection. If I found this value I’m just printing the message saying that “we found it on after this many intervals”. I’m just using one int variable to keep a check on the number of traces. We need to find this number.

This idea is nothing but it’s my algorithm for this process. Again I’m telling you that don’t worry about the code, just take an idea to implement logic.

Now let’s run this program and see how many traces we are taking to find this number and also see how long it taking to execute this program.

We found the value at 9999996 try Time is : 12 ms

See here, this algorithm finds the value after 9999996 traces. Means a 9999996 trace and the total time is taken for this process is 12 milliseconds. But algorithm execution time will not always see for everything. If you run this code next time we may end up with a different execution time. Even we are not changing anything into code. We are running the same code on the same machine but still, we are getting to different execution times. It’s quite common.

But if you see the number of traces it will be the same all the time. So for now, we can take this algorithm approximately taking 10 or 12 milliseconds to find this number.

Now, I’m just thinking is there any better way to do this job.

## Solution #2

There are two kinds of numbers. One is an odd number and another one is an even number. So, for example, if it’s an even number why should we check odd numbers. If I skip checking odd numbers I can save half of the trace, Right?

Let’s change my algorithm.

### Algorithm #2 to find the number

class Algorithm2 { public static void main(String[] args) { long startTime = System.currentTimeMillis(); int n = 10000000; int x = 9999996; int count = 0; boolean isEven = n%2 == 0; if(x>=0){ if(isEven){ for(int i = 2; i<= n; i+=2){ count++; if(i == x){ System.out.println("We found the value at " + count + " try"); } } } else{ for(int i = 1; i<= n; i+=2){ count++; if(i == x){ System.out.println("We found the value at " + count + " try"); } } } } long endTime = System.currentTimeMillis(); System.out.println("Time is : " + (endTime-startTime) + " ms"); } }

Now, this iteration starts from 2. I’m just increasing `i`

value by 2. So I will check the number which is we’re looking for is 2 or not. If no, I will move to 4 instead of 3. After 4, I will move to 6 without checking 5. Like this, I will skip all the odd numbers.

And if the number we’re looking for is odd then I will start the iteration from 1. So for the next iteration, it will be 3 and then 5 and then 7 like that.

Let’s run this code.

We found the value at 4999998 try Time is : 12 ms

See here. This algorithm finds the value after 4999998 tries. Seems like the number of tries reduced to be half of the time. And the total time execution for this process is 12 milliseconds.

Now, I’m pretty much happy with this. But still, I can think is there any better way to do this.

## Solution #3

After I spent some time I come up with another algorithm.

Now my idea is I’m splitting the collection of numbers into two off by identifying mid-element. It’s simple. The total number of elements divide by 2. It’s the middle element.

**[1,2,3,4, ……. 4999999] [5000001 ….. 10000000]**

**MID – 5000000**

If the value I’m looking for is lesser than the mid then there is no use if I travel the second off. Similarly, if the number we are looking for is greater than the mid then there is no use if I travel first off.

If we find the middle number from this number of collection between 1 to 10000000 mid will be 5000000.

So I’m checking the value we’re looking for is greater than 5000000 or less than 4000000. If it’s less than 5000000 then we have to go over the first stuff or else the second stuff.

In this case, the value we’re looking for is greater than 5000000, Right?

So we have to go over the second.

Again I’m finding the middle element from this collection of numbers. And again I’m doing the same process until I found the number.

I feel it’s a great idea. I look at them to find the elements from a large number of collections.

This is the implementation of this algorithm.

### Algorithm #3 to find the number

class Algorithm1 { static int count = 0; int findNumber(int[] collection, int start, int end, int x) { count++; if (end >= start) { int mid = start + (end - start) / 2; if (collection[mid] == x) return mid; if (collection[mid] > x) return findNumber(collection, start, mid - 1, x); return findNumber(collection, mid + 1, end, x); } return -1; } public static void main(String[] args) { Algorithm1 obj = new Algorithm1(); int[] numColl = new int[10000000]; for (int i = 1; i < numColl.length; i++) { numColl[i] = i; } int high = numColl.length - 1; long startTime = System.currentTimeMillis(); obj.findNumber(numColl, 0, high, 9999997); System.out.println("We found the values at " + count + " try"); long endTime = System.currentTimeMillis(); System.out.println("Total time :: " + (endTime - startTime) + " ms"); } }

Here, first I find the mid element then based on the mid element I am deciding whether I’m going to travel for the first off or second off to find the element. In this case, the number we are looking for is greater than the mid element.

So obviously we have to go for this second off. To travel the second off again I am calling the same method recursively by changing the starting number.

Now, the new collection is the complete second half of the ordered collection. Again I am limiting this collection into two off and doing the same process. At some point, I look at the number.

Let’s run this program and see the results.

We found the values at 22 try Total time :: 0 ms

See here, this algorithm finds the value on the 22nd try, and the total time taken for this process is not even 1 millisecond.

Now I’m pretty much happy with this performance. Still, we make it a better algorithm than this.

When we talk about the algorithm for some processes we can say that this is the best algorithm for this process.

Maybe today this is the best approach but tomorrow someone may discover a better algorithm than this algorithm for the same process. It’s like an endless process.

So put your effort to find the best algorithm for the process.