2

I cannot see anything wrong with my code:-

import java.util.ArrayList;

public class Main {

    public static void main(String[] args) {

       int[] A = new int[] {2, 1, 1, 2, 3, 1}; 
       ArrayList<Integer> foundNumbers = new ArrayList<>();
        int distinct = 0;

        for(int i = 0; i < A.length-1; i++) {
            if(foundNumbers.get(i-1) == null) {

                foundNumbers.set((i-1), A[i]);
                distinct++;
            }


    }
        System.out.println(distinct);
}    
}

I want to check if the value of Array element i has already been assigned to ArrayList element i-1, then increment the distinct variable and print how many distinct values are in the array.

Here's the exception when I change the value of i to 1:-

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    at java.util.ArrayList.rangeCheck(ArrayList.java:604)
    at java.util.ArrayList.get(ArrayList.java:382)
    at tdd.Main.main(Main.java:19)

3 Answers3

2

The list is completely empty. You haven't put anything in it, yet you're trying to read elements from it with the foundNumbers.get call, so any index will be out of bounds.

To add unique elements from A to the list, get and set are simply the wrong list methods to call, use contains and add if that's what you want to do:

for (int x : A) {
    if (!foundNumbers.contains(x))
        foundNumbers.add(x);
}

Here is the same logic as above written in a more verbose fashion that might make it easier to understand what is involved:

for (int i = 0; i < A.length; i++) {
    boolean found = false;
    for (int j = 0; j < foundNumbers.size(); j++) {
        if (A[i] == foundNumbers.get(j)) {
            found = true;
            break;
        }
    }
    if (!found) {
        foundNumbers.add(A[i]);
    }
}

You don't need the separate distinct variable, since it is simply foundNumbers.size().


Although this works, a List is not very efficient for eliminating duplicates if the count of elements is large, since every contains call requires another loop through the contents of the list. A Set automatically prevent duplicates and internally structures its contents in a way that makes it efficient to do so:

Set<Integer> distinct = new TreeSet<>();
for (int x : A) distinct.add(x);
System.out.println(distinct); // [1, 2, 3]
Boann
  • 48,794
  • 16
  • 117
  • 146
1
for(int i = 0; i < A.length-1; i++) {
    if(foundNumbers.get(i-1) == null) {

In the first iteration of that loop, i will be set to zero, so the second line is doing .get(-1).

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
1

There are multiple issues:

  • when i is 0, you try to get i-1=-1th element which is not valid
  • Even when you fix this, since you dont have elements in list, you will still get IndexOutOfBoundsException, since you havent stored any elements yet and your list is empty.

Your loop should be:

for (int i = 0; i < A.length - 1; i++) {
        if (foundNumbers.size() > i && foundNumbers.get(i) == null) {//or better you use contains method of list like foundNumbers.contains(someNumber);
            foundNumbers.add(A[i]);
            distinct++;
        }
}
SMA
  • 36,381
  • 8
  • 49
  • 73