index 4 is out of bounds for 4 length - java

package dsa450;
import java.util.*;
public class countInversion {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("Enter the size of Array");
int n=sc.nextInt();
int arr[]=new int[n];
System.out.println("Enter the size of Array");
for(int i=0;i<n;i++){
arr[i]=sc.nextInt();
}
int p=arr.length;
int temp[]=new int[n];
int ans=mergeSort(arr,temp,0,n-1);
System.out.println(ans);
}
static int mergeSort(int[] arr,int[]temp,int l,int r) {
int inv=0;
int mid;
if (l<r) {
mid=(l+r)/2;
inv+= mergeSort(arr,temp,l, mid);
inv+= mergeSort(arr,temp,mid+1,r);
inv+= merge(arr,temp,l,mid+1,r);
}
return inv;
}
private static int merge(int []arr,int []temp,int l,int mid,int r) {
int i=0;
int j=0;
int k=0;
int swap=0;
while(i<=mid-1 && j<=r) {
if(arr[i]<=arr[j]) {
temp[k++]=arr[i++];
}
else {
temp[k++]=arr[j++];
swap+=(mid-i);
}
}
while(i<=mid-1) {
temp[k++]=arr[i++];
}
while(j<=r) {
temp[k++]=arr[j++];
}
for(i=l;i<=r;i++) {
arr[i]=temp[i];
}
return swap;
}
}
enter image description here
this is my code I am trying to solve it for 5 hours but I am not getting what is the problem can anybody help. I check resources also but the code is the same as a source but it is not running.

Hints:
The actual error is that you are attempting to get an array element 1 position beyond the end of the array. (Array indexes go from 0 to array.length - 1.)
Use the line numbers in the stacktrace to work out exactly which line of your code the exception occurs on. It is happening in an array indexing operation in the merge method. There are 6 lines where that could be happening.
Add some trace prints to print out the values of critical variables at key points in the merge method; e.g. what l, r and mid are, and what i, j and k are.
Run the modified code, look at the values output by the trace prints, and try to visualize what the code is doing.
Spot where and why you are going beyond the end of an array ... and figure out what you need to change.

Your merge method is failing because you are not validating k against size of temp array.
I am suggesting below small modifications in your merge method which will give you correct answer:
while (i <= mid - 1 && j <= r && k<temp.length) {
if (arr[i] <= arr[j] ) {
temp[k++] = arr[i++];
} else {
temp[k++] = arr[j++];
swap += (mid - i);
}
}
while (i <= mid - 1 && k < temp.length) {
temp[k++] = arr[i++];
}
while (j <= r && k < temp.length) {
temp[k++] = arr[j++];
}

Related

Why do we use two different loop variables while sorting an array using merge sort?

I was learning to merge sort an integer array, when I noticed that while copying the sorted array elements to the original array, we need two separate loop variables to run simultaneously, while the values at those indices are copied to the original array. Here is the code for reference:
class MergeSort {
public static void sort(int arr[], int si, int ei, int mid) {
int merged[] = new int[ei - si + 1];
int index1 = si; // tracks the first array
int index2 = mid + 1; // tracks the second array
int i = 0;
while (index1 <= mid && index2 <= ei) {
if (arr[index1] <= arr[index2]) {
merged[i++] = arr[index1++];
} else {
merged[i++] = arr[index2++];
}
} // end of while
while (index1 <= mid) {
merged[i++] = arr[index1++];
}
while (index2 <= ei) {
merged[i++] = arr[index2++];
}
// to copy merged[] to arr[]
int j = si;
for (i = 0; i < merged.length; i++, j++) {
arr[j] = merged[i];
}
} // end sort()
public static void divide(int arr[], int si, int ei) {
// base case
if (si >= ei) {
return;
} // end of base case
int mid = si + (ei - si) / 2; // same as (ei-si)/2 but with less space complexity
divide(arr, si, mid);
divide(arr, mid + 1, ei);
sort(arr, si, ei, mid);
} // end of divide
public static void main(String args[]) {
int arr[] = { 1, 8, 0, 7, -4 };
int n = arr.length;
divide(arr, 0, n - 1);
for (int i = 0; i < n; i++) {
System.out.print(arr[i] + " ");
} // end of for
} // end of main
} // end of class
Notice that while copying the values of the array merged[] to the array arr[], we are using two separate variables i and j. I did try using only one loop variable, which went like:
for (int i = 0; i < arr.length; i++) {
arr[i] = merged[i];
}
but received an incorrect output. If anyone knows why we need two separate variables for the operation, please let me know. Thank you :)
You could use a single variable in this final loop, but you must add the offset of the start of the slice in the destination array:
for (int i = 0; i < arr.length; i++) {
arr[si + i] = merged[i];
}

