Prolem with binary search algorithm - java

Recently I study algorithms,but I find a terrible problem that I cannot find the number by BinarySearch Algorithm in the link:
http://algs4.cs.princeton.edu/11model/BinarySearch.java.html
public class BinaryFind {
public static int indexOf(int[] a, int key) {
int lo = 0;
int hi = a.length - 1;
while (lo <= hi) {
// Key is in a[lo..hi] or not present.
int mid = lo + (hi - lo) / 2;
if (key < a[mid]) hi = mid - 1;
else if (key > a[mid]) lo = mid + 1;
else return mid;
}
return -1;
}
public static void main(String[] args) {
int[] a = {1, 4, 56, 4, 3, 7, 8, 2, 66, 45};
System.out.print(indexOf(a, 7));
}
}
Why I cannot find the number 7?
The result:

Add this line to the top of the indexOf(..) method.
Arrays.sort(a);
This will sort your input array and then you can go on with finding the index.

The array to be searched from have to be sorted to use binary search.
Try this:
public static void main(String[] args) {
int[] a = {1, 4, 56, 4, 3, 7, 8, 2, 66, 45};
// sort the array
for (int i = a.length - 1; i > 0; i--) {
for (int j = 0; j < i; j++) {
if (a[j] > a[j + 1]) {
int t = a[j];
a[j] = a[j + 1];
a[j + 1] = t;
}
}
}
System.out.print(indexOf(a, 7));
}

Related

How can I partition from the right and not the left?

