Recursive search error - java

running into a silly error and I just don't see it. I've been looking at this for a while and don't see what I'm missing. I am recursively searching an array for a specific target number but once I get up to element [7] it begins returning -1. Thanks for taking a look fellas/ladies!
public static void main(String[] args)
{
int[] a = {1,25,2,6,4,3,23,30,32,14,11,8};
Arrays.sort(a);
int target = a[7];
int first = a[0];
int last = a.length;
for(int i=0;i<a.length;i++)
{
System.out.print(" "+a[i]);
}
System.out.println("\n"+binarySearch(target,first,last,a));
}
public static int binarySearch(int target,int first, int last, int[] a)
{
int result;
if(first>last)
return -1;
else
{
int mid = (first+last)/2;
if(target == mid)
result = mid;
else if(target<a[mid])
result = binarySearch(target,first,last-1,a);
else
result = binarySearch(target,mid+1,last,a);
}
return result;
}

In several places you fail to accurately distinguish between the value in an index of an array and the index itself.
This: a[i] gets the value at the ith element
This: i is simply an index, i
With that in mind, here is a fixed version of your code. See my comments in the code for some specific errors I fixed:
public static void main(String[] args)
{
int[] a = {1,25,2,6,4,3,23,30,32,14,11,8};
Arrays.sort(a);
int target = a[7];
//here you want the index of the first location to search, not the value in that index
//so you use 0 instead of a[0]
int first = 0;
//the last element index is length-1, not length, since arrays are 0-based
int last = a.length - 1;
for(int i=0;i<a.length;i++)
{
System.out.print(" "+a[i]);
}
System.out.println("\n"+binarySearch(target,first,last,a));
}
public static int binarySearch(int target,int first, int last, int[] a)
{
int result;
if(first>last)
return -1;
else
{
int mid = (first+last)/2;
//here you need to check if the target is equal to the value at the index mid
//before you were checking if the target was equal to the index, which was never true
if(target == a[mid])
//you want to return the value at the target, not the index of the target
//so use a[mid] not mid
result = a[mid];
else if(target<a[mid])
//here you want to search from first to mid-1
//before you were searching from first to last-1, which is not correct binary search
result = binarySearch(target,first,mid - 1,a);
else
result = binarySearch(target,mid + 1,last,a);
}
return result;
}

Related

I want to find the last occurrence of a value in an array and also return "-1" if no such number is found

I know there are similar questions on stackoverflow, but none of their answers incorporated a return "-1" when no number is found.
Given an array list such as a = [4, 3, 9, 4, 6]
When entering a value such as v = 4, I want Java to give me the last index equivalent to that value in the array. So in this case, Java should return the index value 3.
If no values exist in the array such as v = 2, then I want it to return "-1".
This following solution I came up with finds the first index and returns it:
public static int lastIndexOf(int[] a, int v) {
int index = 0;
for(int i=0; i<a.length;i++) {
if(a[i]==v) {
index=i;
return index;
}
}
return -1;
}
This other solution I have, finds the last index in the array, but does not return "-1" when I enter a value that doesn't exist in the array.
public static int lastIndexOf(int[] a, int v) {
int index = 0;
for(int i=0; i<a.length;i++) {
if(a[i]==v) {
index=i;
}
}
return index;
}
I feel like I'm close to solving this, but I can't quite figure out how to mix these two solutions together.
In the second solution, just initialize the variable like this:
int index = -1;
Also consider traversing the array from right to left, in this way we can stop as soon as we find the element, it'll be more efficient:
public static int lastIndexOf(int[] a, int v) {
for (int i = a.length-1; i >= 0; i--)
if (a[i] == v)
return i;
return -1;
}
Assing int index = -1. Also a small optimization, loop from end, may be much faster for bigger loops:
public static int lastIndexOf(int[] a, int v) {
int index = -1;
for(int i=a.length-1; i >= 0; i--) {
if(a[i]==v) {
index=i;
return index;
}
}
return index;
}

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] + " ");
}
}
}

Given an array of integers, find out the third largest value in the array

