Binary Search program in Java - java

Here is my code for program using Binary Search:
import java.util.Random;
public class QSrt {
int[] arr = new int[20];
public void addElement() {
for (int i = 0; i < arr.length; i++) {
Random rd = new Random();
arr[i] = rd.nextInt(10);
}
}
public void sort(){
for (int i = 0; i < arr.length - 1; i++) {
for (int j = arr.length - 1; j > i; j--) {
if(arr[j] < arr[j-1]){
int t = arr[j];
arr[j] = arr[j-1];
arr[j-1] = t;
}
}
}
}
public int binarySearch(int val){
int first = 0;
int last = arr.length - 1;
int index = -1;
while (first <= last) {
int middle = (first + last)/2;
if(arr[middle] == val){
index = middle;
}else if(arr[middle] < val){
first = middle + 1;
}else{
last = middle - 1;
}
}
return index;
}
public static void main(String[] args) {
QSrt arr = new QSrt();
arr.addElement();
arr.sort();
for(int i = 0; i < arr.arr.length;i++){
System.out.print(arr.arr[i] + " ");
}
System.out.println("");
System.out.println(arr.binarySearch(0));
}
}
But I get a problem: the program only prints elements of sorted array then it keeps running and does not print the index yet
Here is picture:
enter image description here

You need to break out of the loop once the desired value is obtained
if(arr[middle] == val){
index = middle;
return index; //OR just => return middle;
}

Related

java.lang.StackOverflowError on factorial function being called by another recursive function

I have a factorial function on my program that works fine until i try to execute the function deleteRepeated(), the console is telling me that the error is in the return of the factorial function, maybe it's being called by a single function too many times in a short period of time? I've been stuck for hours.
import java.util.Scanner;
public class ex9 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
}
int[] newArr = new int[n - repeated(arr)];
int[] finalArr = deleteRepeated(arr, newArr);
for (int a : finalArr) {
System.out.println(a);
}
}
public static long factorial(int n) {
if (n == 0)
return 1;
return (n * factorial(n - 1));
}
public static int repeated(int arr[]) {
int n = arr.length;
int mix = (int) (factorial(n) / (2 * factorial(n - 2)));
int i = 0;
int k = 0;
int rep = 0;
int a = -100;
while (i < mix) {
for (int j = k + 1; j < n; j++) {
if (arr[k] == arr[j] && a != j) {
a = j;
rep += 1;
}
i++;
}
k++;
}
return rep;
}
public static int[] deleteRepeated(int arr[], int newArr[]) {
int n = arr.length;
int rep = repeated(arr);
int i = 0;
int k = 0;
int a = -100;
while (i < newArr.length) {
for (int j = k + 1; j < n; j++) {
if (arr[k] == arr[j] && a != arr[k]) {
a = arr[j];
newArr[k] = arr[k];
}
i++;
}
k++;
}
rep = repeated(newArr);
if (rep > 0) {
int[] newArr2 = new int[newArr.length - rep];
deleteRepeated(newArr, newArr2);
}
return newArr;
}
}
Only thing i could do to avoid the error was stopping the function from executing :/, maybe it has to do with how i'm re-calling it at the end of each execution...? is what i did allowed?
So, deleteRepeated is all messed up. The issue is deleteRepeated does not actually remove duplicate elements, so the check for the base case of recursion always fails. I'm not sure why you're using recursion here anyway; if the while loop worked properly, it could remove all duplicates without need for recursion.
It appears that you copy-pasted the implementation of repeated into deleteRepeated, and you replaced the logic for handling repeated elements with logic that handles non-repeated elements.
Here is how I would implement the method:
public static int deleteRepeated(int arr[], int newArr[]) {
int n = 0;
for(int i = 0; i < arr.length; i++) {
boolean unique = true;
for(int j = 0; j < n; j++)
unique = unique && newArr[j] != arr[i];
if(unique)
newArr[n++] = arr[i];
if(n >= newArr.length) break;
}
return n;
}

Bubble sort String array and int array

