I have an array, let's say: LRU_frame[] = {4,1,0,3}
I have a random() function that spits out a random number. If the random number n is contained in the array LRU_frame, then, n should be on LRU_frame[0] and everything else must be shifted down accordingly.
For example if random() gives me a 0, the new LRU_frame[] = {0,4,1,3}
Another example, if random() gives me a 3, the new LRU_frame[] = {3,4,1,0}
How do I do this for any Array size with any number of elements in it?
I know how to shift arrays by adding a new element on LRU_frame[0] but have no idea on how to re-organize the array like I need.
This is the code I have so far and let's assume char a is the random number(casted into char) to use and re-organize the array.
public static void LRU_shiftPageRef(char a) {
for (int i = (LRU_frame.length - 2); i >= 0; i--) {
LRU_frame[i + 1] = LRU_frame[i];
}
LRU_frame[0] = a;
}
You have a good idea, you only need to find the position of the a element in the array and start the cycle from it, instead of LRU_frame.length.
int index = -1;
// find the positon of 'a' in the array
for (int i = 0; i <= (LRU_frame.length - 1); i++) {
if (LRU_frame[i] == a) {
index = i;
break;
}
}
// if it is present, do roughly the same thing as before
if (index > -1) {
for (int i = (index - 1); i >= 0; i--) {
LRU_frame[i + 1] = LRU_frame[i];
}
LRU_frame[0] = a;
}
However if you can use ArrayLists it gets much easier.
// declaration
ArrayList<Integer> LRU_frame = new ArrayList<Integer>();
...
if (LRU_frame.contains(a)) {
LRU_frame.remove((Integer) a);
LRU_frame.add(0, a);
}
I think this could be the sort of thing you are after:
public static void LRU_shiftPageRef(char a) {
int index = indexOf(a);
if (index == -1) {
//not currently in array so create a new array 1 bigger than existing with a in newArray[0] or ignore depending on functionality required.
} else if (index > 0) {
//Set first entry as a and shift existing entries right
char insertChar = a;
char nextChar = LRU_frame[0];
for (int i =0; i < index; i++) {
LRU_frame[i] = insertChar;
insertChar = nextChar;
nextChar = LRU_frame[i+1];
}
LRU_frame[index] = insertChar;
} else {
//do nothing a is already at first position
}
}
public static int indexOf(char a) {
for (int i=0; i < LRU_frame.length; i++) {
if (LRU_frame[i] == a) {
return i;
}
}
return -1;
}
Use Arrays.sort(LRU_frame); to sort the entire array, or Arrays.sort(LRU_frame, fromIndex, toIndex)); to sort part of the array.
Arrays class has other useful methods like copyOfRange.
Related
Need to write an Algo to find Anagram of given string at a given index in lexicographically sorted order. For example:
Consider a String: ABC then all anagrams are in sorted order: ABC ACB
BAC BCA CAB CBA. So, for index 5 value is: CAB. Also, consider the case of duplicates like for AADFS anagram would be DFASA at index 32
To do this I have written Algo but I think there should be something less complex than this.
import java.util.*;
public class Anagram {
static class Word {
Character c;
int count;
Word(Character c, int count) {
this.c = c;
this.count = count;
}
}
public static void main(String[] args) {
System.out.println(findAnagram("aadfs", 32));
}
private static String findAnagram(String word, int index) {
// starting with 0 that's y.
index--;
char[] array = word.toCharArray();
List<Character> chars = new ArrayList<>();
for (int i = 0; i < array.length; i++) {
chars.add(array[i]);
}
// Sort List
Collections.sort(chars);
// To maintain duplicates
List<Word> words = new ArrayList<>();
Character temp = chars.get(0);
int count = 1;
int total = chars.size();
for (int i = 1; i < chars.size(); i++) {
if (temp == chars.get(i)) {
count++;
} else {
words.add(new Word(temp, count));
count = 1;
temp = chars.get(i);
}
}
words.add(new Word(temp, count));
String anagram = "";
while (index > 0) {
Word selectedWord = null;
// find best index
int value = 0;
for (int i = 0; i < words.size(); i++) {
int com = combination(words, i, total);
if (index < value + com) {
index -= value;
if (words.get(i).count == 1) {
selectedWord = words.remove(i);
} else {
words.get(i).count--;
selectedWord = words.get(i);
}
break;
}
value += com;
}
anagram += selectedWord.c;
total--;
}
// put remaining in series
for (int i = 0; i < words.size(); i++) {
for (int j = 0; j < words.get(i).count; j++) {
anagram += words.get(i).c;
}
}
return anagram;
}
private static int combination(List<Word> words, int index, int total) {
int value = permutation(total - 1);
for (int i = 0; i < words.size(); i++) {
if (i == index) {
int v = words.get(i).count - 1;
if (v > 0) {
value /= permutation(v);
}
} else {
value /= permutation(words.get(i).count);
}
}
return value;
}
private static int permutation(int i) {
if (i == 1) {
return 1;
}
return i * permutation(i - 1);
}
}
Can someone help me with less complex logic.
I write the following code to solve your problem.
I assume that the given String is sorted.
The permutations(String prefix, char[] word, ArrayList permutations_list) function generates all possible permutations of the given string without duplicates and store them in a list named permutations_list. Thus, the word: permutations_list.get(index -1) is the desired output.
For example, assume that someone gives us the word "aab".
We have to solve this problem recursively:
Problem 1: permutations("","aab").
That means that we have to solve the problem:
Problem 2: permutations("a","ab").
String "ab" has only two letters, therefore the possible permutations are "ab" and "ba". Hence, we store in permutations_list the words "aab" and "aba".
Problem 2 has been solved. Now we go back to problem 1.
We swap the first "a" and the second "a" and we realize that these letters are the same. So we skip this case(we avoid duplicates).
Next, we swap the first "a" and "b". Now, the problem 1 has changed and we want to solve the new one:
Problem 3: permutations("","baa").
The next step is to solve the following problem:
Problem 4: permutations("b","aa").
String "aa" has only two same letters, therefore there is one possible permutation "aa". Hence, we store in permutations_list the word "baa"
Problem 4 has been solved. Finally, we go back to problem 3 and problem 3 has been solved. The final permutations_list contains "aab", "aba" and "baa".
Hence, findAnagram("aab", 2) returns the word "aba".
import java.util.ArrayList;
import java.util.Arrays;
public class AnagramProblem {
public static void main(String args[]) {
System.out.println(findAnagram("aadfs",32));
}
public static String findAnagram(String word, int index) {
ArrayList<String> permutations_list = new ArrayList<String>();
permutations("",word.toCharArray(), permutations_list);
return permutations_list.get(index - 1);
}
public static void permutations(String prefix, char[] word, ArrayList<String> permutations_list) {
boolean duplicate = false;
if (word.length==2 && word[0]!=word[1]) {
String permutation1 = prefix + String.valueOf(word[0]) + String.valueOf(word[1]);
permutations_list.add(permutation1);
String permutation2 = prefix + String.valueOf(word[1]) + String.valueOf(word[0]);
permutations_list.add(permutation2);
return;
}
else if (word.length==2 && word[0]==word[1]) {
String permutation = prefix + String.valueOf(word[0]) + String.valueOf(word[1]);
permutations_list.add(permutation);
return;
}
for (int i=0; i < word.length; i++) {
if (!duplicate) {
permutations(prefix + word[0], new String(word).substring(1,word.length).toCharArray(), permutations_list);
}
if (i < word.length - 1) {
char temp = word[0];
word[0] = word[i+1];
word[i+1] = temp;
}
if (i < word.length - 1 && word[0]==word[i+1]) duplicate = true;
else duplicate = false;
}
}
}
I think your problem will become a lot simpler if you considerate generating the anagrams in alphabetical order, so you don't have to sort them afterwards.
The following code (from Generating all permutations of a given string) generates all permutations of a String. The order of these permutations are given by the initial order of the input String. If you sort the String beforehand, the anagrams will thus be added in sorted order.
to prevent duplicates, you can simply maintain a Set of Strings you have already added. If this Set does not contain the anagram you're about to add, then you can safely add it to the list of anagrams.
Here is the code for the solution i described. I hope you find it to be simpler than your solution.
public class Anagrams {
private List<String> sortedAnagrams;
private Set<String> handledStrings;
public static void main(String args[]) {
Anagrams anagrams = new Anagrams();
List<String> list = anagrams.permutations(sort("AASDF"));
System.out.println(list.get(31));
}
public List<String> permutations(String str) {
handledStrings = new HashSet<String>();
sortedAnagrams = new ArrayList<String>();
permutation("", str);
return sortedAnagrams;
}
private void permutation(String prefix, String str) {
int n = str.length();
if (n == 0){
if(! handledStrings.contains(prefix)){
//System.out.println(prefix);
sortedAnagrams.add(prefix);
handledStrings.add(prefix);
}
}
else {
for (int i = 0; i < n; i++)
permutation(prefix + str.charAt(i), str.substring(0, i) + str.substring(i + 1, n));
}
}
public static String sort(String str) {
char[] arr = str.toCharArray();
Arrays.sort(arr);
return new String(arr);
}
}
If you create a "next permutation" method which alters an array to its next lexicographical permutation, then your base logic could be to just invoke that method n-1 times in a loop.
There's a nice description with code that can be found here. Here's both the basic pseudocode and an example in Java adapted from that page.
/*
1. Find largest index i such that array[i − 1] < array[i].
(If no such i exists, then this is already the last permutation.)
2. Find largest index j such that j ≥ i and array[j] > array[i − 1].
3. Swap array[j] and array[i − 1].
4. Reverse the suffix starting at array[i].
*/
boolean nextPermutation(char[] array) {
int i = array.length - 1;
while (i > 0 && array[i - 1] >= array[i]) i--;
if (i <= 0) return false;
int j = array.length - 1;
while (array[j] <= array[i - 1]) j--;
char temp = array[i - 1];
array[i - 1] = array[j];
array[j] = temp;
j = array.length - 1;
while (i < j) {
temp = array[i];
array[i] = array[j];
array[j] = temp;
i++;
j--;
}
return true;
}
Trying to solve codility lessons for practice and working on this.
Written my code in Java and tested the code on a wide range of inputs, however the code fails for extreme_min_max, single and double in the codility test results.
Assumption given:
N is an integer within the range [1..100,000].
Each element of array A is an integer within the range [1..1,000,000,000].
Explanation of my code:
1. Sort the given array.
2. Iterate over each element in the array to find the difference between every consecutive pair. If the difference is not 1, Then its not a perm hence return 0. In case there is only one element in the array, return 1.
Can anyone please help me find out the bug(s) in my code?
My code:
public int solution(int[] A)
{
if(A.length == 1)
return 1;
Arrays.sort(A);
for (int i = 0; i < A.length-1; i++)
{
long diff = Math.abs(A[i] - A[i+1]);
if(diff!=1)
return 0;
}
return 1;
}
Here is simple and better implementation which runs in O(N) time complexity and takes O(N) space complexity.
public int solution(int[] A)
{
int size = A.length;
int hashArray[] = new int[size+1];
for (int i = 0; i < size; i++)
{
if(A[i]>size)
return 0;
else
hashArray[A[i]]+=1;
}
for(int i=1;i<=size;i++)
if(hashArray[i]!=1)
return 0;
return 1;
}
Try this in C# (Score 100%) :
using System;
using System.Linq;
class Solution {
public int solution(int[] A) {
if (A.Any(x => x == 0)) { return 0; }
var orderSelect = A.OrderBy(x => x).GroupBy(x => x);
if (orderSelect.Any(x => x.Count() > 1)) { return 0; }
var res = Enumerable.Range(1, A.Length).Except(A);
return res.Any() ? 0 : 1;
}
}
Pretty simple:
Your code doesn't check this condition:
A permutation is a sequence containing each element from 1 to N once, and only once.
Ensure that the first element after sorting is 1, and everything should work.
I'm not big on Java syntax, but what you want to do here is:
Create an array temp the length of A - initialized to 0.
Go over A and do temp[A[i]]++.
Go over temp, and if any place in the array is not 1, return false.
If duplicate exists - return 0 I have implemented with 100% pass
https://codility.com/demo/results/trainingWX2E92-ASF/
public static int permCheck(int A[]){
Set<Integer> bucket = new HashSet<Integer>();
int max = 0;
int sum=0;
for(int counter=0; counter<A.length; counter++){
if(max<A[counter]) max=A[counter];
if(bucket.add(A[counter])){
sum=sum+A[counter];
}
else{
return 0;
}
}
System.out.println(max+"->"+sum);
int expectedSum = (max*(max+1))/2;
if(expectedSum==sum)return 1;
return 0;
}
Here's my first 100% code.
I can't say if it's the fastest but it seems all correct -- watch the double OR ( || ) condition.
import java.util.Arrays;
class Solution
{
public int solution(int[] A)
{
int i = 0;
int size = A.length;
if ( size > 0 && size < 100001)
{
// Sort the array ascending:
Arrays.sort(A);
// Check each element:
for(i = 0; i < size; i++)
if ( A[i] > size || A[i] != (i + 1) )
return 0;
return 1;
}
return 0;
}
}
EDIT
Actually, we need not worry about valid first element data (i.e. A[i] > 0) because, after sorting, a valid perm array must have A[0] = 1 and this is already covered by the condition A[i] = i + 1.
The upper limit for array entries (> 1,000,000,000) is restricted further by the limit on the array size itself (100,000) and we must check for conformity here as there will be a Codility test for this. So I have removed the lower limit condition on array entries.
Below code runs and gave me a 100%, the time complexity is O(n):
private static int solution(int[] A) {
int isPermutation = 1; // all permutations start at 1
int n = A.length;
Arrays.sort(A);
if (n == 0) return 0; // takes care of edge case where an empty array is passed
for (int i = 0; i < n; i++) {
if (A[i] != isPermutation) { //if current array item is not equals to permutation, return 0;
return 0;
}
isPermutation++;
}
return 1;
}
100% score with complexity O(N)
public int solution(int[] A) {
int res = 1;
if (A.length == 1 && A[0]!=1)
return 0;
int[] B = new int[A.length];
for (int j : A) {
int p = j - 1;
if (A.length > p)
B[p] = j;
}
for (int i = 0; i < B.length - 1; i++) {
if (B[i] + 1 != B[i + 1]) {
res = 0;
break;
}
}
return res;
}
I'm trying to write a method that will accept an array and find any equal elements that appear next to each other and return a count for the greatest number of occurances. For example an array with the int values of {1,2,3,4,4,4,5,6} would return a value of 3. An array with {1,1,1,2,2,3,3,3,3,5,6,7} would return a value of four. I've tried a few different ways, but I'm struggling. Any help would be appreciated. Thanks. Heres the code that I have so far-
public class EqualElements
{
public static void consecutiveEqualElements(int [] elements)
{
int occurances = 0;
int temp = 0;
int count = 0;
for (int index = 0; index < elements.length; index++)
{
if(elements[index] == elements[temp])
{
count++;
temp++;
index--;
}
else
{
}
}
System.out.println(count);
}
public static void main(String[] args)
{
int [] numbers = {1,2,2,3,4,5,6,7};
consecutiveEqualElements(numbers);
}
}
Here is a much better way to look through an array for consecutive numbers. This will work for both unsorted and sorted arrays.
public static int consecutiveEqualElements(int [] elements) {
int currentNum = elements[0];
int currentConsecutive = 1;
int maxConsecutive = 1;
for (int i = 1; i < elements.length; i++) {
if (elements[i] == currentNum) {
currentConsecutive++;
maxConsecutive = Math.max(maxConsecutive, currentConsecutive);
} else {
currentNum = elements[i];
currentConsecutive = 1;
}
}
return maxConsecutive;
}
Easiest way is to use a hashmap:
Map map = new HashMap();
Now iterate through the array and put every integer with its count.
map.put(yourIntValue, map.get(1) + 1); // if it is already stored with a value.
For initial condition:
map.put(yourIntValue,0);
Then again iterate and find the max value.
My solution would look like this:
public class EqualElements {
public static void consecutiveEqualElements(int[] elements) {
// Saves the maximal number of consecutive number with the
// same numeric value
int occurances = 0;
// Counts how many numbers with the same value stands right
// behind each other
int count = 1;
// Run from the second index because of the in the body following
// if-clause
for (int index = 1; index < elements.length; index++) {
// In case the current and the previous element
// have the same numeric value
if (elements[index] == elements[index - 1]) {
// Increase the count (which is initialised with 1)
// And save the maximal number of consecutive numbers
// with the same value in occurances
count++;
occurances = Math.max(occurances, count);
} else {
// If the two numbers differ, reset the counter
count = 1;
}
}
System.out.println(occurances);
}
public static void main(String[] args) {
int[] numbers = { 1, 2, 2, 2, 3, 4, 5, 2, 6, 7 };
consecutiveEqualElements(numbers);
}
}
My example returns the correct solution 3. It doesn't count the last 2 since it's nonconsecutive.
You're already iterating over the array - that's good. While you do that you're interested in two numbers:
The longest run so far. This will be your answer in the end.
The length of the current run. You need this to update the longest run.
We create two variables for these: maxCount and count. During the loop, we increment count every time we encounter two consecutive elements that are equal. And to make sure maxCount is always up-to-date, we set it to the maximum of the longest so far, and the current length. When the next element is different from the previous, we reset count to 1, as this is the start of the next run.
public static void consecutiveEqualElements(int [] elements) {
int count = 1;
int maxCount = 1;
for (int index = 1; index < elements.length; index++) {
if (elements[index] == elements[index - 1]) {
count++;
maxCount = Math.max(maxCount, count);
} else {
count = 1;
}
}
System.out.println(maxCount);
}
Note: this method assumes that elements is not null or empty. You can handle these cases seperately, if they are necessary.
As you traverse the array, compare each element to the previous element. If the two elements are equal, increment the number of consecutive equal values you have seen. If they are not equal, check to see if you've found a new maximum, and then reset that counter to 0.
public static int consecutiveEqualElements(int[] elements) {
int max = 0;
int consecutive = 1;
for (int i = 1; i < elements.length; i++) {
if (elements[i] == elements[i-1]) {
consecutive++;
} else {
if (consecutive > max) {
max = consecutive;
}
consecutive = 1;
}
}
if (consecutive > max) {
return consecutive;
} else {
return max;
}
}
Notice that the method returns a value rather than printing it out. This makes the method more flexible, as you may not always want it to print to standard output.
How can i implement a recursive binary search in an int array using only 1 parameter in java ?
it tried but my code doesn't work. I implemented a class which its instances are objects having arrays and a count variable to detect how many elements are their in the array. any idea how can i implement the recursive binary search using only 1 parameter ?
public class LinearSortedArray {
int count;
int[] a;
public LinearSortedArray() {
count = 0;
}
public LinearSortedArray(int size) {
count = 0;
a = new int[size];
}
public static int[] copyingMethod(int startPoint, int endPoint,
LinearSortedArray arrayObj) {
int[] copyingArray = new int[endPoint - startPoint];
int j = startPoint;
for (int i = 0; i < copyingArray.length; i++) {
copyingArray[i] = arrayObj.a[j];
j++;
}
return copyingArray;
}
public int binarySearchRec(int x) {
if (count == 0) {
return -1;
}
int pivot = count / 2;
LinearSortedArray newArrayObj;
if (x > a[pivot]) {
newArrayObj = new LinearSortedArray(count - pivot);
newArrayObj.count = newArrayObj.a.length;
newArrayObj.a = copyingMethod(pivot, count, this);
for (int i = 0; i < newArrayObj.a.length; i++) {
System.out.print(newArrayObj.a[i]);
System.out.print(" ");
}
System.out.println();
return pivot + newArrayObj.binarySearchRec(x);
} else if (x < a[pivot]) {
newArrayObj = new LinearSortedArray(pivot);
newArrayObj.count = newArrayObj.a.length;
newArrayObj.a = copyingMethod(0, pivot, this);
for (int i = 0; i < newArrayObj.a.length; i++) {
System.out.print(newArrayObj.a[i]);
System.out.print(" ");
}
System.out.println();
return newArrayObj.binarySearchRec(x);
} else {
return pivot;
}
}
}
P.S.: The arrays are already sorted
Binary search really requires a range and a target value -- so if you're only passing one parameter, this has to be the target and this must encapsulate the array & range.
public class ArraySegment {
protected int[] array;
protected int boundLo;
protected int boundHi;
public class ArraySegment (int[] array) {
// entire array.
this( array, 0, array.length);
}
public class ArraySegment (int[] array, int lo, int hi) {
this.array = array;
this.boundLo = lo;
this.boundHi = hi;
}
public int binarySearch (int target) {
if (boundHi <= boundLo) {
return -1; // Empty; not found.
}
int pivot = (boundLo + boundHi) / 2;
int pivotEl = array[ pivot];
if (target == pivotEl) {
return pivot; // Found!
}
if (target < pivotEl) {
// recurse Left of pivot.
ArraySegment sub = new ArraySegment( array, boundLo, pivot);
return sub.binarySearch( target);
} else {
// recurse Right of pivot.
ArraySegment sub = new ArraySegment( array, pivot, boundHi);
return sub.binarySearch( target);
}
}
}
It's a little bit questionable what kind of result you should return -- there isn't a good answer with the question posed like this, as an "integer index" kinda defeats the purpose of the ArraySegment/ range wrapper, and returning an ArraySegment containing only the found value is also fairly useless.
PS: You really shouldn't be copying the array or it's contents, just passing round references to ranges on that array. Like java.lang.String is a range on a character array.
You could contrive a single-parameter by using the Value Object Pattern, where you pass one "wrapper" object, but the object has many fields.
For example:
class SearchParams {
int target;
int start;
int end;
SearchParams(t, s, e) {
target = t;
start = s;
end = e'
}
}
int search(SearchParams params) {
// some impl
return search(new SearchParams(params.target, a, b));
}
Technically, this is one parameter. Although it may not be in the spirit of the rules.
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();
}
}