This question already has answers here:
Get all unique values in a JavaScript array (remove duplicates)
(91 answers)
Closed 12 months ago.
I'm just a beginner and I'm trying to write a method returning only unique elements from Java array. What's wrong with this code? Could you please point my mistakes and help me correct them? I've got no idea what to do with it.
P.S. I know I could use packages, but it has to be done in the simplest way.
public static void main(String[] args) {
int[] arr = {1, 1, 2, 3};
int[] items = returnNonRepeated(arr);
System.out.print(items);
}
public static int[] returnNonRepeated(int[] arr) {
int[] temp = new int[0];
int n = 0;
for (int i = 0; i < arr.length; i++) {
if (i == 0) {
temp[i] = arr[i];
} else {
if (arr[i] != arr[i - 1]) {
temp[numbersCount] = arr[i];
numbersCount++;
}
}
}
return temp;
}
}
I know it's not code golf here, but:
if you want to keep only unique values (like a Set would do), you can use a "one-liner". You don't have to implement loops.
public static void main(String[] args) {
int[] dupes = {0, 1, 2, 1, 3, 2, 3};
int[] uniques = Arrays.stream(dupes) // stream ints
.boxed() // make Integer of int
.collect(Collectors.toSet()) // collect into set to remove duplicates
.stream() // stream Integers
.mapToInt(Integer::intValue) // make int of Integer
.toArray(); // and back into an array
System.out.println(Arrays.toString(uniques));
}
Please not that you have to use java.util.Arrays.toString() to get useful output in the last statement. With your variant it will print only something like "[I#531be3c5" which denotes that it is an array of int, but says nothing about the contents.
Nevertheless - if you want to understand, how arrays and loops work, the looping solution is better!
I'm not sure if you mean non-repeat or unique
But here is a method for checking for duplicates:
public static int[] returnUniqueArray(int[] arr) {
int dupes = new int[arr.length]; // The most dupes you could have is the length of the input
int numberOfDupes = 0;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length; j++) {
if(arr[i] == arr[j]) {
dupes[numberOfDupes] = arr[i];
numberOfDupes++;
}
}
}
return dupes;
}
This loops round the arr array twice, therefore comparing every variable in arr to every other variable. If they are the same, it adds that value to a new array.
You could also do similar for non-repeat:
public static int[] returnNonRepeatArray(int[] arr) {
int dupes = new int[arr.length];
int numberOfDupes = 0;
for (int i = 0; i < arr.length - 1; i++) {
if(arr[i] == arr[i+1]) {
dupes[numberOfDupes] = arr[i];
numberOfDupes++;
}
}
return dupes;
}
This loops round the arr array once, but does not check the last item (-1 in the for loop). It then compares the item against the next item, if they are the same it adds that to the dupes.
public static void main(String[] args) {
int[] arr = {1, 1, 2, 2, 3, 4, 5, 5, 5, 6};
int[] items = returnNonRepeated(arr);
System.out.print(Arrays.toString(items));
}
public static int[] returnNonRepeated(int[] arr) {
int[] temp = new int[arr.length];
int numbersCount = 1;
for (int i = 0; i < arr.length; i++) {
if (i == 0) {
uniques[numbersCount] = arr[i];
numbersCount++;
} else {
if (arr[i] != arr[i - 1]) {
uniques[numbersCount] = arr[i];
numbersCount++;
}
}
}
return uniques;
}
Here's the prompt:
Loop through an integer array adding one to each element. Return the resulting array. The array may be of any length including 0.
Here's what I have so far:
public int[] add1toEach(int[] nums) {
int[] array = new int[nums.length];
for (int i = 0; i < nums.length; i++) {
nums[i]++;
}
return array;
}
It works with add1toEach[] and add1toEach[-1] but that's it. How do I get it to spit out [7, 7, 3] if add1toEach[6, 6, 2] is the input?
The fact is that you aren't assigning the new added result to the array, nor are you adding it properly.
The proper code is:
public static int[] add1toEach(int[] nums) {
int[] array = new int[nums.length];
for (int i = 0; i < nums.length; i++) {
array[i]=nums[i]+1;
}
return array;
}
What's happening here is that we add 1 to the item, then we assign the item to an identical array, but which the items are all empty. This happens to every single item of the array, as demonstrated in the statement in the for loop i < nums.length; i++.
This working example:
public class MyClass {
public static void main(String args[]) {
int[] nums = {1, 2, 3};
int[] newnums = add1toEach(nums);
for(int i = 0; i < newnums.length; i++){
System.out.println(newnums[i]);
}
}
public static int[] add1toEach(int[] nums) {
int[] array = new int[nums.length];
for (int i = 0; i < nums.length; i++) {
array[i]=nums[i]+1;
}
return array;
}
}
Produces
2
3
4
What you're code doing is it only returns the untouched int[] array.
Since you have set the length of your array, you just need to set values to your array with position array[i] to make the values assigned and intact position.
array[i]=nums[i]++;
I have to create two arrays with ten random values between 0 and 20. With those arrays create two more arrays:
arrayReps contains the numbers that match between the two arrays. For example with arrays of 3 values: [3, 2, 4], [4, 5, 2] then arrayReps = [2, 4] (order doesnt matter)
arrayUniq contains the unique values of each of the original arrays. From the previous example, arrayUniq = [3, 5].
I already created the two random arrays, but i am having trouble on the arrayReps and arrayUniq, can you help me out? My Code:
import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;
public class P03ArraysExtractUniqsAndReps {
public static void main(String[] args){
Scanner scan1 = new Scanner(System.in);
Random number = new Random();
int a = 0;
int[] randomArray1;
randomArray1 = new int[10];
int[] randomArray2;
randomArray2 = new int[10];
int[] arrayUniq;
int[] arrayReps;
//int[] arrayUniq = new int[10];
for(int i = 0; i < 10; i++){
randomArray1[i] = number.nextInt(20);
}
for(int i = 0; i < 10; i++){
randomArray2[i] = number.nextInt(20);
}
System.out.println(Arrays.toString(randomArray1));
System.out.println(Arrays.toString(randomArray2));
}
}
Compare each element of a1 with the elements of a2. If the match is found, store that element in arrayReps, else store the element in arrayUniq
Something like this:
for(int i=0;i<a1.length;i++)
{
for(int j=0;j<a2.length;j++)
{
if(a1[i]==a2[j])
//add the element in arrayReps
else
//add the element in arrayUniq
}
}
you can also use bucket sort which is the most efficient and the conditions of bucketSort are met: the max and min values are known.
int[] bucketSortArray = new int[20];
for(int i=0;i<10;i++){
bucketSortArray[randomArray1[i]]++;
bucketSortArray[randomArray2[i]]++;
}
System.out.println(Arrays.toString(bucketSortArray));
if bucketSortArray[15]==1, than 15 is unique.
if bucketSortArray[20]>1, than 20 is in Reps.
if it's 0, ignore.
Here's one way of doing it.
Compare the first list of numbers against the second list, then whatever is left in the second list must also be unique.
import java.util.ArrayList;
public class UniqueArray {
public static void main(String[] args)
{
int[] list1 = {0,4,6,2,8,9};
int[] list2 = {0,4,3,2,7,5};
ArrayList<Integer> unique = new ArrayList<Integer>();
ArrayList<Integer> dups = new ArrayList<Integer>();
boolean isUnique = false;
int num;
for(int i = 0; i < list1.length; i++)
{
num = list1[i];
for(int j = 0; j < list1.length; j++)
{
isUnique = true;
if(list1[i] == list2[j])
{
isUnique = false;
list2[j] = -1; // mark as having already been found
break;
}
}
if(isUnique)
{
unique.add(num);
}
else
{
dups.add(num);
}
}
for(int i=0; i< list2.length; i++)
{
if(list2[i]!= -1)
{
unique.add(list2[i]);
}
}
System.out.println("Unique:");
System.out.println(unique);
System.out.println("Dups:");
System.out.println(dups);
}
}
Here is the solution, grab one or both as you wish:
Duplicates O(n+m)
public static int[] getDuplicates(int[] array1, int[] array2) {
HashSet<Integer> duplicates = new HashSet<>();
HashSet<Integer> uniques = new HashSet<>();
for(int i : array1) {
if (!uniques.add(i)) {
duplicates.add(i);
}
}
for(int j : array2) {
if (!uniques.add(j)) {
duplicates.add(j);
}
}
return duplicates.stream().mapToInt(i->i).toArray();
}
Uniques O(n+m)
public static int[] getUniques(int[] array1, int[] array2) {
HashSet<Integer> uniques = new HashSet<>();
for(int i : array1) {
uniques.add(i);
}
for (int j : array2) {
uniques.add(j);
}
return uniques.stream().mapToInt(i->i).toArray();
}
All at once O(n+m)
In case you don't want to use two methods, just put the body of getDuplicates(..) method (it calculates both of duplicates and uniques) to your main(..) one.
public static void main(String[] args) {
int[] array1 = {1,2,5,6,8,9,1};
int[] array2 = {3,4,5,6,0};
HashSet<Integer> setDuplicates = new HashSet<>();
HashSet<Integer> setUniques = new HashSet<>();
for (int i : array1) {
if (!setUniques.add(i)) {
setDuplicates.add(i);
}
}
for (int j : array2) {
if (!setUniques.add(j)) {
setDuplicates.add(j);
}
}
int[] duplicates = setDuplicates.stream().mapToInt(i->i).toArray();
int[] uniques = setUniques.stream().mapToInt(i->i).toArray();
System.out.println(Arrays.toString(duplicates));
System.out.println(Arrays.toString(uniques));
}
All methods will give you the same output:
Duplicates: [1, 5, 6]
Uniques: [0, 1, 2, 3, 4, 5, 6, 8, 9]
I need to add a shift function only with loops (it means I can't use any ListArray method et simila, so this is not a copy of any other question with those methods.) to this method which removes a specific integer from a given array, and put the outcome into another array, and then returning it.
public static int[] removeInt(int v, int[] in) {
int length = 0;
length = in.length;
int[] toReturn = new int[length];
for (int b = 0; b < length; b++) {
toReturn[b] = 0;
}
for (int i = 0; i < length; i++) {
if (in[i] != v) {
toReturn[i] = in[i];
}
}
return toReturn;
}
If the input for the array is {1, 2, 3, 4, 5}, and the number to remove is {2}, the output will be {1 0 3 4 5}, but it needs to be {1 3 4 5}, and I can't find a way to shift numbers to the left.
'v' comes from the main, user input. Same for 'in', fullfilled before by the user.
You will have to iterate over the array two times: The first time, you count how often v is contained in in. If count is 0, you can return in, otherwise you would have to create a new array of length in.length - count. Then again you have to iterate over in and add every value that is not v to your Array.
int count = 0;
for(int i: in) {
if (i==v) {
count++;
}
}
int[] result = new int[in.length-count];
int pos=0;
for(int i: in) {
if (i!=v) {
result[pos] = i;
pos++;
}
}
But you could use Collections to make it easier:
public static void main(String[] args) {
int v = 2;
int[] in = new int[]{1, 2, 3, 4, 5};
List<Integer> list = new ArrayList<>();
for(int i: in) {
if (i!=v) {
list.add(i);
}
}
Integer[] result = list.toArray(new Integer[]{});
}
The disadvantage of this, however, would be that you have an Array of Integer and not of int.
Have you considered using a LinkedList? This internally manages the array so you don't need to deal with moving the elements yourself; you can just call remove().
I need to efficiently sort through 4 arrays and return 2 results.
The first result will contain all numbers that exist in the arrays.
The second result will contain, all occurrences of each number in the result
int[] a = [1,2,3,4,5];
int[] b = [1,2,3,4,5,6];
int[] c = [1,3,7];
int[] d = [2,3,4,8,9,10];
int[] result1 = [1,2,3,4,5,6,7,8,9,10];
int[] result2 = [1,1,1,2,2,2,3,3,3,3,4,4,4,5,5,6,7,8,9,10];
Step 1: Combine all the arrays
Step 2: Sort arrays using Arrays.sort(array);
Step 3: Remove the duplicates.
int[] a = {1,2,3,4,5};
int[] b = {1,2,3,4,5,6};
int[] c = {1,3,7};
int[] d = {2,3,4,8,9,10};
int[] resultArray1 = new int[a.length+b.length+c.length+d.length];
int arrayIndex = 0;
for (int i=0; i< a.length ; i++, arrayIndex++ )
{
resultArray1[arrayIndex] = a[i];
}
for (int i=0; i< b.length ; i++, arrayIndex++ )
{
resultArray1[arrayIndex] = b[i];
}
for (int i=0; i< c.length ; i++, arrayIndex++ )
{
resultArray1[arrayIndex] = c[i];
}
for (int i=0; i< d.length ; i++, arrayIndex++ )
{
resultArray1[arrayIndex] = d[i];
}
// Sorting Arrays
System.out.println("Array before Sort"+Arrays.toString(resultArray1));
Arrays.sort(resultArray1);
System.out.println("Array after Sort"+Arrays.toString(resultArray1));
// Removing duplicates
Set<String> set = new HashSet<String>();
for (int i = 0; i < resultArray1.length; i++) {
set.add(""+resultArray1[i]); // To convert to string
}
String[] uniqueStringArray = set.toArray(new String[set.size()]); ;
int [] uniqueIntArray = new int [uniqueStringArray.length];
// Converting string array to int array
for(int i=0;i<uniqueStringArray.length;i++)
{
uniqueIntArray[i]= Integer.parseInt(uniqueStringArray[i]);
}
Arrays.sort(uniqueIntArray);
System.out.println("Unique Array after Sort"+Arrays.toString(uniqueIntArray));
Output:
Array before Sort[1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 1, 3, 7, 2, 3, 4, 8, 9, 10]
Array after Sort[1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6, 7, 8, 9, 10]
Unique Array after Sort[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Combine all 4 arrays in 1 array
sort Array
Remove Dublicate from array
import java.util.Vector;
class sort
{
public static void main(String args[])
{
int[] a = {1,2,3,4,5};
int[] b = {1,2,3,4,5,6};
int[] c = {1,3,7};
int[] d = {2,3,4,8,9,10};
int[] s = combine(a,b,c,d); //concate array using concate function
int[] sort = sort(s);//sort array using sort function
//SORTING ARRAY
System.out.print("ARRAY AFTER SORT ");
System.out.print("[");
for(int i=0;i<sort.length;i++)
{
if(i==sort.length-1)
System.out.print(sort[i]);
else
System.out.print(sort[i]+",");
}
System.out.println("]\n");
//REMOVE DUPLICATE
int[] removedups=removedups(sort);// Remove Duplicate item from array using removedups
System.out.print("ARRAY REMOVE DUPLICATE ");
System.out.print("[");
for(int i=0;i<removedups.length;i++)
{
if(i==removedups.length-1)
System.out.print(removedups[i]);
else
System.out.print(removedups[i]+",");
}
System.out.print("]");
}
public static int[] combine(int a[],int b[],int c[],int d[])//combine array
{
int sort []=new int[a.length+b.length+c.length+d.length];
int j=0;
for(int i=0;i<a.length;i++)
{
sort[j]=a[i];
j++;
}
for(int i=0;i<b.length;i++)
{
sort[j]=b[i];
j++;
}
for(int i=0;i<c.length;i++)
{
sort[j]=c[i];
j++;
}
for(int i=0;i<d.length;i++)
{
sort[j]=d[i];
j++;
}
return sort;
}
public static int[] sort(int s[]) // sort array
{
int temp;
for(int i=0;i<s.length;i++)
{
for(int j=i+1;j<s.length-1;j++)
{
if(s[i]>s[j])
{
temp=s[i];
s[i]=s[j];
s[j]=temp;
}
}
}
return s;
}
public static int[] removedups(int s[])//remove dups from sorted array
{
Vector array=new Vector();
int l=0;
for(int i=0;i<s.length-1;i++)
{
if(s[i]!=s[i+1])
{
array.add(s[i]);
l++;
}
}
int[] temp=new int[array.size()];
for(int j=0;j<temp.length;j++)
{
temp[j]=Integer.parseInt(""+array.get(j));
}
return temp ;
}
}//end the program
Simpliest way is use sort and HashSet
public class SortClass {
public static void main(String[] args) {
//Define imput data
int[] a = {1, 2, 3, 4, 5};
int[] b = {1, 2, 3, 4, 5, 6};
int[] c = {1, 3, 7};
int[] d = {2, 3, 4, 8, 9, 10};
//Actual algorithm
List<Integer> all = new ArrayList<Integer>();
all.addAll(toList(a));
all.addAll(toList(b));
all.addAll(toList(c));
all.addAll(toList(d));
Collections.sort(all);
TreeSet<Integer> set = new TreeSet<Integer>();
set.addAll(all);
int[] sorted = toIntArray(all);
int[] sortedUniq = toIntArray(set);
//Output result
System.out.println("Sorted: " + Arrays.toString(sorted));
System.out.println("Sorted uniq: " + Arrays.toString(sortedUniq));
}
// We need pair of method to convert between `int[]` and `Collection<Integer>`
private static int[] toIntArray(Collection<Integer> all) {
int[] ints = new int[all.size()];
int i =0;
for (int val : all) {
ints[i] = val;
i++;
}
return ints;
}
private static Collection<? extends Integer> toList(int[] ints) {
ArrayList<Integer> list = new ArrayList<Integer>();
for (int i : ints) {
list.add(i);
}
return list;
}
}
But if performance is critical we can utilize the fact that input arrays already sorted and us merge sort:
public class SortClass {
public static void main(String[] args) {
int[] a = {1, 2, 3, 4, 5};
int[] b = {1, 2, 3, 4, 5, 6};
int[] c = {1, 3, 7};
int[] d = {2, 3, 4, 8, 9, 10};
//Prepare data structure
List<ArrayTail> all = new ArrayList<ArrayTail>();
add(all, new ArrayTail(a));
add(all, new ArrayTail(b));
add(all, new ArrayTail(c));
add(all, new ArrayTail(d));
int[] sorted = sort(all);
int[] sortedUniq = getUniq(sorted);
System.out.println("Sorted: " + Arrays.toString(sorted));
System.out.println("Sorted uniq: " + Arrays.toString(sortedUniq));
}
private static int[] getUniq(int[] sorted) {
Collection<Integer> result = new ArrayList<Integer>();
int current = sorted[0];
result.add(current);
for (int i : sorted){
if(i != current){
current = i;
result.add(i);
}
}
return toIntArray(result);
}
private static int[] sort(List<ArrayTail> all) {
int totalLength = 0;
for (ArrayTail tail : all){
totalLength+=tail.size();
}
int[] result = new int[totalLength];
int pos = 0;
while(!all.isEmpty()){
//Take smallest value from smallest array
ArrayTail smallest = all.get(0);
result[pos] = smallest.take();
pos++;
// remove array if no more elements in it
if(smallest.size() ==0){
all.remove(0);
} else {
// ensure that first element steel smallest
sortFirstElement(all);
}
}
return result;
}
// This is actually on step of bubble sort, but it
// works because all other list except may be first already sorted
private static void sortFirstElement(List<ArrayTail> all) {
for (int i = 0; i < all.size()-1; i++) {
if(all.get(i).get() > all.get(i+1).get()){
Collections.swap(all, i, i + 1);
} else {
break;
}
}
}
private static void add(List<ArrayTail> all, ArrayTail arrayTail) {
// all sorted here
all.add(0, arrayTail);
sortFirstElement(all);
// all sorted here, again
}
private static int[] toIntArray(Collection<Integer> all) {
int[] ints = new int[all.size()];
int i =0;
for (int val : all) {
ints[i] = val;
i++;
}
return ints;
}
// Simpl data structure representing tail of array
private static class ArrayTail {
private final int[] arr;
private int pos;
public ArrayTail(int[] arr) {
this.arr = arr;
this.pos = 0;
}
public int size() {
return arr.length - pos;
}
public int take() {
return arr[pos++];
}
public int get() {
return arr[pos];
}
}
}
As you can see code become more complex but possible work faster.
PS: fun thing is that bubble sort can be used in real life :)
TRY Using merge sort algorithm. wikipedia page here
For result 1, dump the contents of your 4 lists into a TreeSet. This will sort and remove duplicates from the set at the same time. Then get the array of the set.
For result 2, use array copy to copy all the numbers into 1 array and then sort that array using Arrays.sort(...). There is no need to try to merge them on your own due to the nature of the sorting algorithm which is O(nlog(n)). Quadrupling the size results in a multiplying factor of only 2.