I'm working on this program that is essentially using the partition algorithm but it's meant to run from the right and not the left. However, I am having problems as it's not running the correct code.
If my array was [64, 17, 7, 3, 33]; when I run partition my output should be [17, 7, 3, 33, 64] but instead I'm getting [33, 17, 7, 3, 64]. Does someone know what the problem is? and How to fix it.
import java.util.Arrays;
public class PartitionPivotOnRight {
public static int partition(int[] a) {
int left = 0;
int right = a.length - 2;
int pivot = a.length - 1;
while (left <= right) {
while (left < a.length && a[left] < a[pivot])
++left;
while (a[right] > a[pivot])
--right;
if (left <= right)
swap(a, left++, right--);
}
swap(a, left, pivot);
return left;
}
public static void swap(int[] a, int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
public static void main(String[] args) {
int N = 10;
int[] a = new int[N];
for (int i = 0; i < N; i++)
a[i] = (int) (Math.random() * 100);
System.out.println(Arrays.toString(a));
System.out.println(partition(a));
System.out.println(Arrays.toString(a));
}
}

Finding all inversions of an array using Merger-Sort

I'm trying to implement the popular algorithm for finding all inversions of an array using merge sort but it keeps outputting the wrong answer, it counts far too many inversions - I believe part or all of the sub arrays are being iterated too many times in the recurrence calls? I can't quite put my finger on it - I would appreciate some pointers as to why this might be happening. Please see my implementation in java below:
public class inversionsEfficient {
public int mergeSort(int[] list, int[] temp, int left, int right) {
int count = 0;
int mid = 0;
if(right > left) {
mid = (right+left)/2;
count += mergeSort(list, temp, left, mid);
count += mergeSort(list, temp, mid+1, right);
count += merge(list, temp, left, mid+1, right);
}
return count;
}
public int merge(int[] list, int[] temp, int left, int mid, int right) {
int count = 0;
int i = left;
int j = mid;
int k = left;
while((i<=mid-1) && (j<=right)) {
if(list[i] <= list[j]) {
temp[k] = list[i];
k += 1;
i += 1;
}
else {
temp[k] = list[j];
k += 1;
j += 1;
count += mid-1;
}
}
while(i<=mid-1) {
temp[k] = list[i];
k += 1;
i += 1;
}
while(j<=right) {
temp[k] = list[j];
k += 1;
j += 1;
}
for(i=left;i<=right;i++) {
list[i] = temp[i];
}
return count;
}
public static void main(String[] args) {
int[] myList = {5, 3, 76, 12, 89, 22, 5};
int[] temp = new int[myList.length];
inversionsEfficient inversions = new inversionsEfficient();
System.out.println(inversions.mergeSort(myList, temp, 0, myList.length-1));
}
}
This algorithm is based on this pseudocode from Introduction to Algorithms by Cormen:
[1]: https://i.stack.imgur.com/ea9No.png
Instead of -
count += mid - 1;
try -
count += mid - i;
The whole solution becomes as shown below :-
public class inversionsEfficient {
public int mergeSort(int[] list, int[] temp, int left, int right) {
int count = 0;
int mid = 0;
if (right > left) {
mid = (right + left) / 2;
count += mergeSort(list, temp, left, mid);
count += mergeSort(list, temp, mid + 1, right);
count += merge(list, temp, left, mid + 1, right);
}
return count;
}
public int merge(int[] list, int[] temp, int left, int mid, int right) {
int count = 0;
int i = left;
int j = mid;
int k = left;
while ((i <= mid - 1) && (j <= right)) {
if (list[i] <= list[j]) {
temp[k] = list[i];
k += 1;
i += 1;
} else {
temp[k] = list[j];
k += 1;
j += 1;
count += mid - i; // (mid - i), not (mid - 1)
}
}
while (i <= mid - 1) {
temp[k] = list[i];
k += 1;
i += 1;
}
while (j <= right) {
temp[k] = list[j];
k += 1;
j += 1;
}
for (i = left; i <= right; i++) {
list[i] = temp[i];
}
return count;
}
public static void main(String[] args) {
int[] arr = {5, 3, 76, 12, 89, 22, 5};
int[] temp = new int[arr.length];
inversionsEfficient inversions = new inversionsEfficient();
System.out.println(inversions.mergeSort(arr, temp, 0, arr.length - 1));
}
}
The output generated by the above code for the example array mentioned in the question is 8, which is correct because there are 8 inversions in the array [5, 3, 76, 12, 89, 22, 5] -
1. (5, 3)
2. (76, 12)
3. (76, 22)
4. (76, 5)
5. (12, 5)
6. (89, 22)
7. (89, 5)
8. (22, 5)
Explanation for Code Change
This algorithm counts the number of inversions required as the sum of the number of inversions in the left sub-array + number of inversions in the right sub-array + number of inversions in the merge process.
If list[i] > list[j], then there are (mid – i) inversions, because the left and right subarrays are sorted. This implies that all the remaining elements in left-subarray (list[i+1], list[i+2] … list[mid]) will also be greater than list[j].
For a more detailed explanation, have a look at the GeeksForGeeks article on Counting Inversions.

merging 3 sorted arrays

public class array12 {
static void merge_sort(int A[], int start, int end) {
if (end - start > 1) {
int middle1 = (2 * start + end + 1) / 3 - 1;
int middle2 = 2 * middle1 - start + 1;
merge_sort(A, start, middle1);
merge_sort(A, middle1 + 1, middle2);
merge_sort(A, middle2 + 1, end);
merge(A, start, middle1, middle2, end);
}
}
static void merge(int[] x, int start, int middle1, int middle2, int end) {
int n1 = middle1 - start + 1;
int n2 = middle2 - middle1;
int n3 = end - middle2;
int left[] = new int[n1]; // defining and initialising three arrays .
int mid[] = new int[n2];
int right[] = new int[n3];
for (int i = 0; i < left.length; i++) {
left[i] = x[i + start];
}
for (int i = 0; i < mid.length; i++) {
mid[i] = x[i + middle1 + 1];
}
for (int i = 0; i < right.length; i++) {
right[i] = x[i + middle2 + 1];
}
int i = 0;
int j = 0;
int k = 0;
int c = start;
// finding minimum element from the three arrays .
while (i < n1 && j < n2 && k < n3) {
if (left[i] <= mid[j] && left[i] <= right[k]) {
x[c] = left[i];
i++;
c++;
} else if (mid[j] <= left[i] && mid[j] <= right[k]) {
x[c] = mid[j];
j++;
c++;
} else {
x[c] = right[k];
k++;
c++;
}
}
// now only two arrays are left to be compared
while (i < n1 && j < n2) {
if (left[i] <= mid[j]) {
x[c] = left[i];
i++;
c++;
} else {
x[c] = mid[j];
j++;
c++;
}
}
while (j < n2 && k < n3) {
if (mid[j] <= right[k]) {
x[c] = mid[j];
j++;
c++;
} else {
x[c] = right[k];
k++;
c++;
}
}
while (i < n1 && k < n3) {
if (left[i] <= right[k]) {
x[c] = left[i];
i++;
c++;
} else {
x[c] = right[k];
k++;
c++;
}
}
// now only single array is left out of left[] , mid[] and right[].
while (i < n1) {
x[c] = left[i];
i++;
c++;
}
while (j < n2) {
x[c] = mid[j];
j++;
c++;
}
while (k < n3) {
x[c] = right[k];
k++;
c++;
}
System.out.println("");
// printing array elements after every merge operation .
for (int e = 0; e < x.length; e++) {
System.out.print(x[e] + " ");
}
}
public static void main(String[] args) {
int[] x = new int[9];
for (int i = 0; i < x.length; i++) {
x[i] = x.length - i;
}
System.out.println("initial array is : ");
for (int i = 0; i < x.length; i++) {
System.out.print(x[i] + " ");
}
System.out.println("");
merge_sort(x, 0, x.length - 1);
System.out.println("");
System.out.println("");
System.out.println(" sorted array is : ");
for (int i = 0; i < x.length; i++) {
System.out.print(x[i] + " ");
}
}
}
I am trying to merge 3 sorted arrays . I have been able to develop code for array size equal to power of 3 . I am unable to implement it with some other array size . I have tried to change values of middle1 and middle2 but am experiencing serious trouble . Setting their values is the main concern . Merging step is quite simple and is not causing problems .
What changes are required in my code so that it may work for any array size ? Can it be implemented using this approach ? I dont want size of any of the three arrays , left[] , mid[] and right[] to be zero at any time .
Please help .
Here's a similar answer to YCF_L's, but simplified (still uses Java 8):
public static int[] sortMultipleArrays(int[]... arrays) {
return Arrays.stream(arrays)
.flatMapToInt(Arrays::stream)
.sorted()
.toArray();
}
Output:
[1, 2, 3, 5, 6, 7, 9, 10, 12, 13, 17, 20, 21, 24]
I don't follow your merge code. It seems overly complicated.
Here is a method for merging an unlimited number of sorted arrays, each a varying size.
private static int[] mergeSortedArrays(int[]... arrays) {
int totalLen = 0;
for (int[] arr : arrays)
totalLen += arr.length;
int[] idx = new int[arrays.length];
int[] merged = new int[totalLen];
for (int i = 0; i < totalLen; i++) {
int min = 0, minJ = -1;
for (int j = 0; j < arrays.length; j++)
if (idx[j] < arrays[j].length)
if (minJ == -1 || min > arrays[j][idx[j]]) {
min = arrays[j][idx[j]];
minJ = j;
}
merged[i] = min;
idx[minJ]++;
}
return merged;
}
Test
int[] a = { 3, 5, 9, 13, 17, 21 };
int[] b = { 2, 10, 20 };
int[] c = { 1, 7, 12, 24 };
int[] d = { 6 };
int[] merged = mergeSortedArrays(a, b, c, d);
System.out.println(Arrays.toString(merged));
Output
[1, 2, 3, 5, 6, 7, 9, 10, 12, 13, 17, 20, 21, 24]
If using class "Integer" instead of primitive int is not a problem you can use this, basically first do the merge and after sort them: you can do the call Arrays.sort even in the same method and call it mergeAndSort, if you want...
import java.util.Arrays;
public class Main {
public static Integer[] merge(Integer[]... arrays) {
int count = 0;
for (Integer[] array : arrays) {
count += array.length;
}
Integer[] mergedArray = (Integer[]) java.lang.reflect.Array.newInstance(arrays[0][0].getClass(), count);
int start = 0;
for (Integer[] array : arrays) {
System.arraycopy(array, 0, mergedArray, start, array.length);
start += array.length;
}
return mergedArray;
}
public static void main(String[] args) {
Integer[] array1 = {3, 5, 6, 7, 78, 100};
Integer[] array2 = {5, 6, 7, 8, 9};
Integer[] array3 = {2, 6, 7};
Integer[] merged1 = merge(array1, array2);
Arrays.sort(merged1);
Integer[] merged2 = merge(array1, array2, array3);
Arrays.sort(merged2);
printArray(merged1);
printArray(merged2);
}
public static void printArray(Integer[] x) {
System.out.println("--ToString--");
for (Integer var : x) {
System.out.println(var);
}
System.out.println("----");
}
}

Bubblesort doesn't sort properly

I have some code that I've compiled and ran. It is suppose to sort the values from smallest to greatest. Can someone help me find what is going on in the code and not making it sort correctly? I get these numbers
-9 -3 -1 1 6 7 83 19 2 6 4 6 32 66
Can someone help me and tell me what is wrong with the code? Thank you!
int myArray[] = {1, 6, -1, 7, 83, 19, -3, 6, 2, 4, 6, 32, 66, -9};
int n = myArray.length;
myArray = doop(myArray);
for (int i = 0; i < n; i++) {
System.out.println(myArray[i]);
}
private static int[] doop(int[] myArray) {
int n = myArray.length;
int swap;
for (int i = n - 1; i >= 0; i--) {
int j = i;
int min = myArray[i];
while ((j > 0) && (myArray[j - 1] < min)) {
myArray[j] = myArray[j - 1];
j = j - 1;
}
myArray[j] = min;
}
return myArray;
}
In bubble sort you have to compare the only the adjacent elements and traverse the array. Repeating this n-1 times , your array gets sorted and so correct code is:
private static int[] doop(int[] myArray)
{
int n = myArray.length;
for (int i = n - 1; i >= 0; i--)
{
for(int j=n-1;j>0;j--)
{
if(myArray[j]<myArray[j-1])
{
//swapping the elements
myArray[j]=myArray[j]^myArray[j-1];
myArray[j-1]=myArray[j]^myArray[j-1];
myArray[j]=myArray[j]^myArray[j-1];
}
}
}
return myArray;
}
int myArray[] = {1, 6, -1, 7, 83, 19, -3, 6, 2, 4, 6, 32, 66, -9};
int n = myArray.length;
myArray = doop(myArray);
for (int i = 0; i < n; i++) {
System.out.println(myArray[i]);
}
}
private static int[] doop(int[] myArray) {
int n = myArray.length;
int swap;
for (int i = n - 1; i >= 0; i--) {
int j = i;
int min = myArray[i];
while ((j > 0) && (myArray[j - 1] < min)) {
myArray[j] = myArray[j - 1];
j = j - 1;
myArray[j] = min;
}
}
return myArray;
}

