This question already has answers here:
How can I avoid ArrayIndexOutOfBoundsException or IndexOutOfBoundsException? [duplicate]
(2 answers)
Closed 7 years ago.
I found this problem on leetcode, I've solved it on my platform. For the tests I've used 1000 elements arrays, and never got an error. On leetcode platform it throws ArrayIndexOutOfBoundsException. If you look carefully, there is no way the elements a, b, or can n go further than array's length. This is the description of the problem:
Suppose a sorted array is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).
Find the minimum element.
You may assume no duplicate exists in the array.
public class Solution
{
public int findMin(int[] num)
{
int a = 0;
int b = num.length - 1;
int n = ( a + b ) / 2;
while ( true )
{
if ( num[n] < num[n+1] && num[n] < num[n-1] )
break;
if ( num[a] < num[b] )
{
b = n;
n = (a + n) / 2 + 1;
}
else
{
a = n;
n = ( b + n ) / 2;
}
}
return num[n];
}
}
public static int findMin(int[] num) {
return helper(num, 0, num.length - 1);
}
public static int helper(int[] num, int endLeft, int endRight) {
if (endLeft == endRight)
return num[endLeft];
if ((endRight - endLeft) == 1)
return Math.min(num[endLeft], num[endRight]);
int middleIndex = endLeft + (endRight - endLeft) / 2;
int middle = num[middleIndex]; // middle value
if (num[endLeft] < num[endRight]) {
return num[endLeft];
} else if (middle > num[endLeft]) {
// go right side
return helper(num, middleIndex, endRight);
} else {
// go left side
return helper(num, endLeft, middleIndex);
}
}
From coding interview.
Related
This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 1 year ago.
I'm trying to write the binary search algorithm, But Geeks for Geeks practice problem Binary Search yields following error:
Runtime Error:
Runtime ErrorException in thread "main" java.lang.ArrayIndexOutOfBoundsException:
Index 222 out of bounds for length 5
at Solution.binarysearch(GFG.java:44)
at GFG.main(GFG.java:22)
What I've written so far is,
class Solution {
int binarysearch(int arr[], int n, int k){
if (arr == null) return -1;
int begin = 0;
int end = k;
for (; begin < end;)
{
int mid = (begin + end) / 2;
if (arr[mid] == n) return mid;
if (arr[mid] > n)
{
// in left part
begin = begin; // for debug
end = mid;
}
else
{
// in right part
begin = mid + 1;
end = end; // for debug
}
}
return -1;
}
}
Geeks for Geeks problem statement&example:
Given a sorted array of size N and an integer K, find the position at
which K is present in the array using binary search.
Example 1:
Input: N = 5 arr[] = {1 2 3 4 5} K = 4
Output: 3
Explanation: 4 appears at index 3.
Replace int end = k; to int end = n-1;
k is the number you have to find, n is the array size
I am a beginner(first year uni student) programmer trying to solve this problem which i'm finding somewhat difficult. If you are to answer this question, don't provide me with a complex daunting algorithm that will leave me scratching my head. I'll really appreciate it if you explain it step my step (both logically/conceptually then through code)
The problem is as follows:image
I have tried to attempt it and my code only works for a certain case that i tested.
package com.company;
import java.lang.Math;
public class Main {
public static int[][] binary_partition(int array[], int k){
int x = (int) Math.pow(2,k);
int[][] partition = new int[((array.length/x)*2)][array.length/x];
int divisor = array.length/x;
if ((array.length % 2) != 0){
return partition;
}
if (divisor >= array.length-1){
return partition;
}
if (k==1){
return partition;
}
int p = 0;
for(int i=0;i<((array.length/x)*2);i++)
{
for (int j = 0; j<array.length/x;j++)
{
partition[i][j] = array[p];
p += 1;
}
}
return partition;
}
public static void main(String[] args){
int[] array = {3, 2, 4, 7, 8, 9, 2, 3};
int[][] result = binary_partition(array,2);
for (int[] x : result){
for (int y : x)
{
System.out.print(y + " ");
}
System.out.println();
}
}
}
Your question is unclear, but this solution creates a function that partitions an array with the right length into 2^k sets.
First, an interesting fact: using the bitshift operator << on an integer increases its value by a power of two. So to find out the size of your partition, you could write
int numPartitions = 1 << k; // Equivalent to getting the integer value of 2^k
With this fact, the function becomes
public static int[][] partition(int[] set, int k) {
if (set == null)
return null; // Don't try to partition a null reference
// If k = 0, the partition of the set is just the set
if (k == 0) {
int[][] partition = new int[1][set.length];
// Copy the original set into the partition
System.arraycopy(set, 0, partition[0], 0, set.length);
return partition;
}
int numPartitions = 1 << k; // The number of sets to partition the array into
int numElements = set.length / numPartitions; // The number of elements per partition
/* Check if the set has enough elements to create a partition and make sure
that the partitions are even */
if (numElements == 0 || set.length % numElements != 0)
return null; // Replace with an error/exception of your choice
int[][] partition = new int[numPartitions][numElements];
int index = 0;
for (int r = 0; r < numPartitions; r++) {
for (int c = 0; c < numElements; c++) {
partition[r][c] = set[index++]; // Assign an element to the partition
}
}
return partition;
}
There are a few lines of your code where the intention is not clear. For example, it is not clear why you are validating divisor >= array.length-1. Checking k==1 is also incorrect because k=1 is a valid input to the method. In fact, all your validation checks are not needed. All you need to validate is that array.length is divisible by x.
The main problem that you have seems to be that you mixed up the lengths of the resulting array.
The resulting array should have a length of array.length / x, and each of the subarrays should have a length of x, hence:
int[][] partition = new int[array.length/x][x];
If you also fix your bounds on the for loops, your code should work.
Your nested for loop can be rewritten as a single for loop:
for(int i = 0 ; i < array.length ; i++)
{
int index = i / x;
int subArrayIndex = i % x;
partition[index][subArrayIndex] = array[i];
}
You just need to figure out which indices a an element array[i] belongs by dividing and getting the remainder.
I have a public static int Dlist[ ][ ] declared in the class and the below mentioned functions are written.
I saw a similar code (only the basic mergesort code on GeeksforGeeks) where they take k = 1 and their code works completely welll. where as, my does something but the result is not what is expected. i am not able to understand why k=1 working ?
I'd like to know two things.
1) why k = 1 works (https://www.geeksforgeeks.org/java-program-for-merge-sort/)
Shouldn't it be k = 0 and instead of arr[k] it should have been arr[l+k]
2) What is the problem in my code? Why is it not doing anything?
*Also LI is left indes, RI is right index, MI is middle index, ii is for Dlist[ ][ii]
public static void mergeSort(int Dlist[][], int ii, int li, int ri)
{
if(ri > li)
{
int m = (li+ri)/2;
mergeSort(Dlist, ii, li, m);
mergeSort(Dlist, ii, m + 1, ri);
Merge(Dlist, ii, li, m, ri);
}
}
public static void Merge(int Dlist[][], int ii, int li, int m, int ri)
{
int la[][] = new int[m-li+1][2];
int ra[][] = new int[ri-m][2];
int i,j,k;
for(i = 0; i < m-li+1; i++)
{
la[i][0] = Dlist[li+i][0];
la[i][1] = Dlist[li+i][1];
}
for(i = 0; i < ri-m; i++)
{
ra[i][0] = Dlist[m+i+1][0];
ra[i][1] = Dlist[m+i+1][1];
}
i = 0; j = 0; k = 0;
while ((i < m-li+1) && (j < m-ri))
{
if(la[i][ii] < ra[j][ii])
{
Dlist[(li+k)][ii] = la[i][ii];
if(ii == 1)
{
Dlist[(li+k)][0] = la[i][0];
}
i++;
k++;
}
else
{
Dlist[(li+k)][ii] = ra[j][ii];
if(ii == 1)
{
Dlist[(li+k)][0] = ra[j][0];
}
j++;
k++;
}
}
while (i < m-li+1)
{
Dlist[li+k][ii] = la[i][ii];
if(ii == 1)
{
Dlist[li+k][0] = la[i][0];
}
i++;
k++;
}
while (j < m-ri)
{
Dlist[li+k][ii] = ra[j][ii];
if(ii == 1)
{
Dlist[li+k][0] = ra[j][0];
}
j++;
k++;
}
}
The aim of the code is to convert this :-
*The sorting is done with respect to Dlist[ ][1] in descending order.
2 4 5 7 8
4 2 7 9 1
into this :-
7 5 2 4 8
9 7 4 2 1
But the functions don't do anything.
Final Update :-
I was able to make the same code work by copying Dlist[][1] to another array. Then applying those functions on this new copied array and in merge function, while modifying copied array, i made same modifications in Dlist. Don't know why it worked that way. But that worked for me.
It's not k = 1, it's k = l (in upper case K = L).
mergeSort(Dlist, ii, m + 1, mi); should be mergeSort(Dlist, ii, m + 1, ri);
Regardless if ii == 0 or ii == 1, merge should always copy DList[..][0] and DList[..][1].
The code would be simpler if ri was the ending index (last index + 1), eliminating all the +1 in the code. You could change the index names to bgn or bi (instead of li) and end or ei (instead of ri).
Take a look at the wiki example for top down merge sort. It does a one time copy of the original array, into a one time allocated working array, then swaps the array names in the recursive calls so that the direction of merge corresponds to the level of recursion, eliminating the need to create sub-arrays or copy back. It also passes the beginning and ending indexes (as opposed to beginning and last index), and in the initial call beginning index = 0 and ending index = size of array (n).
https://en.wikipedia.org/wiki/Merge_sort#Top-down_implementation
I'm looking a simple solution to get the minimum number "ArrayList of Integers" needed to have all numbers from 1 to n, with the next condition:
Each ArrayList must be created from 3 parameters (a, b and n)
"a" and "b" set the numbers in the ArrayList
"n" is the limit
The condition is:
If a ≤ b ===> a ≤ j ≤ b
if a>b ===> 1 ≤ j ≤ b and a ≤ j ≤ n
Note: "j" are the numbers on the ArrayList.
this is my code:
public Integers(int a, int b, int n) {//constructor
this.numbers = new ArrayList<Integer>();
makeList(a, b, n);
}
public void makeList(int a, int b, int n) {
if (a < b) {
while (a <= b) {
this.numbers.add(a);
a++;
}
} else {
int aux = 1;
while (aux <= b) {
this.numbers.add(aux);
aux++;
}
int aux2 = a;
while (aux2 <= n) {
this.numbers.add(aux2);
aux2++;
}
}
}
public void showNumbers() {
for (int x = 0; x < this.numbers.size(); x++) {
System.out.print(this.numbers.get(x) + "\t");
}
}
this is an example with n=20:
public static void main(String[] args) {
Integers first= new Integers(1, 10, 20);
first.showNumbers();//1 2 3 ...8 9 10
System.out.println();
Integers second= new Integers(15, 5, 20);
second.showNumbers();//1 2 3 4 5 15 16 17 18 19 20
System.out.println();
Integers third= new Integers(15, 20, 20);
third.showNumbers();//15 16 17 18 19 20
System.out.println();
Integers fourth= new Integers(4, 17, 20);
fourth.showNumbers();//4 5 6 ... 15 16 17
System.out.println();
System.out.println("Solution expected is: 2 ====> <second and fourth>");
}
and the answer that I expect is 2 (second and fourth).
If you know what n is from the start, it might be simpler to store a boolean array of n values. Then every time you construct an ArrayList, you just mark off if that value would appear in the ArrayList.
Other than this, you pretty much would have to brute-force (I think this would be equivalent to the vertex-cover problem so you'd at best be able to approximate in faster times than brute-forcing).
Hence, I'd try this implementation of your Integer class:
public class Integer {
private int a, b;
private boolean flipped;
public Integer(int _a, int _b){
a = Math.min(_a, _b);
b = Math.max(_a, _b);
flipped = b < a;
}
public void markOff(boolean [] arr){
for(int i = 0; i < arr.length; i++){
if(a <= i && i <= b){
arr[i] = arr[i] || !flipped;
}else{
arr[i] = arr[i] || flipped;
}
}
}
}
So in the above, markOff just checks if each index would appear in the ArrayList you'd create (I'll leave figuring out the boolean logic up to you, but the idea is just to set all the extra elements to true as necessary - so if a new index is covered by the array, you'd mark it off, but you don't un-mark already marked ones.) You can optimize it to not traverse the whole array and look more like your makeList if you want to.
In order to find the minimal set of arrays that would cover up to n, you'd have to do something like the following:
public static int driveSoln(int n, Integer[] covers){
return helper(covers, new boolean[n], 0, 0);
}
private static int helper(Integer[] covers, boolean[] marked, int idx, int used){
boolean done;
for(boolean d: marked) done = done && d;
if(done) return used;
if(idx >= covers.length) return -1;
boolean [] markCopy = marked.clone();
covers[i].markOff(marked);
int dontUse = helper(covers, markCopy, idx + 1, used);
int use = helper(covers, marked, idx + 1, used + 1);
return Math.min(use, dontUse);
}
Intuitively, what I do here is for each inputted cover, chose whether or not to use it and keep looking at the rest. The recursion here "remembers" my choices. I'm guaranteed to (sadly) check all the choices, so this is quite slow, but definitely right. An optimization might be to ignore subsets: if an array only covers items already covered by 1 array, discard it.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I know one possible way of achieving this:
int a = 7;
int b = -10;
public int makeSmaller(int num) {
int result = Math.abs(num) - 1;
if(num > 0) return result;
else return -result;
}
makeSmaller(a); //returns 6
makeSmaller(b); //returns -9
Are there any more concise way of doing this could use to make this a little cleaner?
EDIT
I want the method to return a result closer to zero by exactly 1, so dividing by 2 or any other number won't work. Neither will multiplying by 0.
Using signum:
public static int makeSmaller(int val) {
return val-Integer.signum(val);
}
Using Math.abs doesn't gain you anything, since you are testing the sign anyway.
Thus, a more concise formulation:
public int makeSmaller(int num) {
return num > 0? num-1 : num+1;
}
Since you say you want to make it closer to zero, you should also check the zero case:
public int towardZero(int num) {
if (num == 0) return 0;
else return num > 0? num-1 : num+1;
}
public int makeSmaller(int num) {
int result = Math.abs(num) - 1;
if(num > 0) return result;
else return -result;
}
Why not just this?
public int makeSmaller(int num) {
return num - (num/Math.abs(num));
}
The parenthetical part will always have the same sign as the number, and will always be 1 (plus or minus).
So, given 7...
7 - (7/|7|) = 7 - 1 = 6
Given -10...
-10 - (-10/|-10|) = - 10 - (-10/10) = -10 - (-1) = -10 + 1 = -9
Not very readable, but working:
int q = -10;
final int s[] = new int[]{-1, 1};
q += s[(q>>>31)];
System.out.println(q); // print -9
int q = 10;
final int s[] = new int[]{-1, 1};
q += s[(q>>>31)];
System.out.println(q); // print 9
So you can rewrite your function as:
final static int[] signsInc = new int[]{-1, 1};
public static int makeSmaller(final int num) {
return (num != 0) ? (num + signsInc[(num>>>31)]) : 0;
}