Here I want to make a bubble sort that compares all the names of type string
in the array names in alphabetic order; like B and A ---> A and B.
And when I do this change I also want to change the position of the itemsToSell array so all the right names have the right numbers next to them. I can't use java.util.Arrays; Any advice?
public static void printNames(String[] name, int[] itemsToSell, int[] amountBought) {
boolean flag = true;
while (flag) {
flag = false;
for (int j = 0; j < name.length - 1; j++) {
for (int i = j + 1; i < name.length; i++) {
if (name[i].compareTo(name[j]) < 0) {
int tempTtem = itemsToSell[j];
itemsToSell[j] = itemsToSell[i];
itemsToSell[i] = tempTtem;
String temp = name[j];
name[j] = name[i];
name[i] = temp;
}
}
System.out.println(name[j] + '\t' + itemsToSell[j] + "\t\t" + amountBought[j]);
}
}
}
public class Main {
public static void bubbleSort(String[] name, int[] itemsToSell) {
while (true) {
boolean sorted = moveRight(name, itemsToSell);
sorted &= moveLeft(name, itemsToSell);
if (sorted)
break;
}
}
private static boolean moveRight(String[] name, int[] itemsToSell) {
boolean sorted = true;
for (int i = 0, j = 1; j < name.length; i++, j++) {
if (name[i].compareTo(name[j]) > 0) {
sorted = false;
swap(itemsToSell, i, j);
swap(name, i, j);
}
}
return sorted;
}
private static boolean moveLeft(String[] name, int[] itemsToSell) {
boolean sorted = true;
for (int j = name.length - 1, i = j - 1; i >= 0; i--, j--) {
if (name[i].compareTo(name[j]) > 0) {
sorted = false;
swap(itemsToSell, i, j);
swap(name, i, j);
}
}
return sorted;
}
private static void swap(String[] arr, int i, int j) {
String tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
private static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}

Counting number of duplicates in a given array

Input: 1,4,2,6,7,5,1,2
Output:2
Counting the number of duplicated numbers in a given array for java. I first sorted the array and then counted duplicates. It's showing me error that variable c is not used and that this method should return value of int.
public class Duplicates
public static void main(String[] args) {
int[]list;
int[]c;
int[] c = new int[list.length];
int temp;
for (int i = 0; i < list.length - 1; i++) {
for (int j = i + 1; j < list; j++) {
if (list[I] > list[j]) {
temp = list[i];
list[i] = list[j];
list[j] = temp;
c = list;
}
}
}
int n = 0;
int counter = 0;
int a = -1;
for (int i = 0; i < c.length; ++i) {
if (c[i] == a) {
++n;
if (n == 1) {
++counter;
if (counter == 1) {
System.out.print(c[i]);
} else {
System.out.print("," + c[i]);
}
}
} else {
a = c[i];
n = 0;
}
}
System.out.println("\nNumber of Duplicated Numbers in array:" + counter);
}
}
It's showing me error that variable c is not used
This should be a warning. So the code should still run correctly even with this is showing.
this method should return value of int
This is a compilation error and since you are not returning any int array at the end of the method, your method's return type should be void. You should change your method signature as below,
public static void c(int[] list)
Otherwise you will need to return an int array at the end of your method.
After fixing your code,
public class Duplicates {
public static void main(String[] args) {
int[] list = new int[]{1, 4, 2, 6, 7, 5, 1, 2};
int temp;
for (int i = 0; i < list.length; ++i) {
for (int j = 1; j < (list.length - i); ++j) {
if (list[j - 1] > list[j]) {
temp = list[j - 1];
list[j - 1] = list[j];
list[j] = temp;
}
}
}
int n = 0, counter = 0;
int previous = -1;
for (int i = 0; i < list.length; ++i) {
if (list[i] == previous) {
++n;
if (n == 1) {
++counter;
if (counter == 1) {
System.out.print(list[i]);
} else {
System.out.print(", " + list[i]);
}
}
} else {
previous = list[i];
n = 0;
}
}
System.out.println("\nNumber of Duplicated Numbers in array: " + counter);
}
}

Exception out of Boundaries in MergeSort