public int thirdLargest(int[] arr){
int f_l = arr[0];
int s_l = arr[0];
int t_l = arr[0];
for(int i=1;i<arr.length;i++)
{
if (f_l < arr[i]){
t_l = s_l;
s_l = f_l;
f_l = arr[i];
}
else if (s_l < arr[i]){
t_l = s_l;
s_l = arr[i];
}
else if (t_l < arr[i]){
t_l = arr[i];
}
}
return t_l;
}
my code didn't passes some cases,any suggestion?
parameter {24,27,30,31,34,37,40,42}' , passes
parameter {2,-1,-2,-3,-4,-5}' , fails
This is simply cause by the fact that you initialize all values to arr[0]. If all elements are smaller than arr[0] this code won't update the values, even though the second-largest element for example wouldn't be arr[0]. Instead initialize the variables for the third/second/largest value with Integer.MIN_VALUE and start the search with the first element (index = 0) instead of the second.
There is actually a well-known algorithm for this, which is more generic than yours. It is called quick-select and looks like a quick sort with an optimization making it faster (linear time in average) : since we don't need to sort the array, we just recurse on the part of the array containing the index we are looking for (in your case, third item so index 2).
Here is an implementation in Java :
private static final Random rd = new Random();
public static int kthElement(int[] arr, int k) {
return kthElement(arr,k,0,arr.length);
}
private static T kthElement(int[] arr, int k, int min, int max) {
if (min < max - 1) {
int p = pivot(arr,min,max);
return p == k - 1 ? arr[p] :
p < k - 1 ? kthElement(arr,k,p + 1,max) : kthElement(arr,k,min,p);
}
return arr[min];
}
private static int pivot(int[] arr, int min, int max) {
int pivot = min + rd.nextInt(max - min);
swap(arr,pivot,max - 1);
pivot = min;
for (int i=min ; i<max ; i++)
if (arr[i] < arr[max - 1]) swap(arr,i,pivot++);
swap(arr,max - 1,pivot);
return pivot;
}
private static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
Well, as an alternative to your working code, here is a solution that will allow you to find the Nth largest integer in your array using Collections to do the heavy lifting:
import java.util.Arrays;
import java.util.Collections;
public class ArrayNthLargest {
public static int getNthLargest(int[] arrayInput, int n) {
Integer[] sortedArray = new Integer[arrayInput.length];
for (int i = 0; i < arrayInput.length; i++) {
sortedArray[i] = new Integer(arrayInput[i]);
}
Arrays.sort(sortedArray, Collections.reverseOrder());
return (sortedArray[n - 1]);
}
public static void main(String[] args){
int nth = new Integer(0);
int n = new Integer(3);
int[] testArray = {1,2,3,4,5,6,23,44,55,8,1};
nth = getNthLargest(testArray, n);
System.out.printf("The %d sorted array value is %d", n, nth);
}
}
This was actually an interesting question to me to do in O(n) complexity. I hope this solution is order n. I used an ArrayList as a stack (since Stack object won't allow addition of items in specific incidences (I've generalized it).
public int thirdLargest(int[] arr){
public int N_TH = 3; // Assuming this is nth largest you want
public ArrayList<Integer> largest = new ArrayList<Integer>(N_TH);
for(int i = 0;i<N_TH;i++)
largest.add(0); // initialize the ArrayList
for(int i = 0;i<arr.length;i++) {
for(int j=0;j<largest.size();j++){
if(arr[i] >= largest.get(j)) {
// Add the item at the correct index
// Pop the last element
largest.remove(largest.size()-1);
largest.add(j,arr[i]);
break;
}
}
}
return largest.get(N_TH);
}
Let me know if you find any problems with it, I might have mistyped part of trying to put it in OP's method.
EDIT won't work with negative numbers at the moment. You can find the smallest value in arr and initialize largest with that value. Then it'll also with negative numbers

Issue with binarySort method not returning proper item

So, I am trying to get my binarySearch to work and it dos not return the proper search item. Anyone have an idea? It always returns close to the item though.I know the issue is specifically with the while loop in the binarySearch method.
public class Sort {
static int item;
static Scanner console = new Scanner(System.in);
public static void main(String[] args) {
int[] list = new int[500];
for (int c = 0; c < 500; c++){
Random r = new Random();
list[c] = r.nextInt(1000);
}
int l = list.length;
System.out.print("Enter a search element: ");
System.out.println();
item = console.nextInt();
insertionSort(list, l);
}
public static int binarySearch(int[] list, int l,
int searchItem){
int first = 0;
int last = l - 1;
int mid = 0;
boolean found = false;
while (first <= last && !found)
{
mid = (first + last) / 2;
if (list[mid] == searchItem)
found = true;
else if (list[mid] > searchItem)
last = mid - 1;
else
first = mid + 1;
}
if (found)
return mid;
else
return 0;
}
public static void insertionSort(int[] list, int l){
int first, location;
int temp;
for (first = 1; first < l; first++){
if (list[first] < list[first - 1]){
temp = list[first];
location = first;
do {
list[location] = list[location - 1];
location--;
}
while(location > 0 && list[location - 1] > temp);
list[location] = temp;
}
}
System.out.println(binarySearch(list, l, item));
}
}
Thanks for the help!
You need to return mid + 1 as index start from 0.
So if you have 1,2,3 element and if you try to find 2, it will return 1 as array[1] points to 2. So if you return 2 it will mean that you found the element at second location.
Your issue lies here:
if (found)
return mid;
Say you have an array with numbers {1,2,3,4,5}
According to the way array indices get assigned 1 will get the index of 0, 2 will get the index of 1 and so on.
when you try to search for 2 and you find it, the value of mid(according to the program) holds the index of value 2 in the array. The index of 2 in the above array is 1. So instead of returning the index of 2, you just need to return the item itself.
if (found)
return list[mid];
I would say better design would be to return true/false from the binary search routine to indicate whether the item was found or not. The reason being you return 0 as the case where you never find the item in the array which becomes problematic if 0 is also included in the values to search.
If you were trying to return the index of item once found instead of the item itself, then your program functions as expected other than the case where it wasn't found - it should return something like an index of -1 and not 0(a valid index).
else
return 0;

Find majority element in an array in java

