0

I'm trying to write a method that accepts an array of integers and returns the number of unique values in that array. For example, for array {5, 6, 5, 7, 5, 7} the method returns 3 because there are 3 duplicates (5,5,7). I'm not sure where I went wrong, I tried creating a variable list so that when I call numUnique(list) it would give me my answer, but that didn't seem to work. Any suggestions?

Code:

import java.util.Scanner;

public class Unique_Values {
public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    int n = sc.nextInt();
    int[] list = new int[n];
    System.out.printf("%d%n ", list);
}

public static int numUnique(int[] list) {
    if (list.length == 0) {
        return 0;
    } else {
        int count = 1;
        for (int i = 1; i < list.length; i++) {
            if (list[i] != list[i - 1]) {
                count++;
            }
        }
        return count;
    }
  }
}
Lukas
  • 65
  • 3
  • 9
  • 3
    "that didn't seem to work" is not a clear problem description. What was your input? What output did you expect? – shmosel Feb 24 '17 at 20:53
  • 1
    Your method only checks for adjacent duplicates. – shmosel Feb 24 '17 at 20:53
  • You need an inner loop. You are only checking the element directly before the number for example: `4545` you are comparing `5` to `4` not `5` to `5`. You need to compare each number in the array to all other numbers. You can do this using an inner loop... – brso05 Feb 24 '17 at 20:54
  • 1
    FYI you can do this very easily with streams: `return Arrays.stream(list).distinct().count();` – shmosel Feb 24 '17 at 20:54
  • Or just add everything to a `Set` and then count its entries, a la http://stackoverflow.com/questions/15752180/how-to-get-unique-items-from-an-array – azurefrog Feb 24 '17 at 20:55
  • You never actually call `numUnique`. And you simply print out a space. – Andy Turner Feb 24 '17 at 20:56
  • @AndyTurner Good point. The first check is not even necessary now that I think of it. You can just do `int count = list.length;`. – shmosel Feb 24 '17 at 20:59
  • @AndyTurner Got me again. Maybe `int count = Math.min(1, list.length);`, but that's getting silly... – shmosel Feb 24 '17 at 21:01

4 Answers4

0

This is not going to be code to solve your problem because I think it is important to think about this problem.

One brute force method to go about doing this is to have a list, lets call it returnList, and to add elements to that list as you read them in. Every time you want to add an element to the list you first should check the list to make sure that the element hasn't been added before. If it has been added before, you don't add the element to the list, and then move into the next input element. After reading in the entire array simple return the length of the returnList which is trivial to do.

Note that this is by no means an efficient way to do this (requires you to check the list every single time) and is just one way to go about solving this problem. I urge you to try and think about better ways to solve the problem!

Good luck!

Jay
  • 157
  • 2
  • 11
  • 2
    Why would you use a list instead of a set? – shmosel Feb 24 '17 at 21:13
  • Again this is not the only implementation and was meant to give a non ideal algorithm that would force OP to think about ways to provide a better time complexity/efficiency. I agree with you that sets are the way to go but I wanted OP to try and figure that out for himself! :) – Jay Feb 24 '17 at 21:14
0

You code compares list[i] to list[i - 1], which means you're only checking for adjacent duplicates. To filter out all duplicates, you'll need to check list[i] against every successive element using an inner loop. For example:

int count = 1;
for (int i = 0; i < list.length - 1; i++) {
    for (int j = i + 1; j < list.length && list[i] != list[j]; j++) {
        if (j == list.length - 1) {
            count++;
        }
    }
}

Note that there are a number of ways to formulate the above, and there are altogether cleaner and more efficient ways to count distinct elements than with an inner loop, as mentioned in the comments.

shmosel
  • 49,289
  • 6
  • 73
  • 138
0

Your code if (list[i] != list[i - 1]) { count++; } just checks for adjacent duplicates. So in array [5, 4, 5], the two fives will not be regarded as duplicates.

One method to solve this issue is by using the brute force method, i.e. having nested for loops, the inner for loop going trough the complete remaining array.

The better method in my opinion is to scan the array, and keep inserting the values in a Set. Once the scan is complete, the length of the set is your answer (the number of unique values).

In Java, considering the input is a list of integers, following code can be used:

public static int findNumberOfUniqueElements(List<Integer> list) {
    if (list == null) {
        return 0;
    }
    return (new HashSet<Integer>(list)).size();
}

A more generic code to be adapted in any language is following:

public static int findNumberOfUniqueElements(List<Integer> list) {
    if (list == null) {
        return 0;
    }
    Set<Integer> set = new HashSet<Integer> ();
    for (int i=0; i<list.size(); i++) {
        set.add(list.get(i));   // get list[i]
    }
    return set.size();
}
Ali Shah Ahmed
  • 3,263
  • 3
  • 24
  • 22
0

If you want to use array only,

For finding the count of duplicate entries, you need to first sort the array and then compare adjacent elements, if both are same increment the count.

Here is the code :

public static int numUnique(int arr[])
{
    int dup = 0;

    Arrays.sort(arr);

    for(int i = 1 ; i < arr.length ; i++)
    {
        if(arr[i-1] == arr[i])
            dup++;
    }
    return dup;
}

There is a comparatively easy way with the use of ArrayList

Here is the code :

public static int numUnique(int arr[])
{
    int dup = 0;

    ArrayList<Integer> al = new ArrayList<Integer>();

    for(int i = 0 ; i < arr.length ; i++)
    {
        if(!al.contains(arr[i]))
        {
            al.add(arr[i]);
        }
        else
            dup++;
    }
    return dup;
}