I've been trying hard to find where the problem is. But everytime I run this program, it shows :
Exception in thread "main" java.lang.NullPointerException
at MergeSortTest.mergeSort(MergeSortTest.java:8)
Can someone please help me how to fix this?
public class MergeSortTest
{
private static int[] arr;
public static void mergeSort(int[] array)
{
int start = 0;
int end = arr.length - 1;
mergeSort(start, end);
array = arr;
}
public static void mergeSort(int start, int end)
{
if (start == end) {
return;
}
int center = (start + end) / 2;
mergeSort(start, center);
mergeSort(center + 1, end);
merge(start, center + 1, end);
}
public static void merge(int left, int right, int rightEnd)
{
int k = left;
int leftEnd = right-1;
int num = rightEnd - left + 1;
int front[] = new int[leftEnd - left + 1];
int back[] = new int[rightEnd - right + 1];
for (int i = left; i < front.length; i++)
{
front[i] = arr[i];
}
for (int i = right; i < back.length; i++)
{
back[i] = arr[i];
}
int[] temp = new int[num];
while (true)
{
if (front[left] <= back[right])
{
if (left < leftEnd)
{
temp[k] = front[left];
k++;
left++;
}
if (left == leftEnd)
{
temp[k] = front[left];
for (right = right; right < rightEnd + 1; right++)
{
k++;
temp[k] = back[right];
}
break;
}
}
else
{
if (right < rightEnd)
{
temp[k] = back[right];
k++;
right++;
}
if (right == rightEnd)
{
temp[k] = back[left];
for(left = left; left < leftEnd+1; left++)
{
k++;
temp[k] = front[left];
}
break;
}
}
}
}
public static void main(String []args)
{
int[] array = new int[10];
initializeRandom(array);
for(int i = 0; i < array.length; i++)
{
System.out.print(array[i] + " ");
}
System.out.println();
mergeSort(array);
for (int i = 0; i < array.length; i++)
{
System.out.print(array[i] + " ");
}
}
public static void initializeRandom(int[] array)
{
for (int i = 0; i < array.length; i++)
{
array[i] = (int)(Math.random() * 10 + 1);
}
}
}
You aren't using the array you're passing as a parameter, but using uninitialized one:
private static int[] arr;
// ...
int end = arr.length - 1;
In your main method:
mergeSort(array);
You need to either pass the arr down to merge or rewrite your logic.

Searching for a sum in an array