I am trying to find out the majority Element in an array ad this code is working fine when I am checking with elements less than size. But it is giving me arrayindexoutofbound exception whenever any element is equal to size of array. Please let me know how to resolve this.
public class MajorityElement {
public static void main(String[] args) {
int a[]={2,2,7,5,2,2,6};
printMajority(a, 7);
}
//1st condition to check if element is in majority.
public static int findCandidate(int a[], int size){
int maj_index=0;
int count =1;
int i;
size=a.length;
for(i=1;i<a.length;i++ ){
if(a[maj_index]==a[i])
count++;
else
count--;
if(count==0)
{
maj_index=a[i]; //current element takes max_inex position.
count =1;
}
}
return a[maj_index];
}
public static boolean isMajority(int a[], int size, int cand){
int i, count =0;
for(i=0;i<a.length;i++)
{
if(a[i]==cand)
count++;
}
if(count>size/2){
return true;
}
else {
return false;
}
}
private static void printMajority(int a[],int size){
size=a.length;
int cand=findCandidate( a, 7);
if(isMajority(a,size,cand))
System.out.printf("%d",cand);
else
System.out.println("no such element as majority");
}
}
The problem is in the maj_index=a[i]; line. You take the value of one of the cells of the array and assign it to maj_index which is subsequently used as an index into the array (see a[maj_index] == a[i]). Thus, if the value at that position was larger than the size of the array an out-of-bounds situation will occur.
Here's your code slightly revised. In particular, I got rid of the maj_index variable so that the index vs. value mixup cannot happen. I also used a for-each loop for (int current : a) instead of the for-loop for(int i = 0; i < a.length; ++i). Finally, I eliminated the the size parameter (no need to pass it, it can be inferred from the array itself via a.length)
public class MajorityElement {
// 1st condition to check if element is in majority.
public static int findCandidate(int a[]) {
int cand = a[0];
int count = 1;
for (int i = 1; i < a.length; i++) {
if (cand == a[i])
count++;
else
count--;
if (count == 0) {
cand = a[i];
count = 1;
}
}
return cand;
}
public static boolean isMajority(int a[], int cand) {
int count = 0;
for (int current : a) {
if (current == cand)
count++;
}
return count > a.length / 2;
}
private static void printMajority(int a[]) {
int cand = findCandidate(a);
if (isMajority(a, cand))
System.out.printf("%d", cand);
else
System.out.println("no such element as majority");
}
public static void main(String[] args) {
int a[] = { 9, 7, 9, 5, 5, 5, 9, 7, 9, 9, 9, 9, 7 };
printMajority(a);
}
}
Problem is with your :
for(i=1;i<a.length;i++ ){
if(a[maj_index]==a[i])
count++;
else
count--;
if(count==0)
{
maj_index=a[i]; //current element takes max_inex position.
count =1;
}
}
return a[maj_index];
here you are getting the value as like :a[maj_index] for a test data int a[]={2,1,8,8,8,8,6}; the elemnt 8 is the major but a[maj_index] is invalid which is causing the issue,
Instead Complete code can be like below:
public class TestMajor {
/**
* #param args
*/
public static void main(String[] args) {
int a[]={2,1,8,8,8,8,6};
printMajority(a, 7);
}
//1st condition to check if element is in majority.
public static int findCandidate(int a[], int size){
int test = a[0];
int count =1;
int i;
size=a.length;
for(i=1;i<a.length;i++ ){
if(test ==a[i])
count++;
else
count--;
if(count==0)
{
test =a[i]; //current element takes max_inex position.
count =1;
}
}
return test;
}
public static boolean isMajority(int a[], int size, int cand){
int i, count =0;
for(i=0;i<a.length;i++)
{
if(a[i]==cand)
count++;
}
if(count>size/2){
return true;
}
else {
return false;
}
}
private static void printMajority(int a[],int size){
size=a.length;
int cand=findCandidate( a, 7);
if(isMajority(a,size,cand))
System.out.printf("%d",cand);
else
System.out.println("no such element as majority");
}
}
Majority Element in an Array using Java 8 OR Find the element appeared max number of times in an array :
public class MajorityElement {
public static void main(String[] args) {
int[] a = {1,3,4,3,4,3,2,3,3,3,3,3};
List<Integer> list = Arrays.stream(a).boxed().collect(Collectors.toList());
Map<Integer, Long> map = list.parallelStream()
.collect(Collectors.groupingBy(Function.identity(),Collectors.counting()));
System.out.println("Map => " + map);
//{1=1, 2=1, 3=8, 4=2}
map.entrySet()
.stream()
.max(Comparator.comparing(Entry::getValue))//compare the values and get the maximum value
.map(Entry::getKey)// get the key appearing maximum number of times
.ifPresentOrElse(System.out::println,() -> new RuntimeException("no such thing"));
/*
* OUTPUT : Map => {1=1, 2=1, 3=8, 4=2}
* 3
*/
System.out.println("...............");
// A very simple method
//method 2
Integer maxAppearedElement = list.parallelStream().max(Comparator.comparing(Integer::valueOf)).get();
System.out.println(maxAppearedElement);
}//main
}

Categories

Resources