HasMaps and BigO
HasMaps and BigO Hacks
- Hacks
- Analyze the Big O complexity on Sorts.
- Build your own Hashmap. Make a HashMap to correspond to a Data Structure using a Collection.
- Extra, Practical learning
- Generate 5000 random Integers into an int Array
- Analyze the Big O complexity on Sorts.(Bubble sort)
- Analyze the Big O complexity on Sorts.(Selection Sort)
- Analyze the Big O complexity on Sorts.(Insertion Sort)
- Analyze the Big O complexity on Sorts.(Merge Sort)
- Hashmap(Binary Search vs. HashMap Lookup)
- HashMap Random Lookup
- Random Binary Search
Hacks
Analyze the Big O complexity on Sorts.
- Establish analytics including:time to sort, number of comparisons and number of swaps.- Average the results for each each Sort, run each at least 12 times and 5000 elements. You should throw out High and Low when doing analysis.
- Make your final/judgement on best sort: Number of Comparisons, Number of Swaps, Big O complexity, and Total Time.
Build your own Hashmap. Make a HashMap to correspond to a Data Structure using a Collection.
- Be sure to have 5000 records
- Perform analysis on Binary Search vs HashMap Lookup, try using random to search and find 100 keys in 5000 records. Perform 12 times and throw out high and low.
Extra, Practical learning
- Performing Iteration, Delete, and Add operations are another way to analyze Collection vs HashMap data structure.
- A HashMap and a Collection can be used in a Class, POJO and API.
- Make a Diagram on the Pros and Cons of Collection vs HashMap
import java.util.Random;
Random num = new Random();
int arr[] = new int[5000];
for (int i = 0; i < arr.length; i++) {
arr[i] = num.nextInt(); // storing random integers in an array
}
Analyze the Big O complexity on Sorts.(Bubble sort)
- Results:
| time to sort ( Nanoseconds ) | number of comparisons | number of swaps |
|---|---|---|
| 40948868 | 24995000 | 18711184 |
| 33597371 | 24995000 | 18711184 |
| 35568813 | 24995000 | 18711184 |
| 41071490 | 24995000 | 18711184 |
| 32054804 | 24995000 | 18711184 |
| 53361763 | 24995000 | 18711184 |
| 30094006 | 24995000 | 18711184 |
| 65122703 | 24995000 | 18711184 |
| 30226742 | 24995000 | 18711184 |
| 37281759 | 24995000 | 18711184 |
| 39752651 | 24995000 | 18711184 |
| 47037993 | 24995000 | 18711184 |
- Average Result ( throw out High and Low ) :
| time to sort ( Nanoseconds ) | number of comparisons | number of swaps |
|---|---|---|
| 39090225.4 ( 0.03909023 sec ) | 24995000 | 18711184 |
- Big O complexity:
- Worst case: O(n²).
- Best case: O(n). if array is already sorted.
int numOfComparisons = 0;
int numberOfSwaps = 0;
public static void bubbleSort (int[] data)
{
for(int i = 0;i < data.length; i++){
for(int j=0;j < data.length - 1; j++){
if(data[j] > data[j+1]){
int temp = arr[j];
data[j] = data[j+1];
data[j+1] = temp;
numberOfSwaps++;
}
numOfComparisons++;
}
}
}
//----------------------------------------------------------------------
int bubbleSortTester[] = new int[5000];
for (int i = 0; i < bubbleSortTester.length; i++) {
int num = arr[i];
bubbleSortTester[i] = num; // storing random integers in an array
}
long start = System.nanoTime();
bubbleSort(bubbleSortTester);
long finish = System.nanoTime();
long timeElapsed = finish - start;
System.out.println("Nanoseconds: " + timeElapsed);
System.out.println("number of comparisons: " + numOfComparisons);
System.out.println("number of Swaps: " + numberOfSwaps);
Analyze the Big O complexity on Sorts.(Selection Sort)
- Results:
| time to sort | number of comparisons | number of swaps |
|---|---|---|
| 25184109 | 12497500 | 5000 |
| 36724410 | 12497500 | 5000 |
| 19282268 | 12497500 | 5000 |
| 27323052 | 12497500 | 5000 |
| 32623821 | 12497500 | 5000 |
| 24525162 | 12497500 | 5000 |
| 21620519 | 12497500 | 5000 |
| 21299771 | 12497500 | 5000 |
| 20977239 | 12497500 | 5000 |
| 22184216 | 12497500 | 5000 |
| 25525767 | 12497500 | 5000 |
| 38868922 | 12497500 | 5000 |
- Average Result ( throw out High and Low ) :
| time to sort | number of comparisons | number of swaps |
|---|---|---|
| 25798806.6 ( 0.02579881 sec ) | 12497500 | 5000 |
- Big O complexity:
- Worst case: O(n²). Since we traverse through the remaining array to find the minimum for each element, the time complexity will become O(n²).
- Best case: O(n²). Even if the array has already been sorted, our algorithm looks for the minimum in the rest of the array. As a result, the best-case time complexity is the same as the worst-case.
int numOfComparisons = 0;
int numberOfSwaps = 0;
public static void selectionSort(int[] data)
{
for(int i=0;i<arr.length; i++) {
int minIndex = i;
for(int j=i+1;j<arr.length; j++) {
if(data[j]<data[minIndex]) {
minIndex = j;
}
numOfComparisons++;
}
int temp = data[i];
data[i] = data[minIndex];
data[minIndex] = temp;
numberOfSwaps++;
}
}
//---------------------------------------------------------------------------
int selectionSortTester[] = new int[5000];
for (int i = 0; i < selectionSortTester.length; i++) {
int num = arr[i];
selectionSortTester[i] = num; // storing random integers in an array
}
long start = System.nanoTime();
selectionSort(selectionSortTester);
long finish = System.nanoTime();
long timeElapsed = finish - start;
System.out.println("Nanoseconds: " + timeElapsed);
System.out.println("number of comparisons: " + numOfComparisons);
System.out.println("number of Swaps: " + numberOfSwaps);
Analyze the Big O complexity on Sorts.(Insertion Sort)
- Results:
| time to sort | number of comparisons | number of swaps |
|---|---|---|
| 12123437 | 6150953 | 6150953 |
| 13525997 | 6150953 | 6150953 |
| 17174613 | 6150953 | 6150953 |
| 19307095 | 6150953 | 6150953 |
| 16558676 | 6150953 | 6150953 |
| 15294102 | 6150953 | 6150953 |
| 12936251 | 6150953 | 6150953 |
| 28740336 | 6150953 | 6150953 |
| 14485925 | 6150953 | 6150953 |
| 15376347 | 6150953 | 6150953 |
| 15016661 | 6150953 | 6150953 |
| 17482556 | 6150953 | 6150953 |
- Average Result ( throw out High and Low ) :
| time to sort | number of comparisons | number of swaps |
|---|---|---|
| 15715822.3 ( 0.01571582 sec ) | 6150953 | 6150953 |
- Big O complexity:
- Worst case: O(n²). In a worst case situation, our array is sorted in descending order. So, for each element, we have to keep traversing and swapping elements to the left.
- Best case: O(n). In the best case, our array is already sorted. So for each element, we compare our current element to the element at the left only once. Since the order is correct, we don’t swap and move on to the next element. Hence the time complexity will be O(n).1.
int numOfComparisons = 0;
int numberOfSwaps = 0;
public static void insertionSort(int[] data)
{
for(int i = 1;i < data.length; i++) {
int j = i;
while(j > 0 && data[j] < data[j-1]) {
numOfComparisons++;
int temp = data[j];
data[j] = data[j-1];
data[j-1] = temp;
j--;
numberOfSwaps++;
}
}
}
//---------------------------------------------------------------------------
int InsertionSortTester[] = new int[5000];
for (int i = 0; i < InsertionSortTester.length; i++) {
int num = arr[i];
InsertionSortTester[i] = num; // storing random integers in an array
}
long start = System.nanoTime();
insertionSort(InsertionSortTester);
long finish = System.nanoTime();
long timeElapsed = finish - start;
System.out.println("Nanoseconds: " + timeElapsed);
System.out.println("number of comparisons: " + numOfComparisons);
System.out.println("number of Swaps: " + numberOfSwaps);
Analyze the Big O complexity on Sorts.(Merge Sort)
- Results:
| time to sort | number of comparisons | number of swaps |
|---|---|---|
| 9317561 | 55175 | 61808 |
| 12992589 | 55175 | 61808 |
| 19746831 | 55175 | 61808 |
| 12912218 | 55175 | 61808 |
| 12534219 | 55175 | 61808 |
| 16034847 | 55175 | 61808 |
| 17103831 | 55175 | 61808 |
| 18385908 | 55175 | 61808 |
| 19866444 | 55175 | 61808 |
| 10257987 | 55175 | 61808 |
| 16992695 | 55175 | 61808 |
| 11263257 | 55175 | 61808 |
- Average Result ( throw out High and Low ) :
| time to sort | number of comparisons | number of swaps |
|---|---|---|
| 14822438.2 ( 0.01482244 sec ) | 55175 | 61808 |
- Big O complexity:
- Worst case: O(nlogn). The worst-case time complexity is the same as the best case.
- Best case: O(nlogn). We are dividing the array into two sub-arrays recursively, which will cost a time complexity of O(logn). For each function call, we are calling the partition function, which costs O(n) time complexity. Hence the total time complexity is O(nlogn).
int numOfComparisons = 0;
int numberOfSwaps = 0;
public void merge(int data[], int l, int m, int r) {
int n1 = m-l+1;
int n2 = r-m;
int[] L = new int[n1];
int[] R = new int[n2];
for(int i = 0;i < n1; i++) {
L[i] = data[l+i];
}
for(int i = 0;i < n2; i++) {
R[i] = data[m+1+i];
}
int i = 0, j = 0, k =l;
while(i < n1 && j < n2) {
if(L[i] <= R[j]) {
data[k++] = L[i++];
numOfComparisons++;
numberOfSwaps++;
}
else {
data[k++] = R[j++];
numOfComparisons++;
numberOfSwaps++;
}
}
while(i < n1) {
data[k++] = L[i++];
numberOfSwaps++;
}
while(j < n2) {
data[k++] = R[j++];
numberOfSwaps++;
}
}
public void mergeSort(int data[], int l, int r) {
if (l < r) {
int m = l + (r-l)/2;
mergeSort(data, l, m);
mergeSort(data , m+1, r);
merge(data, l, m, r);
}
}
//---------------------------------------------------------------------------
int[] MergeSortTester = new int[5000];
for (int i = 0; i < MergeSortTester.length; i++) {
int num = arr[i];
MergeSortTester[i] = num;
}
long start = System.nanoTime();
mergeSort(MergeSortTester, 0, MergeSortTester.length-1);
long finish = System.nanoTime();
long timeElapsed = finish - start;
System.out.println("Nanoseconds: " + timeElapsed);
System.out.println("number of comparisons: " + numOfComparisons);
System.out.println("number of Swaps: " + numberOfSwaps);
| Sort | time to sort | number of comparisons | number of swaps |
|---|---|---|---|
| Bubble | 39090225.4 ( 0.03909023 sec ) | 24995000 | 18711184 |
| Selection | 25798806.6 ( 0.02579881 sec ) | 12497500 | 5000 |
| Insertion | 15715822.3 ( 0.01571582 sec ) | 6150953 | 6150953 |
| Merge | 14822438.2 ( 0.01482244 sec ) | 55175 | 61808 |
import java.util.Random;
int[] randomKey = new int[100];
for(int i =0; i<100; i++){
int random = (int)(Math.random()*5000); //random search by 100 keys
randomKey[i] = random;
}
Map<String, Integer> myHashMap = new HashMap<>();
for (int i = 0; i < 5000; i++) {
myHashMap.put("apple" + i, i); // storing random integers
}
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
long start = System.nanoTime();
for(int i =0; i<100; i++){
myHashMap.get("apple" + randomKey[i]);
}
long finish = System.nanoTime();
long timeElapsed = finish - start;
System.out.println();
System.out.println("Nanoseconds: " + timeElapsed);
Random Binary Search
- Results:
| time to search 100 random keys ( Nanoseconds ) |
|---|
| 10744880 |
| 14870334 |
| 17765997 |
| 15532206 |
| 19414759 |
| 16884201 |
| 13640847 |
| 22480933 |
| 14822539 |
| 17184193 |
| 24756768 |
| 14169391 |
- Average Result ( throw out High and Low ) :
| time to search |
|---|
| 16676540 ( 0.01667654 sec ) |
- The time complexity of binary search is O(log n)
int binarySearchTester[] = new int[5000];
for (int i = 0; i < binarySearchTester.length; i++) {
binarySearchTester[i] = i; // storing random integers in an array
}
public static int binarySearch(int numArray[], int number_to_search_for) {
int low = 0;
int high = numArray.length - 1;
while (low <= high){
int middleIndex = (low + high) / 2;
if (number_to_search_for == numArray[middleIndex]){
return middleIndex;
}
if (number_to_search_for < numArray[middleIndex]){
high = middleIndex - 1;
}
if (number_to_search_for > numArray[middleIndex]){
low = middleIndex + 1;
}
}
return -1;
}
//---------------------------------------------------------------------------
long start = System.nanoTime();
for(int i =0; i<100; i++){
binarySearch(binarySearchTester, binarySearchTester[randomKey[i]]);
}
long finish = System.nanoTime();
long timeElapsed = finish - start;
System.out.println();
System.out.println("Nanoseconds: " + timeElapsed);
| Binary Search vs HashMap Lookup | Time to Search |
|---|---|
| HashMap Lookup | 12075520.2 ( 0.01207552 sec ) |
| Binary Search | 16676540 ( 0.01667654 sec ) |
-
Result: HashMap Lookup is faster than Binary Search
-
Reason: Because Hash algorithms are O(1) while binary search is O(log n).