I have a method which counts how many sums of 3 elements,which are equal to 0, does the array contains. I need help finding the way to stop counting the same triplets in the loop. For instance, 1 + 3 - 4 = 0, but also 3 - 4 +1 = 0.Here is the method:
private static int counter(int A[])
{
int sum;
int e = A.length;
int count = 0;
for (int i=0; i<e; i++)
{
for (int j=i+1; j<e; j++)
{
sum=A[i]+A[j];
if(binarySearch(A,sum))
{
count++;
}
}
}
return count;
edit: I have to use the Binary Search (the array is sorted).
Here is the binarySearch code:
private static boolean binarySearch(int A[],int y)
{
y=-y;
int max = A.length-1;
int min = 0;
int mid;
while (max>=min)
{
mid = (max+min)/2;
if (y==A[mid])
{
return true;
}
if (y<A[mid])
{
max=mid-1;
}
else
{
min=mid+1;
}
}
return false;
You can avoid counting different triplets by making one assumption that we need to look for the triplets (x,y,z) with x < y < z and A[x] + A[y] + A[z] == 0.
So what you need to do is to modify the binarySearch function to return the number of index that greater than y and has A[z] == -(A[x] + A[y])
private static int binarySearch(int A[],int y, int index)
{
y=-y;
int max = A.length-1;
int min = index + 1;
int mid;
int start = A.length;
int end = 0;
while (max>=min)
{
mid = (max+min)/2;
if (y==A[mid])
{
start = Math.min(start, mid);
max = mid - 1;
} else
if (y<A[mid])
{
max=mid-1;
}
else
{
min=mid+1;
}
}
int max = A.length - 1;
int min = index + 1;
while (max>=min)
{
mid = (max+min)/2;
if (y==A[mid])
{
end = Math.max(end, mid);
min= mid + 1;
} else if (y<A[mid])
{
max=mid-1;
}
else
{
min=mid+1;
}
}
if(start <= end)
return end - start + 1;
return 0;
}
So the new function binarySearch will return the total number of index that greater than index and has value equals to y.
So the rest of the job is to count the answer
private static int counter(int A[])
{
int sum;
int e = A.length;
int count = 0;
for (int i=0; i<e; i++)
{
for (int j=i+1; j<e; j++)
{
sum=A[i]+A[j];
count += binarySearch(A,sum, j);
}
}
return count;
}
Notice how I used two binary search to find the starting and the ending index of all values greater than y!
private static int counter(int A[]) {
int e = A.length;
int count = 0;
for (int i = 0; i < e; i++) {
for (int j = 1; (j < e - 1) && (i != j); j++) {
for (int k = 2; (k < e - 2) && (j != k); k++) {
if (A[i] + A[j] + A[k] == 0) {
count++;
}
}
}
}
return count;
}
private static int counter(int ints[]) {
int count = 0;
for (int i = 0; i < ints.length; i++) {
for (int j = 0; j < ints.length; j++) {
if (i == j) {
// cannot sum with itself.
continue;
}
for (int k = 0; k < ints.length; k++) {
if (k == j) {
// cannot sum with itself.
continue;
}
if ((ints[i] + ints[j] + ints[k]) == 0) {
count++;
}
}
}
}
return count;
}
To solve problem with binary search
Your code was almost correct. all you needed to do was just to replace
if (sum == binarySearch(A,sum)) {
with this
if (binarySearch(A,sum)) {
I am assuming that your binarySearch(A, sum) method will return true if it will found sum in A array else false
private static int counter(int A[]) {
int sum;
int e = A.length;
int count = 0;
for (int i=0; i<e; i++) {
for (int j=i+1; j<e; j++) {
sum=A[i]+A[j];
if (binarySearch(A,sum)) {
count++;
}
}
}
return count;
}
Here is my solution assuming the array is sorted and there are no repeated elements, I used the binary search function you provided. Could the input array contain repeated elements? Could you provide some test cases?
In order to not counting the same triplets in the loop, we should have a way of inspecting repeated elements, the main idea that I used here is to have a list of int[] arrays saving the sorted integers of {A[i],A[j],-sum}.Then in each iteration I compare new A[i] and A[j] to the records in the list, thus eliminating repeated ones.
private static int counter(int A[]){
int sum;
int e = A.length;
int count = 0;
List<int[]> elements = new ArrayList<>();
boolean mark = false;
for (int i=0; i<e; i++)
{
for (int j=i+1; j<e; j++)
{
sum=A[i]+A[j];
if (-sum == binarySearch(A,sum)){
int[] sort = {A[i],A[j],-sum};
if(-sum == A[i] || -sum == A[j]){
continue;
}else{
Arrays.sort(sort);
//System.out.println("sort" + sort[0] + " " + sort[1]+ " " + sort[2]);
for (int[] element : elements) {
if((element[0] == sort[0] && element[1] == sort[1]) && element[2] == sort[2])
mark = true;
}
if(mark){
mark = false;
continue;
}else{
count++;
elements.add(sort);
//System.out.println("Else sort" + sort[0] + " " + sort[1]);
}
}
}
}
}
return count;
}
you can use a assisted Array,stored the flag that indicate if the element is used;
Here is the code:
private static int counter(int A[])
{
int sum;
int e = A.length;
int count = 0;
// assisted flag array
List<Boolean> flagList = new ArrayList<Boolean>(e);
for (int k = 0; k < e; k++) {
flagList.add(k, false);// initialization
}
for (int i=0; i<e; i++)
{
for (int j=i+1; j<e; j++)
{
sum=A[i]+A[j];
// if element used, no count
if(binarySearch(A,sum)&& !flagList.get(i)&& !flagList.get(j))
{
count++;
flagList.set(i, true);
flagList.set(j, true);
}
}
}
return count;

Categories

Resources