in a recursive method, find index of largest value in an array - java

//as the title says, i need to find the index of the largest value in an int //array, all of this needs to be done in one method this is what my helper //method looks like so far
it only returns last index in array i can easily return the max value but i cant figure out how to return the index of that value
//this is helper method
private int recursiveGetIndexOfLargest( int[] list, int count )
{
int index;
int[] y = list;
int temp = count - 1;
if( count > 0 )
{
index = Math.max( list[list.length - 1], list[temp] );
for(int x = 0; x < y.length; x++)
{
if(y[x] == index)
{
return x;
}
}
return recursiveGetIndexOfLargest(list, temp);
}
else
{
return -1;//empty list
}
}
this is method that calls helper
public int getIndexOfLargest()
{
return recursiveGetIndexOfLargest(list, count);
}

Try this one:
int recursiveGetIndexOfLargest(int[] list, int count)
{
if (count == list.length - 1) return count;
int index = recursiveGetIndexOfLargest(list, count + 1);
return list[count] > list[index] ? count : index;
}
int[] arr = {1, 5, 2, 3, 0};
System.out.println(recursiveGetIndexOfLargest(arr, 0));

int findLargestIndex(int[] array, int currentPos, int currentLargestIndex)
{
if(currentPos == array.length)
return currentLargestIndex;
if(array[currentPost] > array[currentLargestIndex]
return findLargestIndex(array,currentPos+1, currentPos);
else
return findLargestIndex(array,currentPos+1, currentLargestIndex);
}
It is actually a O(n) for loop done recursively.
You start it like this:
int result = findLargestIndex(array,0,0);
This would work but it will alter the array.
void findLargestIndex(int[] array, int currentPos)
{
if(currentPos == array.size()) return;
array[0] = (array[currentPos] < array[currenPos + 1] ? currentPos + 1 : currentPos;
findLargestIndex(int[] array, currentPos + 1);
}
The largest index will be storred at array[0] (This alters the array).
You simply start the function:
findLargestIndex(array,0);

Thank You tomse!!!!!!!!
the parameter count is actually the size of the array so i changed it a little to
private int recursiveGetIndexOfLargest( int[] list, int count )
{
int index;
int temp = count - 1;
if( temp == 0 )
{
return temp;
}
else
{
index = recursiveGetIndexOfLargest(list, temp);
return list[temp] > list[index] ? temp : index;
}
}
and now it works damn i wasted several hours failing

Related

Bug in recursive selection sort?

I am trying to implement selection sort recursively in java, but my program keeps throwing an ArrayIndexOutOfBounds exception. Not sure what I am doing wrong. Recursion is very hard for me. Please help! I am a beginner.
public static int[] selection(int[] array) {
return sRec(array, array.length - 1, 0);
}
private static int[] sRec(int[] array, int length, int current) {
if (length == current) { //last index of array = index we are at
return array; //it's sorted
}
else {
int index = findBig(array, length, current, 0);
int[] swapped = swap(array, index, length - current);
return sRec(swapped, length - 1, current);
}
}
private static int[] swap(int[] array, int index, int lastPos) {
int temp = array[lastPos];
array[lastPos] = array[index];
array[index] = array[temp];
return array;
}
private static int findBig(int[] array, int length, int current, int biggestIndex) {
if (length == current) {
return biggestIndex;
}
else if (array[biggestIndex] < array[current]) {
return findBig(array, length, current + 1, current);
}
else {
return findBig(array, length, current + 1, biggestIndex);
}
}
public static void main (String [] args) {
int[] array = {8,3,5,1,3};
int[] sorted = selection(array);
for (int i = 0; i < sorted.length; i++) {
System.out.print(sorted[i] + " ");
}
}
Try changing this in your Swap method :
int temp = array[lastPos];
array[lastPos] = array[index];
array[index] = array[temp];
return array;
to this :
int temp = array[lastPos];
array[lastPos] = array[index];
array[index] = temp;
return array;
You have already gotten the value you want to assign to the array , when you add that to the array it is searching in that specific index ,
For Example :
You wanted to enter the value 8 to your Array
Instead of doing
array[index] = 8
You were doing
array[index] = array[8]
That was causing your OutOfBounds Exception.
I tested your code and it did not sort even after having fixed the "Out Of bound Exception". I've changed your method findBig in order to make it work. The principle is :
If the length of the sub array is one (begin==end) then the biggest element is array[begin]
divide the array by half
Recusively find the index of the biggest element in the left side
Recursively find the index if the biggest element in the right side
Compare the biggest element of the left side with that of the right side of the array and return the index of the biggest of both.
This leads to the following code which sort the array in a decreasing order:
public class Sort {
public static int[] selection(int[] array) {
return sRec(array,0);
}
private static int[] sRec(int[] array, int current) {
if (current == array.length-1) { //last index of array = index we are at
return array; //it's sorted
}
else {
int indexOfBiggest = findBig(array, current,array.length-1);
int[] swapped = swap(array, indexOfBiggest, current );
return sRec(swapped, current+1);
}
}
private static int[] swap(int[] array, int index, int lastPos) {
int temp = array[lastPos];
array[lastPos] = array[index];
array[index] = temp;
return array;
}
private static int findBig(int[] array, int begin, int end) {
if (begin < end) {
int middle = (begin+end)/2;
int biggestLeft = findBig(array,begin,middle);
int biggestRight = findBig(array,middle+1,end);
if(array[biggestLeft] > array[biggestRight]) {
return biggestLeft;
}else {
return biggestRight;
}
}else {
return begin;
}
}
public static void main (String [] args) {
int[] array = {8,3,5,1,3};
// System.out.println(findBig(array,0,array.length-1));
int[] sorted = selection(array);
for (int i = 0; i < sorted.length; i++) {
System.out.print(sorted[i] + " ");
}
}
}

issues with codingbat maxMirror exercise

So basically, I've been going through these codingBat problems, and when I get really stuck, I usually check out the solution and trace the logic and that has helped me not get stuck on later problems which used similar ideas.
This max mirror problem is not like the others for me personally; I have no idea how to actually write the code to solve it, even forming the algorithm is kind of tricky for me
We'll say that a "mirror" section in an array is a group of contiguous elements such that somewhere in the array, the same group appears in reverse order. For example, the largest mirror section in {1, 2, 3, 8, 9, 3, 2, 1} is length 3 (the {1, 2, 3} part). Return the size of the largest mirror section found in the given array.
maxMirror({1, 2, 3, 8, 9, 3, 2, 1}) → 3
maxMirror({1, 2, 1, 4}) → 3
maxMirror({7, 1, 2, 9, 7, 2, 1}) → 2
Now, in terms of the algorithm, I sort of want to say something like, if we start by checking if the whole array is a mirror and then decrease the checked area size by 1 if it's not. But in terms of the pseudocode and the real code I have no idea.
My go to solution in cases like this where what your code should be doing is always doing it manually, then figuring out the essence of how it is that I am tackling the solution.
For this problem I found myself looking at possible subsets of the original array, then looking backwards through the original array to see if I can find that same subset again.
Next, I translated that into pseudocode,
for each segment in nums
check if nums contains segment backwards
Repeated, but this time with more implementation details worked out.
for each segment in nums, starting with the largest
reverse the segment
check if nums contains reversed segment
if it does, return the size of that segment
Next, find some likely candidates for methods in the pseudocode and write them. I chose to do this for "reverse" and "contains":
private int[] reverse(int[] nums) {
int[] rtn = new int[nums.length];
for (int pos = 0; pos < nums.length; pos++) {
rtn[nums.length - pos - 1] = nums[pos];
}
return rtn;
}
private boolean contains(int[] nums, int[] segment) {
for (int i = 0; i <= nums.length - segment.length; i++) {
boolean matches = true;
for (int j = 0; j < segment.length; j++) {
if (nums[i + j] != segment[j]) {
matches = false;
break;
}
}
if (matches) return true;
}
return false;
}
Finally, implement the rest:
public int maxMirror(int[] nums) {
for (int window = nums.length; window > 0; window--) {
for (int pos = 0; pos <= nums.length - window; pos++) {
int[] segment = new int[window];
for (int innerpos = 0; innerpos < window; innerpos++) {
segment[innerpos] = nums[pos + innerpos];
}
segment = reverse(segment);
if (contains(nums, segment)) {
return window;
}
}
}
return 0;
}
My irrelevant two cents....
public int maxMirror(int[] nums) {
// maximum mirror length found so far
int maxlen= 0;
// iterate through all possible mirror start indexes
for (int front = 0; front < nums.length; front++) {
// iterate through all possible mirror end indexes
for (int back = nums.length - 1; back >= front; back--) {
// this inner for-loop determines the mirror length given a fixed
// start and end index
int matchlen = 0;
Boolean match = (nums[front] == nums[back]);
// while there is a match
// 1. increment matchlen
// 2. keep on checking the proceeding indexes
while (match) {
matchlen++;
int front_index = front + matchlen;
int back_index = back - matchlen;
// A match requires
// 1. Thee indexes are in bounds
// 2. The values in num at the specified indexes are equal
match =
(front_index < nums.length) &&
(back_index >= 0) &&
(nums[front_index] == nums[back_index]);
}
// Replace the max mirror length with the new max if needed
if (matchlen > maxlen) maxlen = matchlen;
}
}
return maxlen;
}
Alternative solution designed to confuse you
public int maxMirror(int[] nums) {
return maxlen_all_f(nums, 0);
}
int maxlen_all_f(int [] nums, int f) {
return (f >= nums.length)
? 0
: max(
maxlen_for_start_f(nums, f, nums.length - 1),
maxlen_all_f(nums, f + 1)
);
}
int max(int a, int b){
return (a > b)
? a
: b;
}
int maxlen_for_start_f(int [] nums, int f, int b) {
return (b < f)
? 0
: max(
matchlen_f(nums, f, b),
maxlen_for_start_f(nums, f, b - 1)
);
}
int matchlen_f(int[] nums, int f, int b) {
return match_f(nums, f, b)
? 1 + matchlen_f(nums, f + 1, b - 1)
: 0;
}
Boolean match_f(int [] nums, int a, int b) {
return (a < nums.length && b >= 0) && (nums[a] == nums[b]);
}
The solution is simple rather than making it complex:
public static int maxMirror(int[] nums) {
final int len=nums.length;
int max=0;
if(len==0)
return max;
for(int i=0;i<len;i++)
{
int counter=0;
for(int j=(len-1);j>i;j--)
{
if(nums[i+counter]!=nums[j])
{
break;
}
counter++;
}
max=Math.max(max, counter);
}
if(max==1)
max=0;
return max;
}
This is definitely not the best solution in terms of performance. Any further improvements are invited.
public int maxMirror(int[] nums) {
int maxMirror=0;
for(int i=0;i<nums.length;i++)
{
int mirror=0;
int index=lastIndexOf(nums,nums[i]);
if(index!=-1){
mirror++;
for(int j=i+1;j<nums.length;j++)
{
if(index>=0&&existsInReverse(nums,index,nums[j]))
{
mirror++;
index--;
continue;
}
else
break;
}
if(mirror>maxMirror)
maxMirror=mirror;
}
}
return maxMirror;
}
int lastIndexOf(int[] nums,int num){
for(int i=nums.length-1;i>=0;i--)
{
if(nums[i]==num)
return i;
}
return -1;
}
boolean existsInReverse(int nums[],int startIndex,int num){
if(startIndex!=0&&(nums[startIndex-1]==num))
return true;
return false;
}
Here is my answer , Hope the comments explain it well :)
public int maxMirror(int[] nums) {
int max = 0;
// our largest mirror section found stored in max
//iterating array
for(int i=0;i<nums.length;i++){
int iterator = i; // iterator pointing at one element of array
int counter = 0;//counter to count the mirror elements
//Looping through for the iterator element
for(int j=nums.length-1;j>=i;j--){
//found match i.e mirror element
if(nums[iterator] == nums[j]){
iterator++; // match them until the match ends
counter++; // counting the matched ones
}
else{
//matching ended
if(counter >= max){//checking if previous count was lower than we got now
max = counter; // store the count of matched elements
}
counter = 0; // reset the counter
iterator = i; // reset the iterator for matching again
}
}
if(counter >= max){//checking if previous count was lower than we got now
max = counter;// store the count of matched elements at end of iteration
}
}
return max;//return count
}

Inserts an element into an array and returning the index reallocating the array in case of full array

I need to implement a method public int insert (int x) which inserts x in the "elements" array keeping it ordered, and returns the index to which it is entered;
if the element is already present, don't insert x and returns -1; if the array is full, it reallocates "elements" array in an array of double size and then insert the item x.
I know that there are probably similar methods already in the API but rather implement it.
I wrote this, but I do not know how to complete it...
public int insert(int x) {
if(numElements == elements.length) {
//code
}
int pos = binarySearch(x);
if(pos != -1)
return -1;
if(elements[-(pos + 1)] != null) {
for(int i = numElements; i >= -(pos + 1); i--)
elements[i + 1] = elements[i];
}
elements[-(pos + 1)] = x;
numElements++;
return -(pos + 1);
}
I do not know if what I wrote is correct, however, and I miss the case of a full array. Can anyone help me?
Thanks
private int binarySearch(int x) {
int inf = 0;
int sup = numElements - 1;
if(sup == -1 || elements[0] > x)
return -1;
if(elements[sup] < x)
return -(numElements + 1);
//Invariante di ciclo: se x in a, allora x in a[inf...sup]
while(inf <= sup) {
int i = (inf + sup) >>> 1; //divide per due
if(elements[i] > x)
sup = i - 1;
else if(elements[i] < x)
inf = i + 1;
else
return i;
}
return -(inf + 1);
}
Here you go.
What I did was create a new array that is twice the size and then use the System.arraycopy to move the existing elements. Lastly I assigned the reference of the enlarged array to the elements variable.
I used System.arraycopy because it is faster than a manually made loop-copy. It is using a native implementation by the JVM.
Also i replaced the check for array displacement and the for loop with System.arraycopy.
Also, the -(pos + 1) gives you a negative number.
public int insert(int x) {
if(numElements == elements.length) {
int[] enlargedElements = new int[elements.length * 2];
System.arraycopy(elements, 0, enlargedElements, 0, elements.length);
elements = enlargedElements;
}
int pos = binarySearch(x);
if(pos == -1)
return -1;
if(pos < numElements) {
System.arraycopy(elements, pos, elements, pos + 1, numElements - pos);
}
elements[pos] = x;
numElements++;
return pos;
}
private int binarySearch(int x) {
int inf = 0;
int sup = numElements - 1;
if(sup == -1 || elements[0] > x)
return 0;
if(elements[sup] < x)
return numElements;
//Invariante di ciclo: se x in a, allora x in a[inf...sup]
while(inf <= sup) {
int i = (inf + sup) >>> 1; //divide per due
if(elements[i] > x)
sup = i - 1;
else if(elements[i] < x)
inf = i + 1;
else
return -1;
}
return inf;
}

Finding Max value in an array using recursion

For one of the questions i was asked to solve, I found the max value of an array using a for loop, so i tried to find it using recursion and this is what I came up with:
public static int findMax(int[] a, int head, int last) {
int max = 0;
if (head == last) {
return a[head];
} else if (a[head] < a[last]) {
return findMax(a, head + 1, last);
} else {
return a[head];
}
}
So it works fine and gets the max value, but my question is : is it ok to have for the base case return a[head] and for the case when the value at the head is > the value at last?
You could just as easily do it with only one counter, just the index of the value you want to compare this time:
public static int findMax(int[] a, int index) {
if (index > 0) {
return Math.max(a[index], findMax(a, index-1))
} else {
return a[0];
}
}
This much better shows what is going on, and uses the default "recursion" layout, e.g. with a common base step. Initial call is by doing findMax(a, a.length-1).
It's actually much simpler than that. The base case is if you've reached the end of the array (the 'else' part of the ternary control block below). Otherwise you return the max of the current and the recursive call.
public static int findMax(int[] a) {
return findMax(a, 0);
}
private static int findMax(int[] a, int i) {
return i < a.length
? Math.max(a[i], findMax(a, i + 1))
: Integer.MIN_VALUE;
}
At each element, you return the larger of the current element, and all of the elements with a greater index. Integer.MIN_VALUE will be returned only on empty arrays. This runs in linear time.
I would solve this by dividing the array in to the half on each recursive call.
findMax(int[] data, int a, int b)
where a and b are array indices.
The stop condition is when b - a <= 1, then they are neighbours and the max is max(a,b);
The initial call:
findMax(int[] data, int 0, data.length -1);
This reduces the maximum recursion depth from N to log2(N).
But the search effort still stays O(N).
This would result in
int findMax(int[] data, int a, int b) {
if (b - a <= 1) {
return Math.max(data[a], data[b]);
} else {
int mid = (a+b) /2; // this can overflow for values near Integer.Max: can be solved by a + (b-a) / 2;
int leftMax = findMax(a, mid);
int rightMax = findMax(mid +1, b);
return Math.max(leftMax, rightMax);
}
}
I came across this thread and it helped me a lot. Attached is my complete code in both recursion and divide&conquer cases.
The run time for divide&conquer is slightly better than recursion.
//use divide and conquer.
public int findMaxDivideConquer(int[] arr){
return findMaxDivideConquerHelper(arr, 0, arr.length-1);
}
private int findMaxDivideConquerHelper(int[] arr, int start, int end){
//base case
if(end - start <= 1) return Math.max(arr[start], arr[end]);
//divide
int mid = start + ( end - start )/2;
int leftMax =findMaxDivideConquerHelper(arr, start, mid);
int rightMax =findMaxDivideConquerHelper(arr, mid+1, end);
//conquer
return Math.max( leftMax, rightMax );
}
// use recursion. return the max of the current and recursive call
public int findMaxRec(int[] arr){
return findMaxRec(arr, 0);
}
private int findMaxRec(int[] arr, int i){
if (i == arr.length) {
return Integer.MIN_VALUE;
}
return Math.max(arr[i], findMaxRec(arr, i+1));
}
What about this one ?
public static int maxElement(int[] a, int index, int max) {
int largest = max;
while (index < a.length-1) {
//If current is the first element then override largest
if (index == 0) {
largest = a[0];
}
if (largest < a[index+1]) {
largest = a[index+1];
System.out.println("New Largest : " + largest); //Just to track the change in largest value
}
maxElement(a,index+1,largest);
}
return largest;
}
I know its an old Thread, but maybe this helps!
public static int max(int[] a, int n) {
if(n < 0) {
return Integer.MIN_VALUE;
}
return Math.max(a[n-1], max(a, n - 2));
}
class Test
{
int high;
int arr[];
int n;
Test()
{
n=5;
arr = new int[n];
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
arr[3] = 40;
arr[4] = 50;
high = arr[0];
}
public static void main(String[] args)
{
Test t = new Test();
t.findHigh(0);
t.printHigh();
}
public void printHigh()
{
System.out.println("highest = "+high);
}
public void findHigh(int i)
{
if(i > n-1)
{
return;
}
if(arr[i] > high)
{
high = arr[i];
}
findHigh(i+1);
return;
}
}
You can do it recursively as follows.
Recurrent relation it something like this.
f(a,n) = a[n] if n == size
= f(a,n+1) if n != size
Implementation is as follows.
private static int getMaxRecursive(int[] arr,int pos) {
if(pos == (arr.length-1)) {
return arr[pos];
} else {
return Math.max(arr[pos], getMaxRecursive(arr, pos+1));
}
}
and call will look like this
int maxElement = getMaxRecursive(arr,0);
its not okay!
your code will not find the maximum element in the array, it will only return the element that has a higher value than the elements next to it, to solve this problem,the maximum value element in the range can be passed as argument for the recursive method.
private static int findMax(int[] a, int head, int last,int max) {
if(last == head) {
return max;
}
else if (a[head] > a[last]) {
max = a[head];
return findMax(a, head, last - 1, max);
} else {
max = a[last];
return findMax(a, head + 1, last, max);
}
}
Optimized solution
public class Test1 {
public static int findMax(int[] a, int head, int last) {
int max = 0, max1 = 0;
if (head == last) {
return a[head];
} else if (a[head] < a[last]) {
max = findMax(a, head + 1, last);
} else
max = findMax(a, head, last - 1);
if (max >= max1) {
max1 = max;
}
return max1;
}
public static void main(String[] args) {
int arr[] = {1001, 0, 2, 1002, 2500, 3, 1000, 7, 5, 100};
int i = findMax(arr, 0, 9);
System.out.println(i);
}
}
Thanks #Robert Columbia for the suggestion!
Update: This following function is going to recursively start from index 0 and it will keep adding to this index value till it's equal to the Length of the array, if it's more we should stop and return 0. Once we're doing that, we need to get the max of every two items in the array so, for example:
A = [1 , 2 , 3 ];
A[0] ( 1 ) vs A[1] ( 2 ) = 2
A[1] ( 2 ) vs A[2] ( 3 ) = 3
Max(2,3) = 3 ( The answer )
public int GetMax(int [] A, int index) {
index += 1;
if (index >= A.Length) return 0;
return Math.Max(A[index], GetMax(A, index + 1));
}
static int maximumOFArray(int[] array,int n) {
int max=Integer.MIN_VALUE;
if(n==1) return array[0];
else
max=maximumOFArray(array, --n);
max= max>array[n] ? max : array[n];
return max;
}
private static int getMax(int [] arr, int idx) {
if (idx==arr.length-1 ) return arr[idx];
return Math.max(arr[idx], getMax (arr,idx+1 ));
}
public class FindMaxArrayNumber {
public static int findByIteration(int[] array) {
int max = array[0];
for (int j : array) {
max = Math.max(j, max);
}
return max;
}
public static int findByRecursion(int[] array, int index) {
return index > 0
? Math.max(array[index], findByRecursion(array, index - 1))
: array[0];
}
public static void main(String[] args) {
int[] array = new int[]{1, 2, 12, 3, 4, 5, 6};
int maxNumberByIteration = findByIteration(array);
int maxNumberByRecursion = findByRecursion(array, array.length - 1);
System.out.println("maxNumberByIteration: " + maxNumberByIteration);
System.out.println("maxNumberByRecursion: " + maxNumberByRecursion);
// Outputs:
// maxNumberByIteration: 12
// maxNumberByRecursion: 12
}
}
int maximum = getMaxValue ( arr[arr.length - 1 ], arr, arr.length - 1 );
public static int getMaxValue ( int max, int arr[], int index )
{
if ( index < 0 )
return max;
if ( max < arr[index] )
max = arr[index];
return getMaxValue ( max, arr, index - 1 );
}
I felt that using a tracker for current maximum value would be good.

Implementing a binary insertion sort using binary search in Java

I'm having trouble combining these two algorithms together. I've been asked to modify Binary Search to return the index that an element should be inserted into an array. I've been then asked to implement a Binary Insertion Sort that uses my Binary Search to sort an array of randomly generated ints.
My Binary Search works the way it's supposed to, returning the correct index whenever I test it alone. I wrote out Binary Insertion Sort to get a feel for how it works, and got that to work as well. As soon as I combine the two together, it breaks. I know I'm implementing them incorrectly together, but I'm not sure where my problem lays.
Here's what I've got:
public class Assignment3
{
public static void main(String[] args)
{
int[] binary = { 1, 7, 4, 9, 10, 2, 6, 12, 3, 8, 5 };
ModifiedBinaryInsertionSort(binary);
}
static int ModifiedBinarySearch(int[] theArray, int theElement)
{
int leftIndex = 0;
int rightIndex = theArray.length - 1;
int middleIndex = 0;
while(leftIndex <= rightIndex)
{
middleIndex = (leftIndex + rightIndex) / 2;
if (theElement == theArray[middleIndex])
return middleIndex;
else if (theElement < theArray[middleIndex])
rightIndex = middleIndex - 1;
else
leftIndex = middleIndex + 1;
}
return middleIndex - 1;
}
static void ModifiedBinaryInsertionSort(int[] theArray)
{
int i = 0;
int[] returnArray = new int[theArray.length + 1];
for(i = 0; i < theArray.length; i++)
{
returnArray[ModifiedBinarySearch(theArray, theArray[i])] = theArray[i];
}
for(i = 0; i < theArray.length; i++)
{
System.out.print(returnArray[i] + " ");
}
}
}
The return value I get for this when I run it is 1 0 0 0 0 2 0 0 3 5 12. Any suggestions?
UPDATE: updated ModifiedBinaryInsertionSort
static void ModifiedBinaryInsertionSort(int[] theArray)
{
int index = 0;
int element = 0;
int[] returnArray = new int[theArray.length];
for (int i = 1; i < theArray.lenght - 1; i++)
{
element = theArray[i];
index = ModifiedBinarySearch(theArray, 0, i, element);
returnArray[i] = element;
while (index >= 0 && theArray[index] > element)
{
theArray[index + 1] = theArray[index];
index = index - 1;
}
returnArray[index + 1] = element;
}
}
Here is my method to sort an array of integers using binary search.
It modifies the array that is passed as argument.
public static void binaryInsertionSort(int[] a) {
if (a.length < 2)
return;
for (int i = 1; i < a.length; i++) {
int lowIndex = 0;
int highIndex = i;
int b = a[i];
//while loop for binary search
while(lowIndex < highIndex) {
int middle = lowIndex + (highIndex - lowIndex)/2; //avoid int overflow
if (b >= a[middle]) {
lowIndex = middle+1;
}
else {
highIndex = middle;
}
}
//replace elements of array
System.arraycopy(a, lowIndex, a, lowIndex+1, i-lowIndex);
a[lowIndex] = b;
}
}
How an insertion sort works is, it creates a new empty array B and, for each element in the unsorted array A, it binary searches into the section of B that has been built so far (From left to right), shifts all elements to the right of the location in B it choose one right and inserts the element in. So you are building up an at-all-times sorted array in B until it is the full size of B and contains everything in A.
Two things:
One, the binary search should be able to take an int startOfArray and an int endOfArray, and it will only binary search between those two points. This allows you to make it consider only the part of array B that is actually the sorted array.
Two, before inserting, you must move all elements one to the right before inserting into the gap you've made.
I realize this is old, but the answer to the question is that, perhaps a little unintuitively, "Middleindex - 1" will not be your insertion index in all cases.
If you run through a few cases on paper the problem should become apparent.
I have an extension method that solves this problem. To apply it to your situation, you would iterate through the existing list, inserting into an empty starting list.
public static void BinaryInsert<TItem, TKey>(this IList<TItem> list, TItem item, Func<TItem, TKey> sortfFunc)
where TKey : IComparable
{
if (list == null)
throw new ArgumentNullException("list");
int min = 0;
int max = list.Count - 1;
int index = 0;
TKey insertKey = sortfFunc(item);
while (min <= max)
{
index = (max + min) >> 1;
TItem value = list[index];
TKey compKey = sortfFunc(value);
int result = compKey.CompareTo(insertKey);
if (result == 0)
break;
if (result > 0)
max = index - 1;
else
min = index + 1;
}
if (index <= 0)
index = 0;
else if (index >= list.Count)
index = list.Count;
else
if (sortfFunc(list[index]).CompareTo(insertKey) < 0)
++index;
list.Insert(index, item);
}
Dude, I think you have some serious problem with your code. Unfortunately, you are missing the fruit (logic) of this algorithm. Your divine goal here is to get the index first, insertion is a cake walk, but index needs some sweat. Please don't see this algorithm unless you gave your best and desperate for it. Never give up, you already know the logic, your goal is to find it in you. Please let me know for any mistakes, discrepancies etc. Happy coding!!
public class Insertion {
private int[] a;
int n;
int c;
public Insertion()
{
a = new int[10];
n=0;
}
int find(int key)
{
int lowerbound = 0;
int upperbound = n-1;
while(true)
{
c = (lowerbound + upperbound)/2;
if(n==0)
return 0;
if(lowerbound>=upperbound)
{
if(a[c]<key)
return c++;
else
return c;
}
if(a[c]>key && a[c-1]<key)
return c;
else if (a[c]<key && a[c+1]>key)
return c++;
else
{
if(a[c]>key)
upperbound = c-1;
else
lowerbound = c+1;
}
}
}
void insert(int key)
{
find(key);
for(int k=n;k>c;k--)
{
a[k]=a[k-1];
}
a[c]=key;
n++;
}
void display()
{
for(int i=0;i<10;i++)
{
System.out.println(a[i]);
}
}
public static void main(String[] args)
{
Insertion i=new Insertion();
i.insert(56);
i.insert(1);
i.insert(78);
i.insert(3);
i.insert(4);
i.insert(200);
i.insert(6);
i.insert(7);
i.insert(1000);
i.insert(9);
i.display();
}
}

Categories

Resources