What is the difference between these two sections of code? - java

First example
int windowStart = 0;
for (int i = 0; i + windowSize < fileArray.size(); i++) {
ArrayList <Character> window = new ArrayList <Character> ();
for (int s = windowStart; s <= windowStart + windowSize; s++) {
window.add(fileArray.get(s));
}
windowStart++;
}
VS.
second example
int ind = 0;
for (int i = 0; i + windowSize < fileArray.size(); i++) {
for (int b = ind; b <= windowSize + ind; b++) {
window.add(fileArray.get(b));
}
ind++;
}
The first one throws an java.lang.IndexOutOfBoundsException while the second one does not and works just fine. fileArray is the same for both, but for 2. the window array is defined as an attribute, while for the first one, the "window" array is defined inside the method (and the for loop). Does that make a difference?

You can't get an IndexOutOfBoundsException for adding a value to a list. The problem is that a value of s is equal or greater then the actual size of the fileArray array or list.
And because the loops in both examples are equivalent, the problem should be found outside the lines of code you've just posted.
Try to debug (break on IndexOutOfBoundsException if you are using an IDE, otherwise add some simple System.out.println statements to find out, why s is greater than expected.

From the first example, from what you're telling me:
windowSize = 30.
fileArray.size() = 235.
Then, your first for loop will terminate when i + windowSize > 235 (which means i = 236 - 30 = 206`.
You will realize that windowStart gets incremented inside the first for-loop, so eventually, windowStart will increment 205 times (starting from 0).
At that point, the 2nd for-loop will count (windowStart = 205) and your condition s <= windowStart + windowSize will be (s = 205 + 30 which equals 235), which satisfies the condition in the loop, and you're saying fileArray.get(s) which means, fileArray.get(235), and you're getting a IndexOutOfBoundsException.
I'm assuming that windowSize is not the same on the 2nd example, but I can't tell you that until I have seen the full source code.
Hope this helps.

Related

Java - For loop seems to execute past it's termination condition

I have debugged this code and it appears to run a for loop even though the termination condition is met.
This program takes two types of input:
Line 1 - How many data points there are following (N)
Lines 2 to N - The data points
The program should then print the smallest difference between all of the data points.
So, for instance, a sample input would be (on separate lines): 3 5 8 9
There are 3 data points (5 8 9), and the smallest difference is between 8 and 9, so the program should return 1.
I am trying to build the program in a way in which the data points are populated into an array at the same time as the comparisons are made. Obviously I could separate those concerns, but I am experimenting. Here it is:
package com.m3c.vks.test;
import java.util.*;
import java.io.*;
import java.math.*;
class Solution {
public static void main(String args[]) {
Scanner in = new Scanner(System.in);
int N = in.nextInt(); //How many data points there will be
int strengthArray[] = new int[N]; //Initialise the array to be of length = N, the first input line
int tempStrengthDifference=99999; //junk difference set arbitrarily high - bad practice I know
int lowestStrengthDifference=99999;
for (int i = 0; i < N; i++) //Go through all elements of array
{
strengthArray[i] = in.nextInt(); //read a value for the ith element
System.out.println("i: " + i); //test
if (i > 0) //do not execute the next for loop if i = 0 as cannot evaluate sA[-1]
{
for (int j = i - 1; j < 1; j--) // **this is line 20** from wherever the array has populated up to, work backwards to compare the numbers which have been fed in thus far
{
System.out.println("j: " + j); //test
tempStrengthDifference = Math.abs(strengthArray[i] - strengthArray[j]); //finding the difference between two values
if (tempStrengthDifference < lowestStrengthDifference) //store the lowest found thus far in lowestSD
{
lowestStrengthDifference = tempStrengthDifference;
}
}
}
}
System.out.println(lowestStrengthDifference);
}
}
Everything is fine up until when i = 1 on line 20. At this point, j is set to i - 1 = 0 and the difference is found. However, when the for loop comes back around again, the termination condition of j < 1 is not met, and instead the loop continues to set j = -1, at which point it throws an out of bounds error as it clearly cannot evaluate strengthArray[-1]
Any ideas? Thanks
Have a look at your loop: for (int j = i - 1; j < 1; j--)
You start with j = 0 when i == 1 and thus j < 1 is ok.
The next iteration has j = -1 (0-1) and hence you get the problem.
Do you mean to use j >= 0 as your loop condition instead? Note that the second parameter is not a termination condition but a continuation condition, i.e. as long as that condition is met the loop will execute.
The reason behind your failure is the inner loop variable change.
When i=1, j=0 and after executing the loop once, J is decremented, and thus j becomes - 1. The condition j<1 is satisfied since you have written j--, change it to j++ and you should be fine.

array index not incrementing (need to do casting in square brackets)

I have some doubts as to why the value of index is not incrementing here.
The reason why I have declared my array like that is because I need to store n natural numbers where (1 ≤ n ≤ 1012), so numbers are large which is why I have taken an array of type long, but then I get an error that I cannot put any long value in the group, which is why I cast it to int. Is there any way to declare an array for this type of condition, as I want a large number of indexes, and I can not put a long number in the [ ].
hope you guys understand my problem
CODE:
import java.util.Scanner;
class Error{
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
long n = in.nextLong();
long array[] = new long[(int) n];
long index = 0;
for (int j = 1; j <= n; j++) {
if (j % 2 != 0) {//odd
array[(int) index++] = j;
System.out.print(" " + array[(int) --index]);
System.out.print(index);// index value -> always 0 why??
System.out.print(j);
}
}
System.out.println();
}
}
OUTPUT:
Unix-Box ~/Desktop$ javac Error.java
Unix-Box ~/Desktop$ java Error
10
101 303 505 707 909
Unix-Box ~/Desktop$
the middle value is of index and it is always 0
what i shout it to be like
10
101 313 525 737 949
Unix-Box ~/Desktop$
According to
https://www.quora.com/What-is-the-maximum-size-of-the-array-in-Java,
the max size of an array is 2147483647 theoretically, but in practice we would want to use 2147483600 to be safe. Declaring the array as type long will mean that long values can be stored inside. Maybe you can use a two dimensional array to store a long n amount of values. Something like--
public static void main(String[] args)
{
System.out.println("enter the size of the array:");
Scanner in = new Scanner(System.in);
long n = Long.parseLong(in.nextLine());
int secondIndex = 2147483600;
int firstIndex = ((int)(n/secondIndex))+1;
if(secondIndex > n)
{secondIndex = (int)n;
}
else{int leftover = (int)(n%secondIndex);
secondIndex = secondIndex - leftover;}
long[][] array = new long[firstIndex][secondIndex];
//loop through array
outerloop:
for(int i =0;i <firstIndex; i++)
{
for(int z = 0; z<secondIndex; z++)
{
System.out.println("do work with number here: " + array[i][z]);
if(z==(secondIndex-1))
{
z=0;
continue outerloop;
}
}
}
}
You might get a java.lang.OutOfMemoryError:, which can be resolved by reading this article https://plumbr.eu/outofmemoryerror/java-heap-space.
As others have indicated,
array[(int) index++] = j; // You use index and then increment it
System.out.print(" " + array[(int) --index]); // You decrement the index here
That's why index will always be 0 when you print it.
Personally, I don't like mixing brackets with increment operators for the precise reason you're seeing here - it tends to be confusing and it lends itself to subtle (and not-so-subtle) bugs and off-by-one errors. In fact, I really don't like mixing them with any other syntax (with the exception of for loops) as it can quickly become very unclear. For example, if you had done something like
index++;
array[(int)index] = j;
index--;
System.out.print(" " + array[(int)index]);
the problem would've been obvious immediately.
In general, it's a bad idea to sacrifice clarity for brevity.
Also, just to review how the operators in question are working:
index++ - use the value and then increment it
index-- - use the value and then decrement it
++index - increment the value and then use it
--index - decrement the value and then use it.
Here's a C# code sample I put together (Java's behavior will be identical) to illustrate this:
int i = 0;
Trace.TraceInformation((i++).ToString()); // Prints 0
Trace.TraceInformation(i.ToString()); // Prints 1
Trace.TraceInformation((--i).ToString()); // Prints 0
Trace.TraceInformation((i--).ToString()); // Prints 0
Trace.TraceInformation(i.ToString()); // Prints -1
I'd encourage you to trace/step through this to convince yourself that that's the case and to understand exactly why the value is what it is at every point.
Either way, this syntax can be very confusing if overused.

How to find first instance of element array

I'm a pretty basic programmer and I'm coding a 'Master-mind' style guessing game program.
Now the part I'm stuck with is that I want to go through an array and increase the pointer when I come across a specific number.
Now thats pretty easy and stuff, but what I want to do is ONLY increase the counter if the number is encountered for the first time. So, for example if there are two numbers (189, 999), I want the counter to increase only once, instead of 3 times, which is what my code is doing. I know why its doing that, but I can't really figure out a way to NOT do it (except maybe declaring an array and putting all the repeated numbers in there and only incrementing it if none of the numbers match, but that's super inefficient) Here's my code:
for (int i = 0; i < mString.length(); i++) {
for (int j = 0; j < nString.length(); j++) {
if (mString.charAt(i) == nString.charAt(j)) {
correctNumbers++;
}
}
}
Thanks for taking the time to read! I'd prefer it if you wouldn't give me a direct answer and just point me in the right direction so I can learn better. Thanks again!
Your question is quite unclear. I suppose 989 and 999 will return 1. Because you only deal with number, so the solution is:
Create a boolean array with 9 element, from 0-9, named isChecked
Initialize it with false.
Whenever you found a matching number, say 9, turn the boolean element to true, so that you don't count it again (isChecked[9] = true).
Here is the code:
var isChecked = [];
function resetArray(input) {
for (var i = 0; i < 10; i++) {
input[i + ''] = false;
}
}
resetArray(isChecked);
var firstNumber = '989',
secondNumber = '999',
correctNumbers = 0,
fNum, sNum;
for (var i = 0; i < firstNumber.length; i++) {
fNum = firstNumber.charAt(i);
// Skip already checked numbers
if (isChecked[fNum]) {
continue;
}
for (var j = 0; j < secondNumber.length; j++) {
sNum = secondNumber.charAt(j);
if (fNum == sNum && !isChecked[sNum]) {
correctNumbers++;
isChecked[sNum] = true;
}
}
}
console.log(correctNumbers);
Tested on JSFiddle.
If you find anything unclear, feel free to ask me :)
(except maybe declaring an array and putting all the repeated numbers in there and only incrementing it if none of the numbers match, but that's super inefficient)
That approach is a good one, and can be made efficient by using a HashSet of Integers. Everytime you encounter a common digit, you do a contains on the set to check for that digit (gets in HashSets are of constant-time complexitiy - O(1), i.e. super quick), and if it's present in there already, you skip it. If not, you add it into the set, and increment your correctNumbers.
I believe this would help
int found=0; for (int i = 0; i < mString.length(); i++) {
for (int j = 0; j < nString.length(); j++) {
if (mString.charAt(i) == nString.charAt(j)) {
if(found==0){
correctNumbers++;
}
}
}
}
You could try making another 1D array of
int size = nstring.length() * mstring.length();
bool[] array = new bool[size];`
and then have that store a boolean flag of whether that cell has been updated before.
you would find the unique index of the cell by using
bool flag = false
flag = array[(i % mString.length()) + j)];
if(flag == true){
<don't increment>
}else{
<increment>
array[(i % mString.length()) + j)] = true;
}
you could also do this using a 2d array that basically would act as a mirror of your existing table:
bool[][] array = new bool[mstring.length()][nString.length()];
Why not just use the new stream api? Then it's just that:
Arrays.stream(mString).flatMapToInt(s -> s.chars()).distinct().count();
I'll explain:
Arrays.stream(mString) -> Create stream of all strings.
flatMapToInt -> create single concatenated stream from many IntStreams
s -> s.chars() -> Used above to create streams of characters (as ints)
distinct -> remove all duplicates, so each character is counted only once
count -> count the (unique) characters