What's wrong with my modified merge sort implementation?

I'm trying to write a modified merge sorting as an excercise. But i am stuck in why my code doesn't work and i cannot se where is the problem?! any hint or help is appreciate. Thanks in advance.
Here is my code:
public class MergeSort {
public static void mergeSort(int[] list) {
mergeSort(list, 0, list.length - 1);
}
private static void mergeSort(int[] list, int low, int high) {
if (low < high) {
int middle = (high + low) / 2;
mergeSort(list, low, middle);
mergeSort(list, middle + 1, high);
int[] temp = merge(list, low, high);
System.arraycopy(temp, 0, list, low, high - low + 1);
}
}
private static int[] merge(int[] list, int low, int high) {
int low1 = low;
int high1 = high;
int mid = (low + high) / 2;
int end_low = mid;
int start_high = mid + 1;
while ((low <= end_low) && (start_high <= high1)) {
if (list[low] < list[start_high]) {
low++;
} else {
int temp = list[high - low + 1];
for (int k = start_high - 1; k >= low; k--) {
list[k + 1] = list[k];
}
list[low] = temp;
low++;
end_low++;
start_high++;
}
}
return list;
}
public static void main(String[] args) {
int[] list = { 2, 3, 2, 5, 6, 1, -2, 3, 14, 12, -5 };
mergeSort(list);
for (int i = 0; i < list.length; i++)
System.out.print(list[i] + " ");
}
}

Categories