How do you loop through an array until you you reach the last 50 elements of your array then??
say I have this binary search code:
public class Binary
{
public static final int NOT_FOUND = -1;
public static <AnyType extends Comparable<? super AnyType>>
int binarySearch( AnyType [ ] a, AnyType x )
{
int low = 0;
int high = a.length - 1;
int mid;
while( low <= high )
{
mid = ( low + high ) / 2;
if( a[ mid ].compareTo( x ) < 0 )
low = mid + 1;
else if( a[ mid ].compareTo( x ) > 0 )
high = mid - 1;
else
return mid;
}
return NOT_FOUND; // NOT_FOUND = -1
}
// Test program
public static void main( String [ ] args )
{
int SIZE = 8;
Integer [ ] a = new Integer [ SIZE ];
for( int i = 0; i < SIZE; i++ )
a[ i ] = i * 2;
for( int i = 0; i < SIZE * 2; i++ )
System.out.println( "Found " + i + " at " +
binarySearch( a, i ) );
}
}
I would like to search the given array till I reach to the last 50 elements of this array, then the search is concluded with sequential look up of 50 elements.
My question is that how can I construct such a loop and how to jump to the method that does the linear search.
Before you calculate mid, do something like
if(high - low + 1 <= 50) return linearSearch(low, high, a, x);
Then your linearSearch just has to iterator from low to high to find x, or else return NOT_FOUND.
Related
My program runs, but it always gives the incorrect answer. Here are some sample runs:
Enter heap elements: 15 1 14 2 13 3 12 4 11 5 10 6 9 7 8
Enter d: 3
Output: Heap (d= 3): 1 2 3 4 5 6 7 15 11 13 10 14 9 12 8
It should be:
Enter heap elements: 15 1 14 2 13 3 12 4 11 5 10 6 9 7 8
Enter d: 3
Output: Heap (d=3): 1 3 4 2 7 15 12 14 11 5 10 6 9 13 8
import java.util.Scanner;
import java.util.Arrays;
public class D_heap<AnyType extends Comparable<? super AnyType>>
{
private int d;
private final static int DEFAULT_CAPACITY = 10;
private int currentSize;
private AnyType [ ] array; //
/**
* Construct the binary heap.
*/
public D_heap( )
{
this(2, DEFAULT_CAPACITY );
}
/**
* Construct the binary heap.
* #param capacity the capacity of the binary heap.
*/
public D_heap(int numChild )
{
this(numChild, DEFAULT_CAPACITY);
}
public D_heap(int numChild, int cap )
{
currentSize = 0;
d = numChild;
array = (AnyType[]) new Comparable[ cap + 1 ];
}
/**
* Construct the binary heap given an array of items.
*/
//public D_heap( AnyType [ ] items )
//{
// currentSize = items.length;
// array = (AnyType[]) new Comparable[ ( currentSize + 2 ) * 11 / 10 ];
// int i = 1;
// for( AnyType item : items )
// array[ i++ ] = item;
// buildHeap( );
//}
/**
* Insert into the priority queue, maintaining heap order.
* Duplicates are allowed.
* #param x the item to insert.
*/
public void insert( AnyType x )
{
if( currentSize == array.length - 1 )
enlargeArray( array.length * 2 + 1 );
// Percolate up
int hole = ++currentSize;
for( ; hole > 1 && x.compareTo( array[ getParent(hole)] ) < 0; hole = getParent(hole) )
array[ hole ] = array[getParent(hole)];
array[ hole ] = x;
}
private void enlargeArray( int newSize )
{
AnyType [] old = array;
array = (AnyType []) new Comparable[ newSize ];
for( int i = 0; i < old.length; i++ )
array[ i ] = old[ i ];
}
/**
* Find the smallest item in the priority queue.
* #return the smallest item, or throw an UnderflowException if empty.
*/
public AnyType findMin( )
{
if( isEmpty( ) )
throw new UnderflowException(" ");
return array[ 1 ];
}
/**
* Remove the smallest item from the priority queue.
* #return the smallest item, or throw an UnderflowException if empty.
*/
public AnyType deleteMin( )
{
if( isEmpty( ) )
throw new UnderflowException(" ");
AnyType minItem = findMin( );
array[ 1 ] = array[ currentSize-- ];
percolateDown( 1 );
return minItem;
}
/**
* Establish heap order property from an arbitrary
* arrangement of items. Runs in linear time.
*/
private void buildHeap( )
{
for( int i = currentSize / 2; i > 0; i-- )
percolateDown( i );
}
/**
* Test if the priority queue is logically empty.
* #return true if empty, false otherwise.
*/
public boolean isEmpty( )
{
return currentSize == 0;
}
/**
* Make the priority queue logically empty.
*/
public void makeEmpty( )
{
currentSize = 0;
}
public void print( )
{
for( int i = 0; i < currentSize; i++ )
System.out.printf("%d ", array[i+1]);
System.out.println();
}
/**
* Internal method to percolate down in the heap.
* #param hole the index at which the percolate begins.
*/
private void percolateDown( int hole )
{
int child = getChild(hole);
int tempChild = getChild (hole);
AnyType tmp = array[ hole ];
for( ; getChild(hole) <= currentSize; hole = child) {
child = getChild(hole);
tempChild = getChild(hole);
for(int i = 0; i < d && tempChild != currentSize; i++, tempChild++){
if(array[tempChild + 1].compareTo(array[child]) < 0){
child = tempChild + 1;
}
}
if (array[child].compareTo(tmp) < 0)
array[hole] = array[child];
else
break;
}
array[ hole ] = tmp;
}
// Test program
public static void main( String [ ] args )
{
Scanner in = new Scanner(System.in);
D_heap<Integer> h = new D_heap<Integer>();
System.out.print ("How many numeric values do you want to enter? ");
int num = in.nextInt();
System.out.print ("Enter heap elements: ");
for (int i = 1; i <= num; i++){
h.insert (in.nextInt());
}
System.out.print ("Enter d: ");
int d = in.nextInt();
System.out.printf ("Output: Heap (d= %d): ", d);
h.buildHeap();
h.print();
// Create the array of Strings containing the main menu options (Quit - option 0)
// Create the mainMenu object
String opts[] = {"Exit program", "Insert", "deleteMin", "Pick new d value", };
Menu mainMenu = new Menu(opts);
int opt = 0;
do {
opt = mainMenu.runMenu();
switch (opt) {
case 1:
System.out.print ("Enter element to insert: ");
int x = in.nextInt();
h.insert(x);
h.print();
break;
case 2:
h.deleteMin();
h.print();
break;
case 3:
System.out.print ("Enter new d: ");
d = in.nextInt();
h.buildHeap();
h.print();
break;
default:
System.out.println ("Thank you - Have a nice day!");
}
} while (opt != 0);
}
public int getChild( int p){
return d * (p - 1) + 2;
}
public int getParent (int c){
return (c - 2)/d + 1;
}
}
I don't know what it wrong with my code. Im supposed to put in an input file and sort the numbers from lowest to greatest. When i run the program it returns:Sorted array of 25 ints from P4input.txt after insertInOrder:
31 5 8 8 19 23 25 27 27 31 69 70 71 75 90 98 103 103 109 140 145 145 153 157 162
I don't know why the first number is out of order.
/* Project4.java InsertInOrder with bSearch optimization to compute insertion index */
import java.util.*;
import java.io.*;
public class Project4
{
static final int INITIAL_CAPACITY = 5;
public static void main( String args[] ) throws Exception
{
// ALWAYS TEST FIRST TO VERIFY USER PUT REQUIRED INPUT FILE NAME ON THE COMMAND LINE
if (args.length < 1 )
{
System.out.println("\nusage: C:\\> java Project4 <input filename>\n\n"); // i.e. C:\> java Project4 P4input.txt
System.exit(0);
}
// LOAD FILE INTO ARR USING INSERINORDER
Scanner infile = new Scanner( new File( args[0] ) );
int[] arr = new int[INITIAL_CAPACITY];
int count= 0;
while (infile.hasNextInt())
{
if ( count==arr.length )
arr = upSizeArr(arr);
insertInOrder( arr, count++, infile.nextInt() );
}
infile.close();
arr=trimArr(arr,count); // Now count == .length
System.out.println( "Sorted array of " + arr.length + " ints from " + args[0] + " after insertInOrder:" );
printArray( arr ); // we trimmed it thus count == length so we don't bother to pass in count
} // END MAIN
// ############################################################################################################
// USE AS IS - DO NOT MODIFY
static void printArray( int[] arr )
{
for( int i=0 ; i<arr.length ;++i )
System.out.print(arr[i] + " " );
System.out.println();
}
// USE AS IS - DO NOT MODIFY
static int[] upSizeArr( int[] fullArr )
{
int[] upSizedArr = new int[ fullArr.length * 2 ];
for ( int i=0; i<fullArr.length ; ++i )
upSizedArr[i] = fullArr[i];
return upSizedArr;
}
// USE AS IS - DO NOT MODIFY
static int[] trimArr( int[] oldArr, int count )
{
int[] trimmedArr = new int[ count ];
for ( int i=0; i<count ; ++i )
trimmedArr[i] = oldArr[i];
return trimmedArr;
}
// ############################################################################################################
static void insertInOrder( int[] arr, int count, int key )
{
int index=bSearch( arr, count, key ); // LEAVE THIS HERE
if (arr[arr.length - 1] == 0)
{
for (int i = count; i >= index + 1; i--)
{
arr[i] = arr[i - 1];
}
arr[index]=key; // LEAVE THIS HERE
}
}
static int bSearch(int[] a, int count, int key)
{
int hi = count-1;
int lo = 0;
int mid = 0;
if(hi == -1)
{
return lo;
}
else
{
mid = (hi+lo)/2;
}
while (lo <= hi)
{
if (key==a[mid])
{
return (mid+1);
}
else if (key < a[mid])
{
hi = mid-1;
mid = (hi+lo)/2;
}
else
{
lo = mid +1;
mid = (hi+lo)/2;
}
}
return (mid +1);
}
} // END PROJECT4
After reading a bit about heaps/priority queues, I recently made my own implementation of one. Afterwards I decided to compare the performance of my implementation to that of one which I found in a book, and the results are a bit confusing to me. It appears that there is a vast performance difference between the insert methods of the two implementations.
I used this code to test both heaps:
Random rnd = new Random();
long startTime = System.currentTimeMillis();
for(int i = 0; i < 1_000_000_0; i++) heap.insert(rnd.nextInt(1000));
System.out.println(System.currentTimeMillis() - startTime);
When I run this with my heap implementation, I get a result of around 600ms. When I run it with the book's implementation I get around 1900ms. How can the difference possibly be this big? Surely there must be something wrong with my implementation.
My implementation:
public class Heap<T extends Comparable<? super T>> {
private T[] array = (T[])new Comparable[10];
private int size = 0;
public void insert(T data) {
if(size+1 > array.length) expandArray();
array[size++] = data;
int pos = size-1;
T temp;
while(pos != 0 && array[pos].compareTo(array[pos/2]) < 0) {
temp = array[pos/2];
array[pos/2] = array[pos];
array[pos] = temp;
pos /= 2;
}
}
private void expandArray() {
T[] newArray = (T[])new Comparable[array.length*2];
for(int i = 0; i < array.length; i++)
newArray[i] = array[i];
array = newArray;
}
}
The book's implementation:
public class BooksHeap<AnyType extends Comparable<? super AnyType>>
{
private static final int DEFAULT_CAPACITY = 10;
private int currentSize;
private AnyType [ ] array;
public BinaryHeap( )
{
this( DEFAULT_CAPACITY );
}
public BinaryHeap( int capacity )
{
currentSize = 0;
array = (AnyType[]) new Comparable[ capacity + 1 ];
}
public void insert( AnyType x )
{
if( currentSize == array.length - 1 )
enlargeArray( array.length * 2 + 1 );
int hole = ++currentSize;
for( array[ 0 ] = x; x.compareTo( array[ hole / 2 ] ) < 0; hole /= 2 )
array[ hole ] = array[ hole / 2 ];
array[ hole ] = x;
}
private void enlargeArray( int newSize )
{
AnyType [] old = array;
array = (AnyType []) new Comparable[ newSize ];
for( int i = 0; i < old.length; i++ )
array[ i ] = old[ i ];
}
}
Edit: The book is "Data Structures and Algorithm Analysis in Java" by Mark Allen Weiss. Third edition. ISBN: 0-273-75211-1.
Here, your code measured with JMH:
#BenchmarkMode(Mode.AverageTime)
#OutputTimeUnit(TimeUnit.NANOSECONDS)
#OperationsPerInvocation(Measure.SIZE)
#Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
#Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
#State(Scope.Thread)
#Fork(1)
public class Measure
{
static final int SIZE = 4_000_000;
private Random rnd;
#Setup public void setup() {
rnd = new Random();
}
#Benchmark public Object heap() {
Heap<Integer> heap = new Heap<>();
for (int i = 0; i < SIZE; i++) heap.insert(rnd.nextInt());
return heap;
}
#Benchmark public Object booksHeap() {
BooksHeap<Integer> heap = new BooksHeap<>();
for (int i = 0; i < SIZE; i++) heap.insert(rnd.nextInt());
return heap;
}
public static class Heap<T extends Comparable<? super T>> {
private T[] array = (T[])new Comparable[10];
private int size = 0;
public void insert(T data) {
if(size+1 > array.length) expandArray();
array[size++] = data;
int pos = size-1;
T temp;
while(pos != 0 && array[pos].compareTo(array[pos/2]) < 0) {
temp = array[pos/2];
array[pos/2] = array[pos];
array[pos] = temp;
pos /= 2;
}
}
private void expandArray() {
T[] newArray = (T[])new Comparable[array.length*2];
for (int i = 0; i < array.length; i++)
newArray[i] = array[i];
array = newArray;
}
}
public static class BooksHeap<AnyType extends Comparable<? super AnyType>>
{
private static final int DEFAULT_CAPACITY = 10;
private int currentSize;
private AnyType [ ] array;
public BooksHeap()
{
this( DEFAULT_CAPACITY );
}
public BooksHeap( int capacity )
{
currentSize = 0;
array = (AnyType[]) new Comparable[ capacity + 1 ];
}
public void insert( AnyType x )
{
if( currentSize == array.length - 1 )
enlargeArray( array.length * 2 + 1 );
int hole = ++currentSize;
for( array[ 0 ] = x; x.compareTo( array[ hole / 2 ] ) < 0; hole /= 2 )
array[ hole ] = array[ hole / 2 ];
array[ hole ] = x;
}
private void enlargeArray( int newSize )
{
AnyType [] old = array;
array = (AnyType []) new Comparable[ newSize ];
for( int i = 0; i < old.length; i++ )
array[ i ] = old[ i ];
}
}
}
And the results:
Benchmark Mode Cnt Score Error Units
Measure.booksHeap avgt 5 62,712 ± 23,633 ns/op
Measure.heap avgt 5 62,784 ± 44,228 ns/op
They are exactly the same.
Moral of the exercise: don't think you can just write a loop and call it a benchmark. Measuring anything meaningful within a complex, self-optimizing runtime like HotSpot is an incredibly difficult challenge, best left to an expert benchmark tool like JMH.
As a side note, you could shave some 20% off your times (in both implementations) if you use System.arraycopy instead of the manual loop. Embarassingly, this wasn't my idea—IntelliJ IDEA's automatic inspection suggested that, and converted the code on its own :)
Taking the testing of implementations part of this question, how you are testing these implementations can explain a lot of any difference, consider this example. When I place your Heap in a class called OPHeap and the book's heap in a class called BookHeap and then test in this order:
import java.util.Random;
public class Test {
public static void main(String ...args) {
{
Random rnd = new Random();
BookHeap<Integer> heap = new BookHeap<Integer>();
long startTime = System.currentTimeMillis();
for(int i = 0; i < 1_000_000_0; i++) heap.insert(rnd.nextInt(1000));
System.out.println("Book's Heap:" + (System.currentTimeMillis() - startTime));
}
{
Random rnd = new Random();
OPHeap<Integer> heap = new OPHeap<Integer>();
long startTime = System.currentTimeMillis();
for(int i = 0; i < 1_000_000_0; i++) heap.insert(rnd.nextInt(1000));
System.out.println(" OP's Heap:" + (System.currentTimeMillis() - startTime));
}
}
}
I get this output:
Book's Heap:1924
OP's Heap:1171
However when I swap the order of the tests I get this output:
OP's Heap:1867
Book's Heap:1515
This is called "Warm-up" and you can learn a lot of ways to deal with it from this article. Also anytime you are using Random in a test you should define a seed value, so your "pseudo random" results are predictable.
I have given this a lot of thought and was unable to find the most optimal solution. I am preparing for technical interviews, but I haven't found very much stuff related to this question. My first step was to implement a naive O(n) algorithm that searches through the entire array to find the maximum integer. Now I know I can do much better than this, so I thought maybe there was a way to use Binary Search or take advantage of the fact that at least one half of the array is fully sorted. Maybe you could find the middle value and compare it to the start and end of the array.
Example:
[5, 7, 11, 1, 3] would return 11.
[7, 9, 15, 1, 3] would return 15.
In a sorted array (even rotated), you can be sure to use binary search (O(log2(n)).
/**
* Time complexity: O(log2(n))
* Space complexity: O(1)
*
* #param nums
* #return
*/
public int findMax(int[] nums) {
// binary search
int left = 0;
int right = nums.length - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[left] < nums[mid]) {
left = mid;
} else if (nums[left] > nums[mid]) {
right = mid - 1;
} else {
// subtility here if there are duplicate elements in the array.
// shift the left linearly
left = left + 1;
}
}
return nums[left];
}
You have to binary search in a clever way to achieve a O(lg n) bound. Observe that the element to the right of the max element is the min (or none if the array is not rotated at all). So do a regular binary search but check that the element at index mid is the max, if not compare the first and last elements in each of the left/right subarrays. If first<last in the left subarray, you know that the left subarray is sorted and go right, otherwise you go left.
Let's assume that array is called a and it has n elements.
/* check if not rotated at all */
int ans = INFINITY;
if(a[0] < a[n-1] || n == 1)
{ ans = a[n-1];
return;
}
/* array is certainly rotated */
int l = 0, r = n-1;
while(r - l > 5)
{ int m = (l + r) / 2;
if(a[m] > a[m+1]) { ans = a[m]; break; }
else
{ if(a[l] < a[m-1]) l = m+1;
else r = m-1;
}
}
/* check the remaining elements (at most 5) in a loop */
if(ans == INFINITY)
{ for(int i = l; i <= r; i++)
{ ans = max(ans, a[i]);
}
}
I've not tested this code. The reason i break when the number of elements is 5 or less is to be sure that number of elements in either subarray is at least 2 (so you can be sure that first and last are not the same element). You've got to try this yourself and fix it if there is anything to fix. Hope this helps.
Use modified binary search to eliminate half the sorted subarray (if there are two sorted subarrays remove the "lower" subarray) in each step while keeping track of a potentially updated maximum.
#include <iostream>
#include <cstdlib>
#include <vector>
int main(int argc, char** argv)
{
std::vector<int> nums;
for(int i = 1; i < argc; i++)
nums.push_back(atoi(argv[i]));
int start = 0;
int end = argc - 2;
int max = nums[start];
while(start <= end) {
int mid = (start + end) >> 1;
int cand;
if(nums[start] <= nums[mid]) {
start = mid + 1;
} else {
end = mid - 1;
}
cand = nums[mid];
if(cand > max)
max = cand;
}
std::cout << max << std::endl;
return 0;
}
Question : find largest in the rotated sorted array.The array don't have any duplicates:
Solution : Using Binary Search.
The Idea : Always remember in a Sorted Rotated Array, the largest element will always be on the left side of the array. Similarly, the smallest element will always be on the right side of the array.
The code is :
public class Test19 {
public static void main(String[] args) {
int[] a = { 5, 6, 1, 2, 3, 4 };
System.out.println(findLargestElement(a));
}
private static int findLargestElement(int[] a) {
int start = 0;
int last = a.length - 1;
while (start + 1 < last) {
int mid = (last - start) / 2 + start;
if (mid < start) {
mid = start;
}
if (mid > start) {
last = mid - 1;
} else {
mid--;
}
} // while
if (a[start] > a[last]) {
return a[start];
} else
return a[last];
}
}
The solution I've come up with is both compact and efficient.
It is basically a spin-off of the Binary Search Algorithm.
int maxFinder(int[] array, int start, int end)
{
//Compute the middle element
int mid = (start + end) / 2;
//return the first element if it's a single element array
//OR
//the boundary pair has been discovered.
if(array.length == 1 || array[mid] > array[mid + 1])
{return mid;}
//Basic Binary Search implementation
if(array[mid] < array[start])
{return maxFinder(array, start, mid - 1);}
else if(array[mid] > array[end])
{return maxFinder(array, mid + 1, end);}
//Return the last element if the array hasn't been rotated at all.
else
{return end;}
}
Speaking of using binary search to solve this problem at a time complexity of O(log2n). I would do as the following
#include<stdio.h>
#define ARRSIZE 200
int greatestElement(int* , int ) ;
int main() {
int arr[ARRSIZE] ;
int n ;
printf("Enter the number of elements you want to enter in the array!") ;
scanf("%d" , &n) ;
printf("Enter the array elements\n") ;
for(int i = 0 ; i < n ; i++) {
scanf("%d", &arr[i]) ;
}
printf("%d is the maximum element of the given array\n",greatestElement(arr,n)) ;
}
int greatestElement(int* arr, int n) {
int mid = 0 ;
int start = 0 , end = n-1 ;
while(start < end) {
mid = (start+end)/2 ;
if(mid < n-1 && arr[mid] >= arr[mid+1]) {
return arr[mid] ;
}
if(arr[start] > arr[mid]) {
end = mid - 1 ;
}
else {
start = mid + 1;
}
}
return arr[start] ;
}```
This question is so easy with another version of binary search:
int solve(vector<int>& a) {
int n = a.size();
int k=0;
for(int b=n/2; b>=1; b/=2)
{
while(k+b<n && a[k+b] >= a[0])
k += b;
}
return a[k];
}
I've struggling to implement a lexicographical merge sort method for the past couple of days. i've come up to a point were i get: ArrayIndexOutOfBounds error and i dont know why. i f anyone could take a look and tell me what might be wrong.i tried debugging but all the values seem correct.
Reply to aix: it happens at this point temp[index1] = array[min + index1] ;
These are the values at that exact time:
array :String[5] (5 entries originating from a text file)
min : 0
max : 1
size : 2
pivot : 0
temp : Comparable<T>[2] (both entries null)
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
at Merge.mergeSort(Merge.java:47)
at Merge.mergeSort(Merge.java:43)
at Merge.Sort(Merge.java:20)
at Sort.main(Sort.java:96)
Line 43:
mergeSort(array, pivot + 1, max) ;
Line 47:
temp[index1] = array[min + index1] ;
The code:
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class Merge
{
public static void Sort (LinkedList listIn, int size) throws Exception
{
String[] mArray = new String[size] ;
String textContent = null ;
File outputFile ;
//copy the list values in the array
for (int i = 0 ; i < size ; i++)
{
mArray [i] = listIn.get(i).printNode();
}
mergeSort(mArray, 0, mArray.length) ;
}
public static <T extends Comparable<? super T>> void mergeSort(T[] array, int min, int max)
{
T[] temp ;
int index1 ;
int left ;
int right ;
// if array is of size 1
if (min == max)
return ;
// find length and midpoint
int size = max - min + 1 ;
int pivot = (min + max) / 2 ;
temp = (T[]) (new Comparable[size]) ;
mergeSort(array, min, pivot) ;
mergeSort(array, pivot + 1, max) ;
for (index1 = 0 ; index1 < size ; index1++)
{
temp[index1] = array[min + index1] ;
}
left = 0 ;
right = pivot - min + 1 ;
for (index1 = 0 ; index1 < size ; index1++)
{
if (right <= max - min)
if (left <= pivot - min)
if (temp[left].compareTo(temp[right]) > 0)
array[index1 + min] = temp[right++] ;
else
array[index1 + min] = temp[left++] ;
else
array[index1 + min] = temp[right++] ;
else
array[index1 + min] = temp[left++] ;
}
}
}
Your Sort method is sending the wrong values when you first invoke merge. Change mergeSort(mArray, 0, mArray.length) to mergeSort(mArray, 0, mArray.length-1);