why is the Arrayindex out of bound in the following code in java? I have checked the bounds but don't understand why/

Arrayindex out of bounds error is showing up and I have particularly no idea why it is hapening. I am trying create 2N tuple objects and trying to put them in a array of size 2N
Tuple[] minuteunit = new Tuple[2*N];
if(!intervals.isEmpty())
{
for(i = 0; i < ((2*N)-1); i = 1+2)
{
minuteunit[i] = new Tuple(intervals.get(i).getBeginMinuteUnit(),"s");
minuteunit[i+1] = new Tuple(intervals.get(i).getEndMinuteUnit(),"e");
}
it is most likely the face you are using i in intervals.get(i), because i is incrementing +2. I would imagine you have N values in intervals and therefore when i >= (N/2) you get an overflow.
Try this:
for(i = 0; i < N; i++)
{
minuteunit[2*i] = new Tuple(intervals.get(i).getBeginMinuteUnit(),"s");
minuteunit[2*i+1] = new Tuple(intervals.get(i).getEndMinuteUnit(),"e");
}
Also, assuming intervals should contain N entries, you could update your intervals.isEmpty() check to:
if(intevals.size() == N)
{
...
for(i = 0; i < ((2*N)-1); i = 1+2)
At each iteration i equals 3, so it never finishes. I think you want to add 2 at each iteration so use:
for(i = 0; i < ((2*N)-1); i = i+2)
You need to make your loop's termination condition i<2*N-2, otherwise the iteration of adding 2 will push i over the end of your array when i is 2*N-2 (which it wi eventually be).
btw, I assume that your iteration of i=1+2 is a typo, and you have actually coded i=i+2
I'm going to take a shot in the dark here and guess that maybe intervals.get(i) is what's actually causing your problem here and not the array itself. Ignoring what appears to be a typo in the increment, the condition for your loop seems to be fine, since if i < 2*N - 1, then i + 1 < 2*N and so there's no out of bound index for the array. That leaves the intervals.get(i) method.

Difference between two similar algorithms of 3Sum?

I found the 3Sum problem on http://www.leetcode.com/onlinejudge which goes like below:
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
The solution set must not contain duplicate triplets.
For example, given array S = {-1 0 1 2 -1 -4},
A solution set is:
(-1, 0, 1)
(-1, -1, 2)
I went through the site and found this suggested solution:
public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
Arrays.sort(num);
HashSet<ArrayList<Integer>> lstSoln = new HashSet<ArrayList<Integer>>();
ArrayList<Integer> tempArr = null;
for (int i = 0; i < num.length; i++) {
int j = i + 1;
int k = num.length - 1;
while (j < k) {
int sum3 = num[i] + num[j] + num[k];
if (sum3 < 0) {
j++;
} else if (sum3 > 0) {
k--;
} else {
tempArr = new ArrayList<Integer>();
Collections.addAll(tempArr, num[i], num[j], num[k]);
lstSoln.add(tempArr);
j++;
k--;
}
}
}
return new ArrayList<ArrayList<Integer>>(lstSoln);
}
As you can see, this takes every number and then follows with two number after the current index. So, it is pretty clear that once the first positive number is reached, we are just doing useless looping and we are not going to find any triplet adding to 0. So I modified the solution and added a condition after for
if (num[i] > 0)
break;
Effectively this should lower the number of times the for loop runs and hence reduce the time taken to find the solution. This I even checked by adding a counter and incrementing it at every if(). Every time the COUNTER for my solution is less than the counter for suggested solution.
But still, when I enter my modified solution at there checking page, it either causes time out error or the time taken is showed to be more than the unmodified version! I want to know what's wrong with my modification?
I dont see anything wrong with your solution, I tried both the solutions on my local and the one with added if condition runs faster. I checked the time difference using System.nanotime(). You might be facing timeout errors on there solution checking page because of network issues.

Categories

Resources