Recursive in Merge Sort

public static void main(String[] args) {
int[] numbers = {20,4,7,6,1,3,9,5};
mergeSort(numbers);
}
private static void mergeSort(int[] inputArray) {
int inputLength = inputArray.length;
System.out.println(inputLength);
if (inputLength < 2)
return;
int midIndex = inputLength / 2;
int[] leftHalf = new int[midIndex];
int[] rightHalf = new int[inputLength - midIndex];
for (int i = 0; i < midIndex; i++) {
leftHalf[i] = inputArray[i];
}
for (int i = midIndex; i < inputLength; i++) {
rightHalf[i - midIndex] = inputArray[i];
}
mergeSort(leftHalf);
mergeSort(rightHalf);
merge(inputArray, leftHalf, rightHalf);
}
private static void merge(int[] inputArray, int[] leftHalf, int[] rightHalf) {
int leftSize = leftHalf.length;
int rightSize = rightHalf.length;
int i = 0, j = 0, k = 0;
while (i < leftSize && j < rightSize) {
if (leftHalf[i] <= rightHalf[i]) {
inputArray[k] = leftHalf[i];
i++;
} else {
inputArray[k] = rightHalf[j];
j++;
}
k++;
}
while (i < leftSize) { //eğer karşılaştırılmayan bir tane kalırsa diye yapılıyor yani
inputArray[k] = leftHalf[i];
i++;
k++;
}
while (j < rightSize) {
inputArray[k] = rightHalf[j];
j++;
k++;
}
}
In the mergeSort part if inputLength < 2 part of the code, we return when the length is less than 2. And last time the inputLength was 1, it becomes 2 and returns to the array [20,4].
This did not make sense to me logically. How does it get back to [20,4] when last we had [20] left?
first of all the code you have shared is flawed in the merge function part, you can find the proper code for Merge sort online, you can refer to
https://www.geeksforgeeks.org/java-program-for-merge-sort/
Now for understanding merge sort you have to understand the concept of stack (Last in First out) & recursion. In recursion the lines after the recursive call wait till the recursive call to the function has not executed completely. So in case of the
1st call Merge sort the length of the array is n and waiting for the complete execution of mergeSort(leftHalf) and mergeSort(rightHalf) both of size (n/2).
now for both the mergeSort(leftHalf) and mergeSort(rightHalf)
there will be sub left part and sub right part and this will continue till the size of the array becomes <2 and the remaining part will wait.
and after the successful execution of the smallest part it will return to the previous part from where this part was called. By this eventually this will return to the place where the function was called first.
And in case of your code both the smaller arrays are merged into the larger array so the data of the left and right sub array aren't lost.

Why does my bubble sort method not work?

Sorry I am still learning programming. Java just stops and seems to be processing something. It says "Building java application Javaapplication2" then just sits there doing nothing. What have a I done to cause this ?
package javaapplication2;
public class JavaApplication2 {
public static void main(String[] args) {
int a [] = {1,2,3};
int c [] = Sortarray.sortlowhigh(a);
int i = 0;
while (i<c.length){
System.out.println("array is" + c[i]);
i++;
}
}
}
package javaapplication2;
public class Sortarray {
public static int[] sortlowhigh(int a[])
{
int i = 0;
int j = 0;
while(j<a.length){
while(i<a.length){
if (a[i]>a[i+1]){
/* store low value in temp*/
int temp = a[i+1];
/* assign low value to be the higher value*/
a[i+1] = a[i];
/* assign the old higher value to be the lower value stored in temp*/
a[i]=temp;
}
j++;
}
}
return a;
}
}
My code is above. A while ago I wrote a sort and remove duplicates method now I want to put them into a class but I am doing something wrong. Please help. Thanks.
I try your code and I can see that you have a infinite loop in the class Sortarray. The variable i is never increased.
Try this code:
public static int[] sortlowhigh(int a[])
{
int i = 0;
int j = 0;
int temp;
while(j< (a.length -1) ){
i = 0;
while(i< (a.length - j - 1)){
if (a[i] > a[i+1]){
/* store low value in temp*/
temp = a[i];
/* assign low value to be the higher value*/
a[i] = a[i+1];
/* assign the old higher value to be the lower value stored in temp*/
a[i+1]=temp;
}
i++;
}
j++;
}
return a;
}
In the sortlowhigh while loop you have i, i < a.lenght is the condition of the second loop and it will continue until i is >= a.length but i never changes it always stay 0.
/*change your code as given*/
public static int[] sortlowhigh(int a[]){
int i = 0;
int j = 0; int temp=0;
while(j<(a.length-1))
{
i=0;
while(i<a.length-j-1)
{
if(a[i]>a[i+1])/* For descending order use < */
{
temp = a[i];
a[i]=a[i+1];
a[i+1] = temp;
}
i++;
}
j++;
}
return a;
}
you should reset the value of i, when the value of j is incremented.
The array is of size 3. but the value of i is already 3. so it gets garbage value in a[i+1].
Hope this helps. I haven't tried the code.

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
}

