Related
Arrays.sort(arr);
int max=1,m=1;
for(int i=1;i<arr.length;i++){
if(arr[i]==arr[i-1]){
max++;
}
else{
if(max>m){
m=max;
max=1;
}
}
}
if(max>m){
m=max;
}
return m;
This is a function that I have made. This should return the number of times the most frequent element occurs. E.g if the array is 1,2,2,3,3,3 , then it should return 3. But it fails in many cases, e.g for the input 1 2 3 1 2 3 3 3, this code fails and returns 5, which is the wrong output.
I can code it up for you to answer your question using the map interface. I will check each value and if there is already a key for that value, it will increment the value by 1. If not, then it will create the key and assign it a value of 1.
When finished, I only need to ask the map what the largest value was which is what I think you are after. And I can also return the value that was the most frequent, if you want.
Here is the tested code. One class for the working method and then the driver class with main method
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
public class FindMostFrequent {
public static Integer returnFromArrayHighestFrequency(int[] inArray) {
HashMap<Integer, Integer> hashMap = new HashMap<Integer, Integer>();
for (int i = 0; i < inArray.length; i++) {
if (hashMap.containsKey(inArray[i])) {
hashMap.put(inArray[i], hashMap.get(inArray[i]) + 1);
} else {
hashMap.put(inArray[i], 1);
}
}
Integer maxValue = Collections.max(hashMap.values());
return maxValue;
}
}
And here is the driver class:
public static void main(String[] args) {
int[] testArray = { 1, 2, 2, 3, 3, 3 };
Integer max = FindMostFrequent.returnFromArrayHighestFrequency(testArray);
System.out.println("highest frequency is: " + max);
}
I like this technique because it allows you to easily get the minimum or another other value and its key that you want.
Sorting the array first and counting runs of the same number is a good idea. Your logic doesn't quite make sense through.
You need to keep track of the length of the current run, and the length of the longest run. Your current run should get reset when the value in the array is different to the previous value; and your longest run should be updated when the current run is longer than it.
Something like this:
if (arr.length==0) {
return 0;
}
Arrays.sort(arr);
int currentRun = 1;
int longestRun = 1;
for (int i = 1; i < arr.length; i++){
if (arr[i]==arr[i-1]){
++currentRun;
if (currentRun > longestRun) {
longestRun = currentRun;
}
} else {
currentRun = 1;
}
}
return longestRun;
Another way using streams, which basically uses a map to track the frequency of occurrences and grabs the highest value after sorting that map.
public static Long getMostFrequentCount( int ... values ) {
return Arrays.stream(values).boxed().collect(Collectors.groupingBy(Function.identity(),
Collectors.counting())).values().stream().max(Long::compareTo).orElse( null );
}
EDIT: Made better thanks to #saka1029 's excellent suggestion
This might be what you want...
All of the numbers you want to use is contained inside of the array a.
public class Main {
public static void main(String[] args) {
int[] a = {1,2,3,4,5,6,7,7,7,7};
int count = 1, tempCount;
int popular = a[0];
int temp = 0;
for (int i = 0; i < (a.length - 1); i++) {
temp = a[i];
tempCount = 0;
for (int j = 1; j < a.length; j++) {
if (temp == a[j])
tempCount++;
}
if (tempCount > count) {
popular = temp;
count = tempCount;
}
}
System.out.println(popular);
}
}
your logic is totally correct except one line. ==> if(max>m).
In this case you are not resetting the value of max if max == m.
replace if(max>m){ with if(max>=m){
You need to check max against m for each iteration. And the use of continue here simplifies the logic. Prints -1 on an empty array.
int[] arr = {1, 2, 3, 1, 2, 3, 3, 3};
Arrays.sort(arr);
int max = 1;
int m = arr.length == 0 ? -1 : 1;
for (int i = 1; i < arr.length; i++) {
if (arr[i] == arr[i - 1]) {
max++;
if (max > m) {
m = max;
}
continue;
}
max = 1;
}
System.out.println(m);
Prints
4
I have implemented the select/median of medians algorithm using the following as a reference http://www.ics.uci.edu/~eppstein/161/960130.html (this has previously been linked here Median of Medians in Java).
My code seems to work for small arrays (~100) and even works for arrays of size 100001 http://pastebin.com/mwRc4Hig (answer 5008), but then fails on an input array of size 10001 http://pastebin.com/YwVBmgDk (answer 4960, my code outputs 4958).
Note that the correct answers for the texts above are equivalent to sorting the array and returning the element at array[array.length / 2], regardless of whether the array size is even or odd.
I'm not sure how to debug this issue. The functionality seems arbitrary and I'm just lost. Here below is my code:
public class MedianOfMedians {
public static void main(String[] args) {
MedianOfMedians mds = new MedianOfMedians();
mds.run();
}
private void run() {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] numArray = new int[n];
for (int i = 0; i < n; i++) {
numArray[i] = in.nextInt();
}
int median = select(numArray, numArray.length / 2);
System.out.print(median);
}
private int select(int[] numArray, int k) {
if (numArray.length <= 10) {
int[] sorted = insertionSort(numArray);
return sorted[k];
}
int divCount = (numArray.length % 5 == 0) ? numArray.length / 5 - 1 : numArray.length / 5;
int[] medOfMed = new int[divCount + 1];
int counter = 0;
int[] subArray;
while (counter <= divCount) {
subArray = splitByFive(counter, divCount, numArray);
medOfMed[counter] = select(subArray, subArray.length / 2);
counter++;
}
int M = select(medOfMed, numArray.length / 10);
List<Integer> lt = new ArrayList<>();
List<Integer> eq = new ArrayList<>();
List<Integer> gt = new ArrayList<>();
for (int i : numArray) {
if (i < M) {
lt.add(i);
} else if (i == M) {
eq.add(i);
} else {
gt.add(i);
}
}
if (k < lt.size()) {
return select(createArray(lt), k);
} else if (k > lt.size() + eq.size()) {
return select(createArray(gt), k - lt.size() - eq.size());
} else {
return M;
}
}
private int[] splitByFive(int splitIter, int divisions, int[] toSplit) {
int numToCopy;
if (splitIter == divisions) {
numToCopy = toSplit.length - (5 * splitIter);
} else {
numToCopy = 5;
}
int[] subArray = new int[numToCopy];
System.arraycopy(toSplit, splitIter * 5, subArray, 0, numToCopy);
return subArray;
}
private int[] createArray(List<Integer> list) {
int[] result = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
result[i] = list.get(i);
}
return result;
}
private int[] insertionSort(int[] numArray) {
for (int i = 1; i < numArray.length; i++) {
int j = i;
while (j - 1 >= 0 && numArray[j] < numArray[j - 1]) {
int temp = numArray[j];
numArray[j] = numArray[j - 1];
numArray[j - 1] = temp;
j--;
}
}
return numArray;
}
}
I don't have time to debug your code, but maybe I can offer a debugging technique for you to try yourself that's useful for recursive algorithms like this.
If there is an input that the algorithm fails on (and there is, as you found) then there is a smallest such input -- and the smaller this input, the easier it is to figure out what's going wrong. Because the algorithm is recursive, you have a nice way to isolate the first place that things go wrong: you can test that the result you are about to return from select() is correct (using a slow, trusted method like copying the data to a temporary buffer, sorting it and then grabbing the half-way element) just before returning the value. Doing this will be much easier if you rearrange the function to use just a single return statement, e.g.:
private int select(int[] numArray, int k) {
int knownCorrectAnswer = selectSlowlyButDefinitelyCorrectly(numArray, k);
int willReturn;
if (numArray.length <= 10) {
int[] sorted = insertionSort(numArray);
willReturn = sorted[k]; // Just remember what we will return
} else { // Need to add else branch here now
...
if (k < lt.size()) {
willReturn = select(createArray(lt), k);
} else if (k > lt.size() + eq.size()) {
willReturn = select(createArray(gt), k - lt.size() - eq.size());
} else {
willReturn = M;
}
} // End of inserted else branch
if (willReturn == knownCorrectAnswer) {
return willReturn;
} else {
yell("First problem occurs with numArray=<...> and k=<...>!");
}
}
yell() should print out the entire problem instance and halt the program (e.g. by throwing an exception). The nice thing about this setup is that you know that when yell() gets called, every call to select() that has already completed was correct -- since if it wasn't, yell() would have already been called and the program would have halted before now. So the output produced by yell() is guaranteed to be the first (not necessarily the smallest, but often that also) subproblem in which things went wrong.
I was asked to write my own implementation to remove duplicated values in an array. Here is what I have created. But after tests with 1,000,000 elements it took very long time to finish. Is there something that I can do to improve my algorithm or any bugs to remove ?
I need to write my own implementation - not to use Set, HashSet etc. Or any other tools such as iterators. Simply an array to remove duplicates.
public static int[] removeDuplicates(int[] arr) {
int end = arr.length;
for (int i = 0; i < end; i++) {
for (int j = i + 1; j < end; j++) {
if (arr[i] == arr[j]) {
int shiftLeft = j;
for (int k = j+1; k < end; k++, shiftLeft++) {
arr[shiftLeft] = arr[k];
}
end--;
j--;
}
}
}
int[] whitelist = new int[end];
for(int i = 0; i < end; i++){
whitelist[i] = arr[i];
}
return whitelist;
}
you can take the help of Set collection
int end = arr.length;
Set<Integer> set = new HashSet<Integer>();
for(int i = 0; i < end; i++){
set.add(arr[i]);
}
now if you will iterate through this set, it will contain only unique values. Iterating code is like this :
Iterator it = set.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
If you are allowed to use Java 8 streams:
Arrays.stream(arr).distinct().toArray();
Note: I am assuming the array is sorted.
Code:
int[] input = new int[]{1, 1, 3, 7, 7, 8, 9, 9, 9, 10};
int current = input[0];
boolean found = false;
for (int i = 0; i < input.length; i++) {
if (current == input[i] && !found) {
found = true;
} else if (current != input[i]) {
System.out.print(" " + current);
current = input[i];
found = false;
}
}
System.out.print(" " + current);
output:
1 3 7 8 9 10
Slight modification to the original code itself, by removing the innermost for loop.
public static int[] removeDuplicates(int[] arr){
int end = arr.length;
for (int i = 0; i < end; i++) {
for (int j = i + 1; j < end; j++) {
if (arr[i] == arr[j]) {
/*int shiftLeft = j;
for (int k = j+1; k < end; k++, shiftLeft++) {
arr[shiftLeft] = arr[k];
}*/
arr[j] = arr[end-1];
end--;
j--;
}
}
}
int[] whitelist = new int[end];
/*for(int i = 0; i < end; i++){
whitelist[i] = arr[i];
}*/
System.arraycopy(arr, 0, whitelist, 0, end);
return whitelist;
}
There exists many solution of this problem.
The sort approach
You sort your array and resolve only unique items
The set approach
You declare a HashSet where you put all item then you have only unique ones.
You create a boolean array that represent the items all ready returned, (this depend on your data in the array).
If you deal with large amount of data i would pick the 1. solution. As you do not allocate additional memory and sorting is quite fast. For small set of data the complexity would be n^2 but for large i will be n log n.
Since you can assume the range is between 0-1000 there is a very simple and efficient solution
//Throws an exception if values are not in the range of 0-1000
public static int[] removeDuplicates(int[] arr) {
boolean[] set = new boolean[1001]; //values must default to false
int totalItems = 0;
for (int i = 0; i < arr.length; ++i) {
if (!set[arr[i]]) {
set[arr[i]] = true;
totalItems++;
}
}
int[] ret = new int[totalItems];
int c = 0;
for (int i = 0; i < set.length; ++i) {
if (set[i]) {
ret[c++] = i;
}
}
return ret;
}
This runs in linear time O(n). Caveat: the returned array is sorted so if that is illegal then this answer is invalid.
class Demo
{
public static void main(String[] args)
{
int a[]={3,2,1,4,2,1};
System.out.print("Before Sorting:");
for (int i=0;i<a.length; i++ )
{
System.out.print(a[i]+"\t");
}
System.out.print ("\nAfter Sorting:");
//sorting the elements
for(int i=0;i<a.length;i++)
{
for(int j=i;j<a.length;j++)
{
if(a[i]>a[j])
{
int temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
}
//After sorting
for(int i=0;i<a.length;i++)
{
System.out.print(a[i]+"\t");
}
System.out.print("\nAfter removing duplicates:");
int b=0;
a[b]=a[0];
for(int i=0;i<a.length;i++)
{
if (a[b]!=a[i])
{
b++;
a[b]=a[i];
}
}
for (int i=0;i<=b;i++ )
{
System.out.print(a[i]+"\t");
}
}
}
OUTPUT:Before Sortng:3 2 1 4 2 1 After Sorting:1 1 2 2 3 4
Removing Duplicates:1 2 3 4
Since this question is still getting a lot of attention, I decided to answer it by copying this answer from Code Review.SE:
You're following the same philosophy as the bubble sort, which is
very, very, very slow. Have you tried this?:
Sort your unordered array with quicksort. Quicksort is much faster
than bubble sort (I know, you are not sorting, but the algorithm you
follow is almost the same as bubble sort to traverse the array).
Then start removing duplicates (repeated values will be next to each
other). In a for loop you could have two indices: source and
destination. (On each loop you copy source to destination unless they
are the same, and increment both by 1). Every time you find a
duplicate you increment source (and don't perform the copy).
#morgano
import java.util.Arrays;
public class Practice {
public static void main(String[] args) {
int a[] = { 1, 3, 3, 4, 2, 1, 5, 6, 7, 7, 8, 10 };
Arrays.sort(a);
int j = 0;
for (int i = 0; i < a.length - 1; i++) {
if (a[i] != a[i + 1]) {
a[j] = a[i];
j++;
}
}
a[j] = a[a.length - 1];
for (int i = 0; i <= j; i++) {
System.out.println(a[i]);
}
}
}
**This is the most simplest way**
What if you create two boolean arrays: 1 for negative values and 1 for positive values and init it all on false.
Then you cycle thorugh the input array and lookup in the arrays if you've encoutered the value already.
If not, you add it to the output array and mark it as already used.
package com.pari.practice;
import java.util.HashSet;
import java.util.Iterator;
import com.pari.sort.Sort;
public class RemoveDuplicates {
/**
* brute force- o(N square)
*
* #param input
* #return
*/
public static int[] removeDups(int[] input){
boolean[] isSame = new boolean[input.length];
int sameNums = 0;
for( int i = 0; i < input.length; i++ ){
for( int j = i+1; j < input.length; j++){
if( input[j] == input[i] ){ //compare same
isSame[j] = true;
sameNums++;
}
}
}
//compact the array into the result.
int[] result = new int[input.length-sameNums];
int count = 0;
for( int i = 0; i < input.length; i++ ){
if( isSame[i] == true) {
continue;
}
else{
result[count] = input[i];
count++;
}
}
return result;
}
/**
* set - o(N)
* does not guarantee order of elements returned - set property
*
* #param input
* #return
*/
public static int[] removeDups1(int[] input){
HashSet myset = new HashSet();
for( int i = 0; i < input.length; i++ ){
myset.add(input[i]);
}
//compact the array into the result.
int[] result = new int[myset.size()];
Iterator setitr = myset.iterator();
int count = 0;
while( setitr.hasNext() ){
result[count] = (int) setitr.next();
count++;
}
return result;
}
/**
* quicksort - o(Nlogn)
*
* #param input
* #return
*/
public static int[] removeDups2(int[] input){
Sort st = new Sort();
st.quickSort(input, 0, input.length-1); //input is sorted
//compact the array into the result.
int[] intermediateResult = new int[input.length];
int count = 0;
int prev = Integer.MIN_VALUE;
for( int i = 0; i < input.length; i++ ){
if( input[i] != prev ){
intermediateResult[count] = input[i];
count++;
}
prev = input[i];
}
int[] result = new int[count];
System.arraycopy(intermediateResult, 0, result, 0, count);
return result;
}
public static void printArray(int[] input){
for( int i = 0; i < input.length; i++ ){
System.out.print(input[i] + " ");
}
}
public static void main(String[] args){
int[] input = {5,6,8,0,1,2,5,9,11,0};
RemoveDuplicates.printArray(RemoveDuplicates.removeDups(input));
System.out.println();
RemoveDuplicates.printArray(RemoveDuplicates.removeDups1(input));
System.out.println();
RemoveDuplicates.printArray(RemoveDuplicates.removeDups2(input));
}
}
Output:
5 6 8 0 1 2 9 11
0 1 2 5 6 8 9 11
0 1 2 5 6 8 9 11
I have just written the above code for trying out. thanks.
public static int[] removeDuplicates(int[] arr){
HashSet<Integer> set = new HashSet<>();
final int len = arr.length;
//changed end to len
for(int i = 0; i < len; i++){
set.add(arr[i]);
}
int[] whitelist = new int[set.size()];
int i = 0;
for (Iterator<Integer> it = set.iterator(); it.hasNext();) {
whitelist[i++] = it.next();
}
return whitelist;
}
Runs in O(N) time instead of your O(N^3) time
Not a big fun of updating user input, however considering your constraints...
public int[] removeDup(int[] nums) {
Arrays.sort(nums);
int x = 0;
for (int i = 0; i < nums.length; i++) {
if (i == 0 || nums[i] != nums[i - 1]) {
nums[x++] = nums[i];
}
}
return Arrays.copyOf(nums, x);
}
Array sort can be easily replaced with any nlog(n) algorithm.
This is simple way to sort the elements in the array
public class DublicatesRemove {
public static void main(String args[]) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("enter size of the array");
int l = Integer.parseInt(br.readLine());
int[] a = new int[l];
// insert elements in the array logic
for (int i = 0; i < l; i++)
{
System.out.println("enter a element");
int el = Integer.parseInt(br.readLine());
a[i] = el;
}
// sorting elements in the array logic
for (int i = 0; i < l; i++)
{
for (int j = 0; j < l - 1; j++)
{
if (a[j] > a[j + 1])
{
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
// remove duplicate elements logic
int b = 0;
a[b] = a[0];
for (int i = 1; i < l; i++)
{
if (a[b] != a[i])
{
b++;
a[b]=a[i];
}
}
for(int i=0;i<=b;i++)
{
System.out.println(a[i]);
}
}
}
Okay, so you cannot use Set or other collections. One solution I don't see here so far is one based on the use of a Bloom filter, which essentially is an array of bits, so perhaps that passes your requirements.
The Bloom filter is a lovely and very handy technique, fast and space-efficient, that can be used to do a quick check of the existence of an element in a set without storing the set itself or the elements. It has a (typically small) false positive rate, but no false negative rate. In other words, for your question, if a Bloom filter tells you that an element hasn't been seen so far, you can be sure it hasn't. But if it says that an element has been seen, you actually need to check. This still saves a lot of time if there aren't too many duplicates in your list (for those, there is no looping to do, except in the small probability case of a false positive --you typically chose this rate based on how much space you are willing to give to the Bloom filter (rule of thumb: less than 10 bits per unique element for a false positive rate of 1%).
There are many implementations of Bloom filters, see e.g. here or here, so I won't repeat that in this answer. Let us just assume the api described in that last reference, in particular, the description of put(E e):
true if the Bloom filter's bits changed as a result of this operation. If the bits changed, this is definitely the first time object has been added to the filter. If the bits haven't changed, this might be the first time object has been added to the filter. (...)
An implementation using such a Bloom filter would then be:
public static int[] removeDuplicates(int[] arr) {
ArrayList<Integer> out = new ArrayList<>();
int n = arr.length;
BloomFilter<Integer> bf = new BloomFilter<>(...); // decide how many bits and how many hash functions to use (compromise between space and false positive rate)
for (int e : arr) {
boolean might_contain = !bf.put(e);
boolean found = false;
if (might_contain) {
// check if false positive
for (int u : out) {
if (u == e) {
found = true;
break;
}
}
}
if (!found) {
out.add(e);
}
}
return out.stream().mapToInt(i -> i).toArray();
}
Obviously, if you can alter the incoming array in place, then there is no need for an ArrayList: at the end, when you know the actual number of unique elements, just arraycopy() those.
For a sorted Array, just check the next index:
//sorted data!
public static int[] distinct(int[] arr) {
int[] temp = new int[arr.length];
int count = 0;
for (int i = 0; i < arr.length; i++) {
int current = arr[i];
if(count > 0 )
if(temp[count - 1] == current)
continue;
temp[count] = current;
count++;
}
int[] whitelist = new int[count];
System.arraycopy(temp, 0, whitelist, 0, count);
return whitelist;
}
You need to sort your array then then loop and remove duplicates. As you cannot use other tools you need to write be code yourself.
You can easily find examples of quicksort in Java on the internet (on which this example is based).
public static void main(String[] args) throws Exception {
final int[] original = new int[]{1, 1, 2, 8, 9, 8, 4, 7, 4, 9, 1};
System.out.println(Arrays.toString(original));
quicksort(original);
System.out.println(Arrays.toString(original));
final int[] unqiue = new int[original.length];
int prev = original[0];
unqiue[0] = prev;
int count = 1;
for (int i = 1; i < original.length; ++i) {
if (original[i] != prev) {
unqiue[count++] = original[i];
}
prev = original[i];
}
System.out.println(Arrays.toString(unqiue));
final int[] compressed = new int[count];
System.arraycopy(unqiue, 0, compressed, 0, count);
System.out.println(Arrays.toString(compressed));
}
private static void quicksort(final int[] values) {
if (values.length == 0) {
return;
}
quicksort(values, 0, values.length - 1);
}
private static void quicksort(final int[] values, final int low, final int high) {
int i = low, j = high;
int pivot = values[low + (high - low) / 2];
while (i <= j) {
while (values[i] < pivot) {
i++;
}
while (values[j] > pivot) {
j--;
}
if (i <= j) {
swap(values, i, j);
i++;
j--;
}
}
if (low < j) {
quicksort(values, low, j);
}
if (i < high) {
quicksort(values, i, high);
}
}
private static void swap(final int[] values, final int i, final int j) {
final int temp = values[i];
values[i] = values[j];
values[j] = temp;
}
So the process runs in 3 steps.
Sort the array - O(nlgn)
Remove duplicates - O(n)
Compact the array - O(n)
So this improves significantly on your O(n^3) approach.
Output:
[1, 1, 2, 8, 9, 8, 4, 7, 4, 9, 1]
[1, 1, 1, 2, 4, 4, 7, 8, 8, 9, 9]
[1, 2, 4, 7, 8, 9, 0, 0, 0, 0, 0]
[1, 2, 4, 7, 8, 9]
EDIT
OP states values inside array doesn't matter really. But I can assume that range is between 0-1000. This is a classic case where an O(n) sort can be used.
We create an array of size range +1, in this case 1001. We then loop over the data and increment the values on each index corresponding to the datapoint.
We can then compact the resulting array, dropping values the have not been incremented. This makes the values unique as we ignore the count.
public static void main(String[] args) throws Exception {
final int[] original = new int[]{1, 1, 2, 8, 9, 8, 4, 7, 4, 9, 1, 1000, 1000};
System.out.println(Arrays.toString(original));
final int[] buckets = new int[1001];
for (final int i : original) {
buckets[i]++;
}
final int[] unique = new int[original.length];
int count = 0;
for (int i = 0; i < buckets.length; ++i) {
if (buckets[i] > 0) {
unique[count++] = i;
}
}
final int[] compressed = new int[count];
System.arraycopy(unique, 0, compressed, 0, count);
System.out.println(Arrays.toString(compressed));
}
Output:
[1, 1, 2, 8, 9, 8, 4, 7, 4, 9, 1, 1000, 1000]
[1, 2, 4, 7, 8, 9, 1000]
public static void main(String args[]) {
int[] intarray = {1,2,3,4,5,1,2,3,4,5,1,2,3,4,5};
Set<Integer> set = new HashSet<Integer>();
for(int i : intarray) {
set.add(i);
}
Iterator<Integer> setitr = set.iterator();
for(int pos=0; pos < intarray.length; pos ++) {
if(pos < set.size()) {
intarray[pos] =setitr.next();
} else {
intarray[pos]= 0;
}
}
for(int i: intarray)
System.out.println(i);
}
I know this is kinda dead but I just wrote this for my own use. It's more or less the same as adding to a hashset and then pulling all the elements out of it. It should run in O(nlogn) worst case.
public static int[] removeDuplicates(int[] numbers) {
Entry[] entries = new Entry[numbers.length];
int size = 0;
for (int i = 0 ; i < numbers.length ; i++) {
int nextVal = numbers[i];
int index = nextVal % entries.length;
Entry e = entries[index];
if (e == null) {
entries[index] = new Entry(nextVal);
size++;
} else {
if(e.insert(nextVal)) {
size++;
}
}
}
int[] result = new int[size];
int index = 0;
for (int i = 0 ; i < entries.length ; i++) {
Entry current = entries[i];
while (current != null) {
result[i++] = current.value;
current = current.next;
}
}
return result;
}
public static class Entry {
int value;
Entry next;
Entry(int value) {
this.value = value;
}
public boolean insert(int newVal) {
Entry current = this;
Entry prev = null;
while (current != null) {
if (current.value == newVal) {
return false;
} else if(current.next != null) {
prev = current;
current = next;
}
}
prev.next = new Entry(value);
return true;
}
}
int tempvar=0; //Variable for the final array without any duplicates
int whilecount=0; //variable for while loop
while(whilecount<(nsprtable*2)-1) //nsprtable can be any number
{
//to check whether the next value is idential in case of sorted array
if(temparray[whilecount]!=temparray[whilecount+1])
{
finalarray[tempvar]=temparray[whilecount];
tempvar++;
whilecount=whilecount+1;
}
else if (temparray[whilecount]==temparray[whilecount+1])
{
finalarray[tempvar]=temparray[whilecount];
tempvar++;
whilecount=whilecount+2;
}
}
Hope this helps or solves the purpose.
package javaa;
public class UniqueElementinAnArray
{
public static void main(String[] args)
{
int[] a = {10,10,10,10,10,100};
int[] output = new int[a.length];
int count = 0;
int num = 0;
//Iterate over an array
for(int i=0; i<a.length; i++)
{
num=a[i];
boolean flag = check(output,num);
if(flag==false)
{
output[count]=num;
++count;
}
}
//print the all the elements from an array except zero's (0)
for (int i : output)
{
if(i!=0 )
System.out.print(i+" ");
}
}
/***
* If a next number from an array is already exists in unique array then return true else false
* #param arr Unique number array. Initially this array is an empty.
* #param num Number to be search in unique array. Whether it is duplicate or unique.
* #return true: If a number is already exists in an array else false
*/
public static boolean check(int[] arr, int num)
{
boolean flag = false;
for(int i=0;i<arr.length; i++)
{
if(arr[i]==num)
{
flag = true;
break;
}
}
return flag;
}
}
public static int[] removeDuplicates(int[] arr) {
int end = arr.length;
HashSet<Integer> set = new HashSet<Integer>(end);
for(int i = 0 ; i < end ; i++){
set.add(arr[i]);
}
return set.toArray();
}
You can use an auxiliary array (temp) which in indexes are numbers of main array. So the time complexity will be liner and O(n). As we want to do it without using any library, we define another array (unique) to push non-duplicate elements:
var num = [2,4,9,4,1,2,24,12,4];
let temp = [];
let unique = [];
let j = 0;
for (let i = 0; i < num.length; i++){
if (temp[num[i]] !== 1){
temp[num[i]] = 1;
unique[j++] = num[i];
}
}
console.log(unique);
If you are looking to remove duplicates using the same array and also keeping the time complexity of O(n). Then this should do the trick. Also, would only work if the array is sorted.
function removeDuplicates_sorted(arr){
let j = 0;
for(let x = 0; x < arr.length - 1; x++){
if(arr[x] != arr[x + 1]){
arr[j++] = arr[x];
}
}
arr[j++] = arr[arr.length - 1];
arr.length = j;
return arr;
}
Here is for an unsorted array, its O(n) but uses more space complexity then the sorted.
function removeDuplicates_unsorted(arr){
let map = {};
let j = 0;
for(var numbers of arr){
if(!map[numbers]){
map[numbers] = 1;
arr[j++] = numbers;
}
}
arr.length = j;
return arr;
}
Note to other readers who desire to use the Set method of solving this problem: If original ordering must be preserved, do not use HashSet as in the top result. HashSet does not guarantee the preservation of the original order, so LinkedHashSet should be used instead-this keeps track of the order in which the elements were inserted into the set and returns them in that order.
This is an interview question.
public class Test4 {
public static void main(String[] args) {
int a[] = {1, 2, 2, 3, 3, 3, 6,6,6,6,6,66,7,65};
int newlength = lengthofarraywithoutduplicates(a);
for(int i = 0 ; i < newlength ;i++) {
System.out.println(a[i]);
}//for
}//main
private static int lengthofarraywithoutduplicates(int[] a) {
int count = 1 ;
for (int i = 1; i < a.length; i++) {
int ch = a[i];
if(ch != a[i-1]) {
a[count++] = ch;
}//if
}//for
return count;
}//fix
}//end1
But, it's always better to use Stream :
int[] a = {1, 2, 2, 3, 3, 3, 6,6,6,6,6,66,7,65};
int[] array = Arrays.stream(a).distinct().toArray();
System.out.println(Arrays.toString(array));//[1, 2, 3, 6, 66, 7, 65]
How about this one, only for the sorted Array of numbers, to print the Array without duplicates, without using Set or other Collections, just an Array:
public static int[] removeDuplicates(int[] array) {
int[] nums = new int[array.length];
int addedNumber = 0;
int j = 0;
for(int i=0; i < array.length; i++) {
if (addedNumber != array[i]) {
nums[j] = array[i];
j++;
addedNumber = nums[j-1];
}
}
return Arrays.copyOf(nums, j);
}
An array of 1040 duplicated numbers processed in 33020 nanoseconds(0.033020 millisec).
public static void main(String[] args) {
Integer[] intArray = { 1, 1, 1, 2, 4, 2, 3, 5, 3, 6, 7, 3, 4, 5 };
Integer[] finalArray = removeDuplicates(intArray);
System.err.println(Arrays.asList(finalArray));
}
private static Integer[] removeDuplicates(Integer[] intArray) {
int count = 0;
Integer[] interimArray = new Integer[intArray.length];
for (int i = 0; i < intArray.length; i++) {
boolean exists = false;
for (int j = 0; j < interimArray.length; j++) {
if (interimArray[j]!=null && interimArray[j] == intArray[i]) {
exists = true;
}
}
if (!exists) {
interimArray[count] = intArray[i];
count++;
}
}
final Integer[] finalArray = new Integer[count];
System.arraycopy(interimArray, 0, finalArray, 0, count);
return finalArray;
}
I feel Android Killer's idea is great, but I just wondered if we can leverage HashMap. So I did a little experiment. And I found HashMap seems faster than HashSet.
Here is code:
int[] input = new int[1000000];
for (int i = 0; i < input.length; i++) {
Random random = new Random();
input[i] = random.nextInt(200000);
}
long startTime1 = new Date().getTime();
System.out.println("Set start time:" + startTime1);
Set<Integer> resultSet = new HashSet<Integer>();
for (int i = 0; i < input.length; i++) {
resultSet.add(input[i]);
}
long endTime1 = new Date().getTime();
System.out.println("Set end time:"+ endTime1);
System.out.println("result of set:" + (endTime1 - startTime1));
System.out.println("number of Set:" + resultSet.size() + "\n");
long startTime2 = new Date().getTime();
System.out.println("Map start time:" + startTime1);
Map<Integer, Integer> resultMap = new HashMap<Integer, Integer>();
for (int i = 0; i < input.length; i++) {
if (!resultMap.containsKey(input[i]))
resultMap.put(input[i], input[i]);
}
long endTime2 = new Date().getTime();
System.out.println("Map end Time:" + endTime2);
System.out.println("result of Map:" + (endTime2 - startTime2));
System.out.println("number of Map:" + resultMap.size());
Here is result:
Set start time:1441960583837
Set end time:1441960583917
result of set:80
number of Set:198652
Map start time:1441960583837
Map end Time:1441960583983
result of Map:66
number of Map:198652
This is not using Set, Map, List or any extra collection, only two arrays:
package arrays.duplicates;
import java.lang.reflect.Array;
import java.util.Arrays;
public class ArrayDuplicatesRemover<T> {
public static <T> T[] removeDuplicates(T[] input, Class<T> clazz) {
T[] output = (T[]) Array.newInstance(clazz, 0);
for (T t : input) {
if (!inArray(t, output)) {
output = Arrays.copyOf(output, output.length + 1);
output[output.length - 1] = t;
}
}
return output;
}
private static <T> boolean inArray(T search, T[] array) {
for (T element : array) {
if (element.equals(search)) {
return true;
}
}
return false;
}
}
And the main to test it
package arrays.duplicates;
import java.util.Arrays;
public class TestArrayDuplicates {
public static void main(String[] args) {
Integer[] array = {1, 1, 2, 2, 3, 3, 3, 3, 4};
testArrayDuplicatesRemover(array);
}
private static void testArrayDuplicatesRemover(Integer[] array) {
final Integer[] expectedResult = {1, 2, 3, 4};
Integer[] arrayWithoutDuplicates = ArrayDuplicatesRemover.removeDuplicates(array, Integer.class);
System.out.println("Array without duplicates is supposed to be: " + Arrays.toString(expectedResult));
System.out.println("Array without duplicates currently is: " + Arrays.toString(arrayWithoutDuplicates));
System.out.println("Is test passed ok?: " + (Arrays.equals(arrayWithoutDuplicates, expectedResult) ? "YES" : "NO"));
}
}
And the output:
Array without duplicates is supposed to be: [1, 2, 3, 4]
Array without duplicates currently is: [1, 2, 3, 4]
Is test passed ok?: YES
I was asked to write my own implementation to remove duplicated values in an array. Here is what I have created. But after tests with 1,000,000 elements it took very long time to finish. Is there something that I can do to improve my algorithm or any bugs to remove ?
I need to write my own implementation - not to use Set, HashSet etc. Or any other tools such as iterators. Simply an array to remove duplicates.
public static int[] removeDuplicates(int[] arr) {
int end = arr.length;
for (int i = 0; i < end; i++) {
for (int j = i + 1; j < end; j++) {
if (arr[i] == arr[j]) {
int shiftLeft = j;
for (int k = j+1; k < end; k++, shiftLeft++) {
arr[shiftLeft] = arr[k];
}
end--;
j--;
}
}
}
int[] whitelist = new int[end];
for(int i = 0; i < end; i++){
whitelist[i] = arr[i];
}
return whitelist;
}
you can take the help of Set collection
int end = arr.length;
Set<Integer> set = new HashSet<Integer>();
for(int i = 0; i < end; i++){
set.add(arr[i]);
}
now if you will iterate through this set, it will contain only unique values. Iterating code is like this :
Iterator it = set.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
If you are allowed to use Java 8 streams:
Arrays.stream(arr).distinct().toArray();
Note: I am assuming the array is sorted.
Code:
int[] input = new int[]{1, 1, 3, 7, 7, 8, 9, 9, 9, 10};
int current = input[0];
boolean found = false;
for (int i = 0; i < input.length; i++) {
if (current == input[i] && !found) {
found = true;
} else if (current != input[i]) {
System.out.print(" " + current);
current = input[i];
found = false;
}
}
System.out.print(" " + current);
output:
1 3 7 8 9 10
Slight modification to the original code itself, by removing the innermost for loop.
public static int[] removeDuplicates(int[] arr){
int end = arr.length;
for (int i = 0; i < end; i++) {
for (int j = i + 1; j < end; j++) {
if (arr[i] == arr[j]) {
/*int shiftLeft = j;
for (int k = j+1; k < end; k++, shiftLeft++) {
arr[shiftLeft] = arr[k];
}*/
arr[j] = arr[end-1];
end--;
j--;
}
}
}
int[] whitelist = new int[end];
/*for(int i = 0; i < end; i++){
whitelist[i] = arr[i];
}*/
System.arraycopy(arr, 0, whitelist, 0, end);
return whitelist;
}
There exists many solution of this problem.
The sort approach
You sort your array and resolve only unique items
The set approach
You declare a HashSet where you put all item then you have only unique ones.
You create a boolean array that represent the items all ready returned, (this depend on your data in the array).
If you deal with large amount of data i would pick the 1. solution. As you do not allocate additional memory and sorting is quite fast. For small set of data the complexity would be n^2 but for large i will be n log n.
Since you can assume the range is between 0-1000 there is a very simple and efficient solution
//Throws an exception if values are not in the range of 0-1000
public static int[] removeDuplicates(int[] arr) {
boolean[] set = new boolean[1001]; //values must default to false
int totalItems = 0;
for (int i = 0; i < arr.length; ++i) {
if (!set[arr[i]]) {
set[arr[i]] = true;
totalItems++;
}
}
int[] ret = new int[totalItems];
int c = 0;
for (int i = 0; i < set.length; ++i) {
if (set[i]) {
ret[c++] = i;
}
}
return ret;
}
This runs in linear time O(n). Caveat: the returned array is sorted so if that is illegal then this answer is invalid.
class Demo
{
public static void main(String[] args)
{
int a[]={3,2,1,4,2,1};
System.out.print("Before Sorting:");
for (int i=0;i<a.length; i++ )
{
System.out.print(a[i]+"\t");
}
System.out.print ("\nAfter Sorting:");
//sorting the elements
for(int i=0;i<a.length;i++)
{
for(int j=i;j<a.length;j++)
{
if(a[i]>a[j])
{
int temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
}
//After sorting
for(int i=0;i<a.length;i++)
{
System.out.print(a[i]+"\t");
}
System.out.print("\nAfter removing duplicates:");
int b=0;
a[b]=a[0];
for(int i=0;i<a.length;i++)
{
if (a[b]!=a[i])
{
b++;
a[b]=a[i];
}
}
for (int i=0;i<=b;i++ )
{
System.out.print(a[i]+"\t");
}
}
}
OUTPUT:Before Sortng:3 2 1 4 2 1 After Sorting:1 1 2 2 3 4
Removing Duplicates:1 2 3 4
Since this question is still getting a lot of attention, I decided to answer it by copying this answer from Code Review.SE:
You're following the same philosophy as the bubble sort, which is
very, very, very slow. Have you tried this?:
Sort your unordered array with quicksort. Quicksort is much faster
than bubble sort (I know, you are not sorting, but the algorithm you
follow is almost the same as bubble sort to traverse the array).
Then start removing duplicates (repeated values will be next to each
other). In a for loop you could have two indices: source and
destination. (On each loop you copy source to destination unless they
are the same, and increment both by 1). Every time you find a
duplicate you increment source (and don't perform the copy).
#morgano
import java.util.Arrays;
public class Practice {
public static void main(String[] args) {
int a[] = { 1, 3, 3, 4, 2, 1, 5, 6, 7, 7, 8, 10 };
Arrays.sort(a);
int j = 0;
for (int i = 0; i < a.length - 1; i++) {
if (a[i] != a[i + 1]) {
a[j] = a[i];
j++;
}
}
a[j] = a[a.length - 1];
for (int i = 0; i <= j; i++) {
System.out.println(a[i]);
}
}
}
**This is the most simplest way**
What if you create two boolean arrays: 1 for negative values and 1 for positive values and init it all on false.
Then you cycle thorugh the input array and lookup in the arrays if you've encoutered the value already.
If not, you add it to the output array and mark it as already used.
package com.pari.practice;
import java.util.HashSet;
import java.util.Iterator;
import com.pari.sort.Sort;
public class RemoveDuplicates {
/**
* brute force- o(N square)
*
* #param input
* #return
*/
public static int[] removeDups(int[] input){
boolean[] isSame = new boolean[input.length];
int sameNums = 0;
for( int i = 0; i < input.length; i++ ){
for( int j = i+1; j < input.length; j++){
if( input[j] == input[i] ){ //compare same
isSame[j] = true;
sameNums++;
}
}
}
//compact the array into the result.
int[] result = new int[input.length-sameNums];
int count = 0;
for( int i = 0; i < input.length; i++ ){
if( isSame[i] == true) {
continue;
}
else{
result[count] = input[i];
count++;
}
}
return result;
}
/**
* set - o(N)
* does not guarantee order of elements returned - set property
*
* #param input
* #return
*/
public static int[] removeDups1(int[] input){
HashSet myset = new HashSet();
for( int i = 0; i < input.length; i++ ){
myset.add(input[i]);
}
//compact the array into the result.
int[] result = new int[myset.size()];
Iterator setitr = myset.iterator();
int count = 0;
while( setitr.hasNext() ){
result[count] = (int) setitr.next();
count++;
}
return result;
}
/**
* quicksort - o(Nlogn)
*
* #param input
* #return
*/
public static int[] removeDups2(int[] input){
Sort st = new Sort();
st.quickSort(input, 0, input.length-1); //input is sorted
//compact the array into the result.
int[] intermediateResult = new int[input.length];
int count = 0;
int prev = Integer.MIN_VALUE;
for( int i = 0; i < input.length; i++ ){
if( input[i] != prev ){
intermediateResult[count] = input[i];
count++;
}
prev = input[i];
}
int[] result = new int[count];
System.arraycopy(intermediateResult, 0, result, 0, count);
return result;
}
public static void printArray(int[] input){
for( int i = 0; i < input.length; i++ ){
System.out.print(input[i] + " ");
}
}
public static void main(String[] args){
int[] input = {5,6,8,0,1,2,5,9,11,0};
RemoveDuplicates.printArray(RemoveDuplicates.removeDups(input));
System.out.println();
RemoveDuplicates.printArray(RemoveDuplicates.removeDups1(input));
System.out.println();
RemoveDuplicates.printArray(RemoveDuplicates.removeDups2(input));
}
}
Output:
5 6 8 0 1 2 9 11
0 1 2 5 6 8 9 11
0 1 2 5 6 8 9 11
I have just written the above code for trying out. thanks.
public static int[] removeDuplicates(int[] arr){
HashSet<Integer> set = new HashSet<>();
final int len = arr.length;
//changed end to len
for(int i = 0; i < len; i++){
set.add(arr[i]);
}
int[] whitelist = new int[set.size()];
int i = 0;
for (Iterator<Integer> it = set.iterator(); it.hasNext();) {
whitelist[i++] = it.next();
}
return whitelist;
}
Runs in O(N) time instead of your O(N^3) time
Not a big fun of updating user input, however considering your constraints...
public int[] removeDup(int[] nums) {
Arrays.sort(nums);
int x = 0;
for (int i = 0; i < nums.length; i++) {
if (i == 0 || nums[i] != nums[i - 1]) {
nums[x++] = nums[i];
}
}
return Arrays.copyOf(nums, x);
}
Array sort can be easily replaced with any nlog(n) algorithm.
This is simple way to sort the elements in the array
public class DublicatesRemove {
public static void main(String args[]) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("enter size of the array");
int l = Integer.parseInt(br.readLine());
int[] a = new int[l];
// insert elements in the array logic
for (int i = 0; i < l; i++)
{
System.out.println("enter a element");
int el = Integer.parseInt(br.readLine());
a[i] = el;
}
// sorting elements in the array logic
for (int i = 0; i < l; i++)
{
for (int j = 0; j < l - 1; j++)
{
if (a[j] > a[j + 1])
{
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
// remove duplicate elements logic
int b = 0;
a[b] = a[0];
for (int i = 1; i < l; i++)
{
if (a[b] != a[i])
{
b++;
a[b]=a[i];
}
}
for(int i=0;i<=b;i++)
{
System.out.println(a[i]);
}
}
}
Okay, so you cannot use Set or other collections. One solution I don't see here so far is one based on the use of a Bloom filter, which essentially is an array of bits, so perhaps that passes your requirements.
The Bloom filter is a lovely and very handy technique, fast and space-efficient, that can be used to do a quick check of the existence of an element in a set without storing the set itself or the elements. It has a (typically small) false positive rate, but no false negative rate. In other words, for your question, if a Bloom filter tells you that an element hasn't been seen so far, you can be sure it hasn't. But if it says that an element has been seen, you actually need to check. This still saves a lot of time if there aren't too many duplicates in your list (for those, there is no looping to do, except in the small probability case of a false positive --you typically chose this rate based on how much space you are willing to give to the Bloom filter (rule of thumb: less than 10 bits per unique element for a false positive rate of 1%).
There are many implementations of Bloom filters, see e.g. here or here, so I won't repeat that in this answer. Let us just assume the api described in that last reference, in particular, the description of put(E e):
true if the Bloom filter's bits changed as a result of this operation. If the bits changed, this is definitely the first time object has been added to the filter. If the bits haven't changed, this might be the first time object has been added to the filter. (...)
An implementation using such a Bloom filter would then be:
public static int[] removeDuplicates(int[] arr) {
ArrayList<Integer> out = new ArrayList<>();
int n = arr.length;
BloomFilter<Integer> bf = new BloomFilter<>(...); // decide how many bits and how many hash functions to use (compromise between space and false positive rate)
for (int e : arr) {
boolean might_contain = !bf.put(e);
boolean found = false;
if (might_contain) {
// check if false positive
for (int u : out) {
if (u == e) {
found = true;
break;
}
}
}
if (!found) {
out.add(e);
}
}
return out.stream().mapToInt(i -> i).toArray();
}
Obviously, if you can alter the incoming array in place, then there is no need for an ArrayList: at the end, when you know the actual number of unique elements, just arraycopy() those.
For a sorted Array, just check the next index:
//sorted data!
public static int[] distinct(int[] arr) {
int[] temp = new int[arr.length];
int count = 0;
for (int i = 0; i < arr.length; i++) {
int current = arr[i];
if(count > 0 )
if(temp[count - 1] == current)
continue;
temp[count] = current;
count++;
}
int[] whitelist = new int[count];
System.arraycopy(temp, 0, whitelist, 0, count);
return whitelist;
}
You need to sort your array then then loop and remove duplicates. As you cannot use other tools you need to write be code yourself.
You can easily find examples of quicksort in Java on the internet (on which this example is based).
public static void main(String[] args) throws Exception {
final int[] original = new int[]{1, 1, 2, 8, 9, 8, 4, 7, 4, 9, 1};
System.out.println(Arrays.toString(original));
quicksort(original);
System.out.println(Arrays.toString(original));
final int[] unqiue = new int[original.length];
int prev = original[0];
unqiue[0] = prev;
int count = 1;
for (int i = 1; i < original.length; ++i) {
if (original[i] != prev) {
unqiue[count++] = original[i];
}
prev = original[i];
}
System.out.println(Arrays.toString(unqiue));
final int[] compressed = new int[count];
System.arraycopy(unqiue, 0, compressed, 0, count);
System.out.println(Arrays.toString(compressed));
}
private static void quicksort(final int[] values) {
if (values.length == 0) {
return;
}
quicksort(values, 0, values.length - 1);
}
private static void quicksort(final int[] values, final int low, final int high) {
int i = low, j = high;
int pivot = values[low + (high - low) / 2];
while (i <= j) {
while (values[i] < pivot) {
i++;
}
while (values[j] > pivot) {
j--;
}
if (i <= j) {
swap(values, i, j);
i++;
j--;
}
}
if (low < j) {
quicksort(values, low, j);
}
if (i < high) {
quicksort(values, i, high);
}
}
private static void swap(final int[] values, final int i, final int j) {
final int temp = values[i];
values[i] = values[j];
values[j] = temp;
}
So the process runs in 3 steps.
Sort the array - O(nlgn)
Remove duplicates - O(n)
Compact the array - O(n)
So this improves significantly on your O(n^3) approach.
Output:
[1, 1, 2, 8, 9, 8, 4, 7, 4, 9, 1]
[1, 1, 1, 2, 4, 4, 7, 8, 8, 9, 9]
[1, 2, 4, 7, 8, 9, 0, 0, 0, 0, 0]
[1, 2, 4, 7, 8, 9]
EDIT
OP states values inside array doesn't matter really. But I can assume that range is between 0-1000. This is a classic case where an O(n) sort can be used.
We create an array of size range +1, in this case 1001. We then loop over the data and increment the values on each index corresponding to the datapoint.
We can then compact the resulting array, dropping values the have not been incremented. This makes the values unique as we ignore the count.
public static void main(String[] args) throws Exception {
final int[] original = new int[]{1, 1, 2, 8, 9, 8, 4, 7, 4, 9, 1, 1000, 1000};
System.out.println(Arrays.toString(original));
final int[] buckets = new int[1001];
for (final int i : original) {
buckets[i]++;
}
final int[] unique = new int[original.length];
int count = 0;
for (int i = 0; i < buckets.length; ++i) {
if (buckets[i] > 0) {
unique[count++] = i;
}
}
final int[] compressed = new int[count];
System.arraycopy(unique, 0, compressed, 0, count);
System.out.println(Arrays.toString(compressed));
}
Output:
[1, 1, 2, 8, 9, 8, 4, 7, 4, 9, 1, 1000, 1000]
[1, 2, 4, 7, 8, 9, 1000]
public static void main(String args[]) {
int[] intarray = {1,2,3,4,5,1,2,3,4,5,1,2,3,4,5};
Set<Integer> set = new HashSet<Integer>();
for(int i : intarray) {
set.add(i);
}
Iterator<Integer> setitr = set.iterator();
for(int pos=0; pos < intarray.length; pos ++) {
if(pos < set.size()) {
intarray[pos] =setitr.next();
} else {
intarray[pos]= 0;
}
}
for(int i: intarray)
System.out.println(i);
}
I know this is kinda dead but I just wrote this for my own use. It's more or less the same as adding to a hashset and then pulling all the elements out of it. It should run in O(nlogn) worst case.
public static int[] removeDuplicates(int[] numbers) {
Entry[] entries = new Entry[numbers.length];
int size = 0;
for (int i = 0 ; i < numbers.length ; i++) {
int nextVal = numbers[i];
int index = nextVal % entries.length;
Entry e = entries[index];
if (e == null) {
entries[index] = new Entry(nextVal);
size++;
} else {
if(e.insert(nextVal)) {
size++;
}
}
}
int[] result = new int[size];
int index = 0;
for (int i = 0 ; i < entries.length ; i++) {
Entry current = entries[i];
while (current != null) {
result[i++] = current.value;
current = current.next;
}
}
return result;
}
public static class Entry {
int value;
Entry next;
Entry(int value) {
this.value = value;
}
public boolean insert(int newVal) {
Entry current = this;
Entry prev = null;
while (current != null) {
if (current.value == newVal) {
return false;
} else if(current.next != null) {
prev = current;
current = next;
}
}
prev.next = new Entry(value);
return true;
}
}
int tempvar=0; //Variable for the final array without any duplicates
int whilecount=0; //variable for while loop
while(whilecount<(nsprtable*2)-1) //nsprtable can be any number
{
//to check whether the next value is idential in case of sorted array
if(temparray[whilecount]!=temparray[whilecount+1])
{
finalarray[tempvar]=temparray[whilecount];
tempvar++;
whilecount=whilecount+1;
}
else if (temparray[whilecount]==temparray[whilecount+1])
{
finalarray[tempvar]=temparray[whilecount];
tempvar++;
whilecount=whilecount+2;
}
}
Hope this helps or solves the purpose.
package javaa;
public class UniqueElementinAnArray
{
public static void main(String[] args)
{
int[] a = {10,10,10,10,10,100};
int[] output = new int[a.length];
int count = 0;
int num = 0;
//Iterate over an array
for(int i=0; i<a.length; i++)
{
num=a[i];
boolean flag = check(output,num);
if(flag==false)
{
output[count]=num;
++count;
}
}
//print the all the elements from an array except zero's (0)
for (int i : output)
{
if(i!=0 )
System.out.print(i+" ");
}
}
/***
* If a next number from an array is already exists in unique array then return true else false
* #param arr Unique number array. Initially this array is an empty.
* #param num Number to be search in unique array. Whether it is duplicate or unique.
* #return true: If a number is already exists in an array else false
*/
public static boolean check(int[] arr, int num)
{
boolean flag = false;
for(int i=0;i<arr.length; i++)
{
if(arr[i]==num)
{
flag = true;
break;
}
}
return flag;
}
}
public static int[] removeDuplicates(int[] arr) {
int end = arr.length;
HashSet<Integer> set = new HashSet<Integer>(end);
for(int i = 0 ; i < end ; i++){
set.add(arr[i]);
}
return set.toArray();
}
You can use an auxiliary array (temp) which in indexes are numbers of main array. So the time complexity will be liner and O(n). As we want to do it without using any library, we define another array (unique) to push non-duplicate elements:
var num = [2,4,9,4,1,2,24,12,4];
let temp = [];
let unique = [];
let j = 0;
for (let i = 0; i < num.length; i++){
if (temp[num[i]] !== 1){
temp[num[i]] = 1;
unique[j++] = num[i];
}
}
console.log(unique);
If you are looking to remove duplicates using the same array and also keeping the time complexity of O(n). Then this should do the trick. Also, would only work if the array is sorted.
function removeDuplicates_sorted(arr){
let j = 0;
for(let x = 0; x < arr.length - 1; x++){
if(arr[x] != arr[x + 1]){
arr[j++] = arr[x];
}
}
arr[j++] = arr[arr.length - 1];
arr.length = j;
return arr;
}
Here is for an unsorted array, its O(n) but uses more space complexity then the sorted.
function removeDuplicates_unsorted(arr){
let map = {};
let j = 0;
for(var numbers of arr){
if(!map[numbers]){
map[numbers] = 1;
arr[j++] = numbers;
}
}
arr.length = j;
return arr;
}
Note to other readers who desire to use the Set method of solving this problem: If original ordering must be preserved, do not use HashSet as in the top result. HashSet does not guarantee the preservation of the original order, so LinkedHashSet should be used instead-this keeps track of the order in which the elements were inserted into the set and returns them in that order.
This is an interview question.
public class Test4 {
public static void main(String[] args) {
int a[] = {1, 2, 2, 3, 3, 3, 6,6,6,6,6,66,7,65};
int newlength = lengthofarraywithoutduplicates(a);
for(int i = 0 ; i < newlength ;i++) {
System.out.println(a[i]);
}//for
}//main
private static int lengthofarraywithoutduplicates(int[] a) {
int count = 1 ;
for (int i = 1; i < a.length; i++) {
int ch = a[i];
if(ch != a[i-1]) {
a[count++] = ch;
}//if
}//for
return count;
}//fix
}//end1
But, it's always better to use Stream :
int[] a = {1, 2, 2, 3, 3, 3, 6,6,6,6,6,66,7,65};
int[] array = Arrays.stream(a).distinct().toArray();
System.out.println(Arrays.toString(array));//[1, 2, 3, 6, 66, 7, 65]
How about this one, only for the sorted Array of numbers, to print the Array without duplicates, without using Set or other Collections, just an Array:
public static int[] removeDuplicates(int[] array) {
int[] nums = new int[array.length];
int addedNumber = 0;
int j = 0;
for(int i=0; i < array.length; i++) {
if (addedNumber != array[i]) {
nums[j] = array[i];
j++;
addedNumber = nums[j-1];
}
}
return Arrays.copyOf(nums, j);
}
An array of 1040 duplicated numbers processed in 33020 nanoseconds(0.033020 millisec).
public static void main(String[] args) {
Integer[] intArray = { 1, 1, 1, 2, 4, 2, 3, 5, 3, 6, 7, 3, 4, 5 };
Integer[] finalArray = removeDuplicates(intArray);
System.err.println(Arrays.asList(finalArray));
}
private static Integer[] removeDuplicates(Integer[] intArray) {
int count = 0;
Integer[] interimArray = new Integer[intArray.length];
for (int i = 0; i < intArray.length; i++) {
boolean exists = false;
for (int j = 0; j < interimArray.length; j++) {
if (interimArray[j]!=null && interimArray[j] == intArray[i]) {
exists = true;
}
}
if (!exists) {
interimArray[count] = intArray[i];
count++;
}
}
final Integer[] finalArray = new Integer[count];
System.arraycopy(interimArray, 0, finalArray, 0, count);
return finalArray;
}
I feel Android Killer's idea is great, but I just wondered if we can leverage HashMap. So I did a little experiment. And I found HashMap seems faster than HashSet.
Here is code:
int[] input = new int[1000000];
for (int i = 0; i < input.length; i++) {
Random random = new Random();
input[i] = random.nextInt(200000);
}
long startTime1 = new Date().getTime();
System.out.println("Set start time:" + startTime1);
Set<Integer> resultSet = new HashSet<Integer>();
for (int i = 0; i < input.length; i++) {
resultSet.add(input[i]);
}
long endTime1 = new Date().getTime();
System.out.println("Set end time:"+ endTime1);
System.out.println("result of set:" + (endTime1 - startTime1));
System.out.println("number of Set:" + resultSet.size() + "\n");
long startTime2 = new Date().getTime();
System.out.println("Map start time:" + startTime1);
Map<Integer, Integer> resultMap = new HashMap<Integer, Integer>();
for (int i = 0; i < input.length; i++) {
if (!resultMap.containsKey(input[i]))
resultMap.put(input[i], input[i]);
}
long endTime2 = new Date().getTime();
System.out.println("Map end Time:" + endTime2);
System.out.println("result of Map:" + (endTime2 - startTime2));
System.out.println("number of Map:" + resultMap.size());
Here is result:
Set start time:1441960583837
Set end time:1441960583917
result of set:80
number of Set:198652
Map start time:1441960583837
Map end Time:1441960583983
result of Map:66
number of Map:198652
This is not using Set, Map, List or any extra collection, only two arrays:
package arrays.duplicates;
import java.lang.reflect.Array;
import java.util.Arrays;
public class ArrayDuplicatesRemover<T> {
public static <T> T[] removeDuplicates(T[] input, Class<T> clazz) {
T[] output = (T[]) Array.newInstance(clazz, 0);
for (T t : input) {
if (!inArray(t, output)) {
output = Arrays.copyOf(output, output.length + 1);
output[output.length - 1] = t;
}
}
return output;
}
private static <T> boolean inArray(T search, T[] array) {
for (T element : array) {
if (element.equals(search)) {
return true;
}
}
return false;
}
}
And the main to test it
package arrays.duplicates;
import java.util.Arrays;
public class TestArrayDuplicates {
public static void main(String[] args) {
Integer[] array = {1, 1, 2, 2, 3, 3, 3, 3, 4};
testArrayDuplicatesRemover(array);
}
private static void testArrayDuplicatesRemover(Integer[] array) {
final Integer[] expectedResult = {1, 2, 3, 4};
Integer[] arrayWithoutDuplicates = ArrayDuplicatesRemover.removeDuplicates(array, Integer.class);
System.out.println("Array without duplicates is supposed to be: " + Arrays.toString(expectedResult));
System.out.println("Array without duplicates currently is: " + Arrays.toString(arrayWithoutDuplicates));
System.out.println("Is test passed ok?: " + (Arrays.equals(arrayWithoutDuplicates, expectedResult) ? "YES" : "NO"));
}
}
And the output:
Array without duplicates is supposed to be: [1, 2, 3, 4]
Array without duplicates currently is: [1, 2, 3, 4]
Is test passed ok?: YES
Find the first covering prefix of a given array.
A non-empty zero-indexed array A consisting of N integers is given. The first covering
prefix of array A is the smallest integer P such that and such that every value that
occurs in array A also occurs in sequence.
For example, the first covering prefix of array A with
A[0]=2, A[1]=2, A[2]=1, A[3]=0, A[4]=1 is 3, because sequence A[0],
A[1], A[2], A[3] equal to 2, 2, 1, 0 contains all values that occur in
array A.
My solution is
int ps ( int[] A )
{
int largestvalue=0;
int index=0;
for(each element in Array){
if(A[i]>largestvalue)
{
largestvalue=A[i];
index=i;
}
}
for(each element in Array)
{
if(A[i]==index)
index=i;
}
return index;
}
But this only works for this input, this is not a generalized solution.
Got 100% with the below.
public int ps (int[] a)
{
var length = a.Length;
var temp = new HashSet<int>();
var result = 0;
for (int i=0; i<length; i++)
{
if (!temp.Contains(a[i]))
{
temp.Add(a[i]);
result = i;
}
}
return result;
}
I would do this
int coveringPrefixIndex(final int[] arr) {
Map<Integer,Integer> indexes = new HashMap<Integer,Integer>();
// start from the back
for(int i = arr.length - 1; i >= 0; i--) {
indexes.put(arr[i],i);
}
// now find the highest value in the map
int highestIndex = 0;
for(Integer i : indexes.values()) {
if(highestIndex < i.intValue()) highestIndex = i.intValue();
}
return highestIndex;
}
Your question is from Alpha 2010 Start Challenge of Codility platform. And here is my solution which got score of 100. The idea is simple, I track an array of counters for the input array. Traversing the input array backwards, decrement the respective counter, if that counter becomes zero it means we have found the first covering prefix.
public static int solution(int[] A) {
int size = A.length;
int[] counters = new int[size];
for (int a : A)
counters[a]++;
for (int i = size - 1; i >= 0; i--) {
if (--counters[A[i]] == 0)
return i;
}
return 0;
}
here's my solution in C#:
public static int CoveringPrefix(int[] Array1)
{
// Step 1. Get length of Array1
int Array1Length = 0;
foreach (int i in Array1) Array1Length++;
// Step 2. Create a second array with the highest value of the first array as its length
int highestNum = 0;
for (int i = 0; i < Array1Length; i++)
{
if (Array1[i] > highestNum) highestNum = Array1[i];
}
highestNum++; // Make array compatible for our operation
int[] Array2 = new int[highestNum];
for (int i = 0; i < highestNum; i++) Array2[i] = 0; // Fill values with zeros
// Step 3. Final operation will determine unique values in Array1 and return the index of the highest unique value
int highestIndex = 0;
for (int i = 0; i < Array1Length; i++)
{
if (Array2[Array1[i]] < 1)
{
Array2[Array1[i]]++;
highestIndex = i;
}
}
return highestIndex;
}
100p
public static int ps(int[] a) {
Set<Integer> temp = new HashSet<Integer>();
int p = 0;
for (int i = 0; i < a.length; i++) {
if (temp.add(a[i])) {
p = i+1;
}
}
return p;
}
You can try this solution as well
import java.util.HashSet;
import java.util.Set;
class Solution {
public int ps ( int[] A ) {
Set set = new HashSet();
int index =-1;
for(int i=0;i<A.length;i++){
if(set.contains(A[i])){
if(index==-1)
index = i;
}else{
index = i;
set.add(A[i]);
}
}
return index;
}
}
Without using any Collection:
search the index of the first occurrence of each element,
the prefix is the maximum of that index. Do it backwards to finish early:
private static int prefix(int[] array) {
int max = -1;
int i = array.length - 1;
while (i > max) {
for (int j = 0; j <= i; j++) { // include i
if (array[i] == array[j]) {
if (j > max) {
max = j;
}
break;
}
}
i--;
}
return max;
}
// TEST
private static void test(int... array) {
int prefix = prefix(array);
int[] segment = Arrays.copyOf(array, prefix+1);
System.out.printf("%s = %d = %s%n", Arrays.toString(array), prefix, Arrays.toString(segment));
}
public static void main(String[] args) {
test(2, 2, 1, 0, 1);
test(2, 2, 1, 0, 4);
test(2, 0, 1, 0, 1, 2);
test(1, 1, 1);
test(1, 2, 3);
test(4);
test(); // empty array
}
This is what I tried first. I got 24%
public int ps ( int[] A ) {
int n = A.length, i = 0, r = 0,j = 0;
for (i=0;i<n;i++) {
for (j=0;j<n;j++) {
if ((long) A[i] == (long) A[j]) {
r += 1;
}
if (r == n) return i;
}
}
return -1;
}
//method must be public for codility to access
public int solution(int A[]){
Set<Integer> set = new HashSet<Integer>(A.length);
int index= A[0];
for (int i = 0; i < A.length; i++) {
if( set.contains(A[i])) continue;
index = i;
set.add(A[i]);
}
return index;
}
this got 100%, however detected time was O(N * log N) due to the HashSet.
your solutions without hashsets i don't really follow...
shortest code possible in java:
public static int solution(int A[]){
Set<Integer> set = new HashSet<Integer>(A.length);//avoid resizing
int index= -1; //value does not matter;
for (int i = 0; i < A.length; i++)
if( !set.contains(A[i])) set.add(A[index = i]); //assignment + eval
return index;
}
I got 100% with this one:
public int solution (int A[]){
int index = -1;
boolean found[] = new boolean[A.length];
for (int i = 0; i < A.length; i++)
if (!found [A[i]] ){
index = i;
found [A[i]] = true;
}
return index;
}
I used a boolean array which keeps track of the read elements.
This is what I did in Java to achieve 100% correctness and 81% performance, using a list to store and compare the values with.
It wasn't quick enough to pass random_n_log_100000 random_n_10000 or random_n_100000 tests, but it is a correct answer.
public int solution(int[] A) {
int N = A.length;
ArrayList<Integer> temp = new ArrayList<Integer>();
for(int i=0; i<N; i++){
if(!temp.contains(A[i])){
temp.add(A[i]);
}
}
for(int j=0; j<N; j++){
if(temp.contains(A[j])){
temp.remove((Object)A[j]);
}
if(temp.isEmpty()){
return j;
}
}
return -1;
}
Correctness and Performance: 100%:
import java.util.HashMap;
class Solution {
public int solution(int[] inputArray)
{
int covering;
int[] A = inputArray;
int N = A.length;
HashMap<Integer, Integer> map = new HashMap<>();
covering = 0;
for (int i = 0; i < N; i++)
{
if (map.get(A[i]) == null)
{
map.put(A[i], A[i]);
covering = i;
}
}
return covering;
}
}
Here is my Objective-C Solution to PrefixSet from Codility. 100% correctness and performance.
What can be changed to make it even more efficient? (without out using c code).
HOW IT WORKS:
Everytime I come across a number in the array I check to see if I have added it to the dictionary yet.
If it is in the dictionary then I know it is not a new number so not important in relation to the problem. If it is a new number that we haven't come across already, then I need to update the indexOftheLastPrefix to this array position and add it to the dictionary as a key.
It only used one for loop so takes just one pass. Objective-c code is quiet heavy so would like to hear of any tweaks to make this go faster. It did get 100% for performance though.
int solution(NSMutableArray *A)
{
NSUInteger arraySize = [A count];
NSUInteger indexOflastPrefix=0;
NSMutableDictionary *myDict = [[NSMutableDictionary alloc] init];
for (int i=0; i<arraySize; i++)
{
if ([myDict objectForKey:[[A objectAtIndex:i]stringValue]])
{
}
else
{
[myDict setValue:#"YES" forKey:[[A objectAtIndex:i]stringValue]];
indexOflastPrefix = i;
}
}
return indexOflastPrefix;
}
int solution(vector &A) {
// write your code in C++11 (g++ 4.8.2)
int max = 0, min = -1;
int maxindex =0,minindex = 0;
min = max =A[0];
for(unsigned int i=1;i<A.size();i++)
{
if(max < A[i] )
{
max = A[i];
maxindex =i;
}
if(min > A[i])
{
min =A[i];
minindex = i;
}
}
if(maxindex > minindex)
return maxindex;
else
return minindex;
}
fwiw: Also gets 100% on codility and it's easy to understand with only one HashMap
public static int solution(int[] A) {
// write your code in Java SE 8
int firstCoveringPrefix = 0;
//HashMap stores unique keys
HashMap hm = new HashMap();
for(int i = 0; i < A.length; i++){
if(!hm.containsKey(A[i])){
hm.put( A[i] , i );
firstCoveringPrefix = i;
}
}
return firstCoveringPrefix;
}
I was looking for the this answer in JavaScript but didn't find it so I convert the Java answer to javascript and got 93%
function solution(A) {
result=0;
temp = [];
for(i=0;i<A.length;i++){
if (!temp.includes(A[i])){
temp.push(A[i]);
result=i;
}
}
return result;
}
// you can also use imports, for example:
import java.util.*;
// you can use System.out.println for debugging purposes, e.g.
// System.out.println("this is a debug message");
class Solution {
public int solution(int[] A) {
// write your code in Java SE 8
Set<Integer> s = new HashSet<Integer>();
int index = 0;
for (int i = 0; i < A.length; i++) {
if (!s.contains(A[i])) {
s.add(A[i]);
index = i;
}
}
return index;
}
}