Why no out of bounds error on for loop (Java) - java

I'm doing a problem on codingbat.com and am confused with why this solution to the problem does not give an index out of bounds error. Wouldn't the first for loop search for an index that is beyond the length of the passed array?
Here's the problem:
We'll say that a value is "everywhere" in an array if for every pair of adjacent elements in the array, at least one of the pair is that value. Return true if the given value is everywhere in the array.
Here's my working solution:
public boolean isEverywhere(int[] nums, int val) {
boolean flag1 = true;
boolean flag2 = true;
for (int i = 0; i < nums.length; i += 2) {
if (nums[i] != val) flag1 = false;
}
for (int i = 0; i < nums.length - 1; i += 2) {
if (nums[i + 1] != val) flag2 = false;
}
return flag1 || flag2;
}
Thanks!

No. The test happens after i is incremented. So, once i is not less than the length of the nums array the loop stops. The second loop uses i + 1 at if (nums[i + 1] != val) which is why it needs to test that i is less than the length minus one.
Also you can make the method static (since it uses no instance state).

It wouldn't because while i += 2 is written after i < nums.length, the loop still checks that i is less than the given length(nums.length) before going onto the body of the loop even after 2 has been added on.

Related

Why I am returning the wrong output?

I am not sure why I am returning false for the first test run as shown in the test table attachment. This was one of my assignments last semester and I never figured out how to solve it:/ My assignment was to:
Write the definition of a method , oddsMatchEvens, whose two parameters are arrays of integers of equal size. The size of each array is an even number. The method returns true if and only if the even-indexed elements of the first array equal the odd-indexed elements of the second, in sequence. That is if w is the first array and q the second array , w[0] equals q[1], and w[2] equals q[3], and so on.
Test table
My code was:
public boolean oddsMatchEvens(int[] w, int[] q) {
int count = 0;
for (int i = 0; i < w.length; i++) {
if (w[i] == q[i + 1])
count++;
if (count == (w.length - 1))
return true;
}
return false;
}
if (count == (w.length - 1))
return true;
This is wrong, since you have only w.length/2 indices which you have to compare.
You should just return false, if w[i] != q[i+1].
And you should increase i by 2, not by 1.
There are two problems with the code:
Firstly, it is clearly mentioned the two input arrays are of equal length and you have to compare them even index to odd index. So the corner case occurs when you are checking last item of first array with last+1 item of second array(which doesn't exist as arrays are of equal length.
Secondly, you have to check first array even with second array odd so increment should be i+=2 and not i++.
Correct code with optimization(if one check fails you can come out of loop):
public boolean oddsMatchEvens(int[] w, int[] q) {
for (int i = 0; i < w.length-1; i+=2) {
if (w[i] != q[i + 1])
return false;
else
continue;
}
return true;
}
public boolean oddsMatchEvens (int []w, int []q) {
for (int j = 0; j < w.length-1; j+=2) {
if (w [j] != q [j+1])
return false;
continue;
}
return true;
}

How would I find the index of the smallest value in an int array?

I'm fairly new to java so I would like to keep it simple, and I figure I would have to take the first value of the array then compare it to each following value and if the value is larger smaller than the first, replace the value with it, but I don't know how to get index from that.
For an unstructured, unsorted array the best you can do, assuming you are only going to find the minimum value once, is a simple iteration over all elements (O(n) complexity), like so:
public int findMinIdx(int[] numbers) {
if (numbers == null || numbers.length == 0) return -1; // Saves time for empty array
// As pointed out by ZouZou, you can save an iteration by assuming the first index is the smallest
int minVal = numbers[0] // Keeps a running count of the smallest value so far
int minIdx = 0; // Will store the index of minVal
for(int idx=1; idx<numbers.length; idx++) {
if(numbers[idx] < minVal) {
minVal = numbers[idx];
minIdx = idx;
}
}
return minIdx;
}
Also, in the case of a tie for minimum value, this method will return the index of the first case of that value it found. If you want it to be the last case, simply change numbers[idx] < minVal to numbers[idx] <= minVal.
Here is with Java 8
public static int findMinIdx(int[] numbers) {
OptionalInt minimun = IntStream.of(numbers).min();
return IntStream.of(numbers).boxed().collect(toList()).indexOf(minimun.getAsInt());
}
Never cared about run time optimization, was just looking for a solution!, this worked and this would help you too, finding the index of the lowest values in an array.
// array[] -> Received the array in question as an parameter
// index -> stores the index of the lowest value
// in for loop, i is important to complete all the comparison in the function
// When it finds a lower value between the two, it does not change the index
// When it finds a lower value it changes it's index to that index
// If array has same value more than once, it will provide index to that values last occurrence
// Correct me if you find anything not working in this example...
//...
private static int index_of_minimum_value(int[] array) {
int index = 0;
for (int i = 1; i < array.length; i++) {
if ((array[i - 1] < array[i]) && ([index] > array[i - 1])) index = i - 1;
else if (array[index] > array[i]) index = i;
}
return index;
}

View if a word's letters are in ascending order

I've been at this for a while, but as the title says, I'm trying to create a method that will compare each letter to the letter after it and see if the word is ascending. The method should then return a boolean value. But when it's implemented in my code, it will fail with:
java.lang.StringIndexOutOfBoundsException: String index out of range: 1
at java.lang.String.charAt(Unknown Source)
and multiple other lines of error code.
Here's my source code:
public static boolean ascending(String word){
int i = 0;
boolean ascend;
do {
if (word.charAt(i) <= word.charAt(i+1))
ascend = false;
else
ascend = true;
} while (i <= word.length());
i = 0;
return (ascend);
}
I can't see where I'm going wrong?
condition should be
i < word.length()-1
and the i = 0; at the end should be in side the loop as i++, else it will be infinite loop.
also, you have actually put the reverse check. once you fix ArrayIndexOutOfBoundsException you will return false for ascending string and true otherwise
public static boolean ascending(String word){
if(word == null || word.length <2) return false;
int i = 0;
boolean ascend = false;
while(i < word.length()-1){
if (word.charAt(i) <= word.charAt(i+1))
ascend = true;
else{
ascend = false;
break;
}
i++;
}
return (ascend);
}
In pseudo code:
take the first letter (F) => store it
take the next letter (N) => check against first => stop here if not OK
is there another next letter => stop here if not
update first letter (F) with next letter (N)
repeat starting from 2
Few things needs to be fixed here:
You need to increment "i" to traverse through the word.
Restrict your while loop till (i < word.length() )
You may break at any point when you find ascend is false. No need to continue with the looping.
I would not use a do while because there is an opportunity to run this on an empty string causing it to crash. I would instead use a regular while and at the beginning test for while (i < word.length()-1). You never want to test past the end of the string. You always want to check to see for a string length of n that charAt(n-1) < charAt(n). Also I don't see an incrementer to increase the value of i. Loop will never continue on to the next letter and will run forever.
public static boolean ascending(String word){
int i = 0;
boolean ascend;
while (i < word.length()-1)
{
if (word.charAt(i) <= word.charAt(i+1))
ascend = false;
else
ascend = true;
i++;
}
i = 0;
return (ascend);
}
Do not use do-while loop. Even if you do you need to run some checks beforehand to make sure your word has length more than 1 otherwise your code will raise an IndexOutOfBounds Exception. If you insist on using it, change your condition to i
Here is a working code example:
public boolean isAscending(String word){
if (word==null || word.length==0){
return false;
}
for (int i=1; i<word.length(); i++){
if (word.charAt(i) < word.charAt(i-1))
return false;
}
return true;
}

Boolean with loops to check an array

Write Java code for a loop that sets boolean variable isOrdered to true if the elements of a given array of ints called are in non-decreasing order, otherwise it sets isOrdered to false.
int i[] = { 1, 2, 3, 4, 5 };
int b = 0;
boolean isOrdered = false;
while (b < i.length) {
if (i[0] <= i[b]) {
isOrdered = true;
}
b++;
}
out.println(isOrdered);
Am I doing this correctly?
Let's see what is wrong.
if (i[0] <= i[b])
This is the main area which troubles me with your code. How are you checking if the next value you is lower/higher then i[b] you are only comparing values at index zero to index b!
Essentially your code would look like this in a loop.
/w int i[] = { 1, 2, 3, 4, 5 };
i[0] i[b]
1 1
1 2
1 3
...
you get the picture right? What you really need is to check the next value after b.
so the code would look like i[b] > i[b+1]
Honestly, you could probably make it work on how you initialized the order of isOrdered to true and false. I would first initialize it to true. Then the idea is to break out of whatever process you are doing if you find a fallacy in the question with a false. Please look at my examples for further references.
iterative
boolean isOrdered = true;
while(isOrdered && array.length - 1 > b){
if(array[b] > array[b+1]) isOrdered = false;
b++;
}
recursive
boolean isOrdered(int[] array, index){
if(index == array.length - 1) return true;
if(array[index] > array[index + 1]) return false;
return isOrdered(array, index + 1);
}
The recursive method for this is waaaaaaaaaay cooler.
No; you are only checking whether the first element of the array is smaller than or equal to at least one of the elements - including the first element itself, which will always be equal to itself, setting isOrdered to true no matter what the remaining elements are.
Hint #1: you should be comparing every element except the first one with the element immediately before it.
Hint #2: you should be optimistic and assume that the array is ordered, then search for a counter-example. As soon as you found a pair of elements that violate the ordering, set isOrdered to false and break out of the loop.
do a for loop on the size of the array to check if the next item is less then the current:
int arr[] = { 1, 2, 3, 4, 5 };
int b = 0;
boolean isOrdered = true;
for (int i = 0; i< arr.length - 1 ; i ++) {
if (arr[i] > arr[i+1])
{
isOrdered = false;
break;
}
b++;
}
out.println(isOrdered);

(Java) Check array for increasing elements

I'm attempting to create a method that checks an array for increasing elements. True should be returned if all the elements are in increasing order. I get an out-of-bounds exception when I compare arr[i+1]. Any ideas on how I can make it work.
int[] one = {1,2,3,4,5};
public static boolean isIncreasing(int[]arr)
{
boolean z = false;
for(int i=0; i<arr.length;i++)
{
if(arr[i]<arr[i+1])
{
z = true;
}
}
return z;
}
Because in a list with n items there are only n-1 gaps between them.
Change to
for (int i=0; i<arr.length-1; i++)
(Also you might want to check whether starting with false and setting to true is the right way around).
You have two problems:
Your loop is one iteration too long: Because you are checking element i+1, i needs to finished incrementing one iteration earlier than a usual loop.
Your logic is flawed. Your loop will terminate the first time the check is true, so this array will pass: {1, 2, 0} when tested the first iteration tests 1 < 2 which is true, so return true - this is not what we want)
Fixing these two problems:
int[] one = {1,2,3,4,5};
public static boolean isIncreasing(int[] arr) {
for(int i=0 ; i < arr.length - 1; i++) { // finish at length - 1
if (arr[i] > arr[i+1]) {
return false; // found elements that are out of order - return false
}
}
return true; // nothing out of order found - return true
}
This kind of logic - with an early exit with false on problem and a final return of true - is very common and a good pattern to learn.
I suggest you write your method like this
public static boolean isIncreasing(int[]arr)
{
for(int i=1; i<arr.length;i++)
{
if(arr[i-1]>arr[i])
return false;
}
return true;
}
it will help
return the proper result (yours returns true when it should not)
consider out of bounds
avoid unnecessary looping
You get that exception as when (i+1)'s value becomes array.length. For example if you have an array of length 10, the elements indexes will be from 0,1,2...till 9. so either you have to check till i < arr.length - 1 or you can modify your logic accordingly.
You can use Java 8's IntStream.
import java.util.stream.IntStream;
public class Test {
public static boolean isIncreasing(int[] a) {
return IntStream.range(1, a.length).reduce(0, (acc, e) -> acc + (a[e - 1] <= a[e] ? 0 : 1)) == 0;
}
}

Categories

Resources