Find the first occurrence of an odd and count them

import java.util.*;
public class FirstOddOccurrence {
public static void main(String[] args) {
int[] x = {2, 4, 6, 7, 4, 3, 2, 7, 6, 7, 7};
int i;
display(x);
System.out.printf("# Occurrences of first odd = %3d\n", firstOddCount(x));
}
private static void display(int[] x) {
int i;
System.out.print("Array: ");
for (i = 0; i < x.length; i++) {
if (i < x.length - 1)
System.out.printf("%3d, ", x[i]);
else
System.out.printf("%3d\n", x[i]);
}
}
public static int odd(int[] x) {
int i;
int y;
for (i = 0; i < x.length; i++) {
y = x[i] % 2;
if (y == 1) {
return x[i];
} else {
return 0;
}
}
return x[i];
}
public static int firstOddCount(int x[]) {
int i;
int c = 0;
for (i = 0; i < x.length; i++) {
if (x[i] == odd(x))
c++;
}
return c;
}
}
I'm trying to find the first occurrence of an odd number in the array that has been provided. What is wrong with my program? I can't seem to get the program to count the first odd occurrences.
Your code here:
if (y == 1) {
return x[i];
} else {
return 0;
}
does not work - if a tested number is even, you immediately return 0. Instead you want to skip these even numbers and wait until an odd number comes up. In the end, if you don't find any odd number, you return 0. Here is the corrected version of odd():
int i;
int y;
for (i = 0; i < x.length; i++) {
y = x[i] % 2;
if (y == 1) {
return x[i];
}
}
return 0;
Andr's solution fixes your issue; odd(x) will return 0 if x[0] is even, and x[0] if it is odd.
You could also improve firstOddCount like so: odd(x) will always return the same value, so only calculate it once.
public static int firstOddCount(int x[]) {
int firstOdd = odd(x);
int c=0;
for(int i=0; i < x.length; i++) {
if (x[i]==firstOdd)
c++;
}
return c;
}
Your particular problem is that you return 0 if you find an even number. That means that the list {2, 4, 6, 8, 1} will give you 0, rather than 1, as the first odd number.
What you should do is ignore leading even numbers and continue to process the list.
However, the way you've organised your program, you're processing the first all-even part of the list twice, once in odd() to find the first odd number, then again in firstOddCount() to count how many of that number there are - that's totally unnecessary.
Once you find the first odd number, I think you can be reasonably certain that number (or any other odd number for that matter) does not exist in the space you've already searched. Otherwise it would have been the first odd number. Hence it makes little sense to go back and look at that initial part of the list again.
A way in which you can easily just process the list once is as follows:
public static int firstOddCount (int numbers[]) {
// Find first odd number or end of list.
int idx = 0, len = numbers.length;
while ((idx < len) && ((numbers[idx] % 2) == 0)
idx++;
// If at end of list, everything is even => count(first(odd)) is 0.
if (idx == len)
return 0;
// Otherwise, start counting from current position.
int count = 1, oddnum = numbers[idx];
while (++idx < len)
if (numbers[idx] == oddnum)
count++;
return count;
}
If you are trying to get one element from group you should use 'break' when your condition matched first time else it will give all...

Categories

Resources