How to remove duplicate elements from a sorted array - java

Given a sorted array A of size N, delete all the duplicates elements from A.
Note: Don't use set or HashMap to solve the problem.
example:
Input:
N = 5
Array = {2, 2, 2, 2, 2}
Output:
2
Explanation: After removing all the duplicates
only one instance of 2 will remain.
I have tried the below code. Please tell me what's wrong with the code?
int remove_duplicate(int arr[],int N){
// code here
int index=0;
for(int i=1;i<N;i++){
if(arr[i]!=arr[i-1]){
arr[index]=arr[i-1];
index++;
}
}
return index+1;
}

You could replace some duplicate elements and set the length at the end.
This approach mutates the array.
const
remove_duplicate = array => {
let j = 0;
for (let i = 0; i < array.length; i++) {
if (array[j - 1] !== array[i]) array[j++] = array[i];
}
array.length = j;
return array;
};
console.log(...remove_duplicate([2, 2, 2]));
console.log(...remove_duplicate([1, 1, 2, 2, 3, 4, 5, 5]));

Overkill using binary tree
BinaryTree binaryTree = new BinaryTree();
for (int i = 0; i < n; i++){
//add or insert function need to check that the key isn't in the stracture
binaryTree.Add(arr[i]);
}
binaryTree.TraverseInOrder(binaryTree.Root);
You need to implement some of the classes.
Check this example:
c-binary-search-tree-implementation
For more on Inorder output for binaryTree:
binary-tree-from-inorder-traversal

Look here: https://www.geeksforgeeks.org/duplicates-array-using-o1-extra-space-set-2/
// Java program to print all elements that
// appear more than once.
import java.util.*;
class GFG {
// function to find repeating elements
static void printRepeating(int arr[], int n)
{
// First check all the values that are
// present in an array then go to that
// values as indexes and increment by
// the size of array
for (int i = 0; i < n; i++)
{
int index = arr[i] % n;
arr[index] += n;
}
// Now check which value exists more
// than once by dividing with the size
// of array
for (int i = 0; i < n; i++)
{
if ((arr[i] / n) >= 2)
System.out.println(i + " ");
}
}
// Driver code
public static void main(String args[])
{
int arr[] = { 1, 6, 3, 1, 3, 6, 6 };
int arr_size = arr.length;
System.out.println("The repeating elements are: ");
// Function call
printRepeating(arr, arr_size);
}
}

Try this:
int remove_duplicate(int arr[],int N){
int index=0;
for(int i=1;i<N;i++){
if(arr[i]!=arr[index]){ //change index
index++; //swapt next line
arr[index]=arr[i];
}
}
return index+1;
}

you can check my answer here - and it works perfectly
https://stackoverflow.com/a/32931932/3052125
Here is the main logic to remove the duplicates - arr is the sorted array provided to you with duplicate elements -
// Logic for removing the duplicate elements
int compare = 0;
arr[compare] = arr[0];
for (int i = 1; i < size; i++) {
if (arr[compare] != arr[i]) {
compare++;
arr[compare] = arr[i];
}
}

Given a sorted array A of size N, delete all the duplicates elements from A
Well, that implies returning an array with duplicates deleted.
int[] v = { 1, 1, 1, 2, 2, 2, 2,3 };
v = remove_duplicates(v);
System.out.println(Arrays.toString(v));
prints
[1, 2, 3]
The method. This works by copying the unique values toward the front of the passed array. So this does alter that array.
public static int[] remove_duplicates(int[] v) {
int current = 0;
for (int i = 0; i < v.length; i++) {
if (v[i] != v[current]) {
v[++current] = v[i];
}
}
// Now return the front portion of the array that contains the distinct
// values. You could also just create a new array and copy the elements
// using a loop.
return Arrays.copyOf(v, current+1);
}

Related

How can I count these duplicate integers? [duplicate]

This question already has answers here:
How to count duplicate elements in ArrayList?
(13 answers)
Closed 4 years ago.
I must not modify the contents of the array, like using Array.sort().
Expected return of this code is 6, because there are three duplicates of the value 1, one duplicate of the value 2, and two duplicates of the value 4. but mine is showing 10. I know the reason why it is 10: it's counting the duplicates multiple times.
How can I make this code check duplicate integer only once?
private int count = 0;
public void run() {
int[] a = {1, 4, 2, 4, 7, 1, 1, 9, 2, 3, 4, 1};
println(countDuplicates(a));
}
private int countDuplicates(int[] a) {
for (int i = 0; i < a.length; i++) {
for (int j = i + 1; j < a.length; j++) {
if (a[i] == a[j]) {
count++;
}
}
}
return count;
}
One option would be to take the current size minus the size with duplicates removed:
Set<Integer> set = new HashSet<>();
for (int i=0; i < a.length; ++i) {
set.add(a[i]);
}
int numDuplicates = a.length - set.size();
There is probably a sleek way to populate a set of Integer from an array of primitive int using streams in Java 8.
Here you go with simple to understand logic for leaners
public static void main(String[] args) throws IOException {
int []a ={1, 4, 2, 4, 7, 1, 1, 9, 2, 3, 4, 1};
Map<Integer, Integer> occurances = new HashMap<>();
for(int i = 0; i < a.length; i++) {
//Check the is already occurred if not then add occurrence as 1
if (!occurances.containsKey(a[i])) {
occurances.put(a[i], 1);
}
// Second occurrences for a number
else {
occurances.put(a[i], occurances.get(a[i]) + 1);
}
}
System.out.println(occurances);
System.out.println("Total Numbers: "+a.length);
System.out.println("Duplicate count is "+ (a.length - occurances.size()));
}
Sort the array in-place.
Run through the array once, and count how many times current value is equal to previous value.
(Assuming you are allowed to use a library method to sort the array)
private static int countDuplicates(final int[] a)
{
int count = 0;
Arrays.sort(a); // sort array, you can use any way for it
for (int i = 0; i < a.length - 1; i++)
{
if (a[i] == a[i + 1]) // check only next element
{
count++;
}
}
return count; // return 6
}

Java - Obtain the indexes in ascending order of an int array

I have an int array as [2,4,1,0,0,3] and need to obtain from that an array of the indexes in ascending order, means [3,4,2,0,5,1].
I tried to resolve this by using a sorted array to get the numbers in order, then iterating over the original array to find the index when a match happens. As follows:
public class IndexAscendingSorter {
public static void main (String[] args) {
int[] array = {2,4,1,0,0,3};
IndexAscendingSorter finder = new IndexAscendingSorter();
int[] indixes = finder.orderIndexAscending(array);
System.out.println("Indexes of the array in ascending order: " +
Arrays.toString(indixes));
}
public int[] orderIndexAscending(int[] array) {
int[] minimumIndexes = new int[array.length];
int[] sortedArray = array.clone();
Arrays.sort(sortedArray);
for (int index = 0; index < array.length; index++){
int minIndex = 0;
for (int number : array) {
if (number == sortedArray[index]) {
minimumIndexes[index] = minIndex;
break;
}
minIndex++;
}
}
return minimumIndexes;
}
}
The problem is that for same numbers don't return the correct indexes, the output of executing that code is:
Indexes of the array in ascending order: [3, 3, 2, 0, 5, 1]
The second value array[1] should have been 4 instead of 3. Does anyone know how can I improve this?
Continuing with your approach, a quick solution would be to use a hash set where you will add the indexes you have already used, and then can check if it is a repeated index. Just change the orderIndexAscending() function to:
public int[] orderIndexAscending(int[] array) {
int[] minimumIndexes = new int[array.length];
int[] sortedArray = array.clone();
Arrays.sort(sortedArray);
Set<Integer> savedIndexes = new HashSet<>();
for (int index = 0; index < array.length; index++){
int minIndex = 0;
// Add the index in ascending order, we need to keep the indexes already
// saved, so won't miss indexes from repeted values
for (int number : array) {
if (number == sortedArray[index] && !savedIndexes.contains(minIndex)) {
savedIndexes.add(minIndex);
minimumIndexes[index] = minIndex;
break;
}
minIndex++;
}
}
return minimumIndexes;
}
}
Pair the numbers with their original indices:
[2,4,1,0,0,3] => [[2,0],[4,1],[1,2],[0,3],[0,4],[3,5]]]
Then sort by the original value:
=> [[0,3],[0,4],[1,2],[2,0],[3,5],[4,1]]]
And lastly extract the indices:
=> [3,4,2,0,5,1]
Initialize the index array to the Integers 0, 1, 2, 3, ..., then sort it, using a custom comperator that looks up the corresponding array values and compares them.
for (int index = 0; index < array.length; index++){
int minIndex = 0;
for (int number : array) {
if (number == sortedArray[index]) {
minimumIndexes[index] = minIndex;
array[minIndex]=Integer.MAX_VALUE;
break;
}
minIndex++;
}
}
You can simply update already visited value with any value never present in the array.
You may simply update the value that has already been visited with any value that is not present in the array.
for (int index = 0; index < array.length; index++){
int minIndex = 0;
for (int number : array) {
if (number == sortedArray[index]) {
minimumIndexes[index] = minIndex;
array[minIndex]=Integer.MAX_VALUE;
break;
}
minIndex++;
}
}

Remove duplicates in array, zero padding at end

I have a task, to remove duplicates in array, what by "remove" means to shift elements down by 1, and making the last element equal to 0,
so if I have int[] array = {1, 1, 2, 2, 3, 2}; output should be like:
1, 2, 3, 0, 0, 0
I tried this logic:
public class ArrayDuplicates {
public static void main(String[] args) {
int[] array = {1, 1, 2, 2, 3, 2};
System.out.println(Arrays.toString(deleteArrayDuplicates(array)));
}
public static int[] deleteArrayDuplicates(int[] array) {
for (int i = 0; i < array.length; i++) {
for (int j = i + 1; j < array.length; j++) {
if (array[i] == array[j]) { //this is for comparing elements
for (; i > 0; i--) {
array[j + 1] = array[j]; //this is for shifting
}
array[array.length - 1] = 0; //making last element equal to "0"
}
}
}
return array;
}
}
But it doesn't work.. Is anyone familiar with a right solution?
I appreciate your assistance and attention very much.
Your Code:
In short, the approach you have chosen calls for a third loop variable, k, to represent the index that is currently being shifted left by 1 position.
i - the current unique item's position
j - the current position being tested for equality with unique item at i
k - the current position being shifted left due to erasure at j
Suggestion:
A more efficient approach would be to eliminate the repetitive left shifting which occurs each time a duplicate is found and instead keep track of an offset based on the number of duplicates found:
private static int[] deleteArrayDuplicates(int[] array) {
int dupes = 0; // total duplicates
// i - the current unique item's position
for (int i = 0; i < array.length - 1 - dupes; i++) {
int idupes = 0; // duplicates for current value of i
// j - the current position being tested for equality with unique item at i
for (int j = i + 1; j < array.length - dupes; j++) {
if (array[i] == array[j]) {
idupes++;
dupes++;
} else if(idupes > 0){
array[j-idupes] = array[j];
}
}
}
if(dupes > 0) {
Arrays.fill(array, array.length-dupes, array.length, 0);
}
return array;
}
This has similar complexity to the answer posted by dbl, although it should be slightly faster due to eliminating some extra loops at the end. Another advantage is that this code doesn't rely on any assumptions that the input should not contain zeroes, unlike that answer.
#artshakhov:
Here is my approach, which is pretty much close enough to what you've found but using a bit fewer operations...
private static int[] deleteArrayDuplicates(int[] array) {
for (int i = 0; i < array.length - 1; i++) {
if (array[i] == NEUTRAL) continue; //if zero is a valid input value then don't waste time with it
int idx = i + 1; //no need for third cycle, just use memorization for current shifting index.
for (int j = i + 1; j < array.length; j++) {
if (array[i] == array[j]) {
array[j] = NEUTRAL;
} else {
array[idx++] = array[j];
}
}
}
return array;
}
I just wrote the following code to answer your question. I tested it and I am getting the output you expected. If there are any special cases I may have missed, I apologize but it seemed to work for a variety of inputs including yours.
The idea behind is that we will be using a hash map to keep track if we have already seen a particular element in our array as we are looping through the array. If the map already contains that element- meaning we have already seen that element in our array- we just keep looping. However, if it is our first time seeing that element, we will update the element at the index where j is pointing to the element at the index where i is pointing to and then increment j.
So basically through the j pointer, we are able to move all the distinct elements to the front of the array while also making sure it is in the same order as it is in our input array.
Now after the first loop, our j pointer points to the first repeating element in our array. We can just set i to j and loop through the rest of the array, making them zero.
The time complexity for this algorithm is O(N). The space complexity is O(N) because of the hash table. There is probably a way to do this in O(N) time, O(1) space.
public static int[] deleteArrayDuplicates(int[] array) {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
int j = 0;
for (int i = 0; i < array.length; i++) {
if (map.containsKey(array[i])) {
continue;
}
else {
map.put(array[i],1);
array[j] = array[i];
j++;
}
}
for (int i = j; i < array.length; i++) {
array[i] = 0;
}
return array;
}
Let me know if you have additional questions.
Spent a couple of hours trying to find a solution for my own, and created something like this:
public static int[] deleteArrayDuplicates(int[] array) {
for (int i = 0; i < array.length; i++) {
for (int j = i + 1; j < array.length; j++) {
if (array[j] == array[i]) { //this is for comparing elements
int tempIndex = j;
while (tempIndex + 1 < array.length) {
array[tempIndex] = array[tempIndex + 1]; //this is for shifting elements down/left by "1"
array[array.length - 1] = 0; //making last element equal to "0"
tempIndex++;
}
}
}
}
return array;
}
Code is without any API-helpers, but seems like is working now.
Try this:
public static void main(String[] args)
{
int a[]={1,1,1,2,3,4,5};
int b[]=new int[a.length];
int top=0;
for( int i : a )
{
int count=0;
for(int j=0;j<top;j++)
{
if(i == b[j])
count+=1;
}
if(count==0)
{
b[top]=i;
top+=1;
}
}
for(int i=0 ; i < b.length ; i++ )
System.out.println( b[i] );
}
Explanation:
Create an another array ( b ) of same size of the given array.Now just include only the unique elements in the array b. Add the elements of array a to array b only if that element is not present in b.
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class StackOverFlow {
public static void main(String[] args) {
int[] array = {1, 1, 2, 2, 3, 2};
Set<Integer> set=new HashSet<>();
for (int anArray : array) {
set.add(anArray);
}
int[] a=new int[array.length];
int i=0;
for (Integer s:set) {
a[i]=s;
i++;
}
System.out.println(Arrays.toString(a));
}
}
Hope this simple one may help you.
Make use of Set which doesn't allow duplicates.
We can use ARRAYLIST and Java-8 Streams features to get the output.
public static int[] deleteArrayDuplicates(int[] array) {
List<Integer> list = new ArrayList(Arrays.stream(array).boxed().distinct().collect(Collectors.toList()));
for (int i = 0; i < array.length; i++) {
if (i < list.size()) {
array[i] = list.get(i);
} else {
array[i] = 0;
}
}
return array;
}
OUTPUT
[1, 2, 3, 0, 0, 0]

How to Delete All Elements That Have an Even Index in Java ArrayList

I'm trying to write a method that removes all ArrayList elements that have an even index. I would like to accomplish this without using any auxiliary data structures. I'm thinking that I should set all even index items to null. Then, I'll try to remove all null elements.
Example:
{1, 2, 3, 4, 5, 6}
Should change to this
{1, 3, 5}
I was able to find the even positions, but I still can't figure out how to remove them from the ArrayList.
public void removeEvenElems() {
for (int i = 0; i < size; i++) {
if (i % 2 == 0) {
//how to delete array[i] ?
}
}
}
This will work try it :
The current is 1 and will increase by 2 every time get in the loop to store the odd elements
public void removeEvenElems() {
current = 1;
for (int i = 0; i < size; i++) {
nodes[i] = nodes[current];
size--;
current = current + 2;
}
}
Since you don't want to use ArrayList or call any additional functions, this code creates a new array
public void removeEvenElems(int[] array) {
int[] temp = new int[array.length];
int spot = 0;
for (int i = 0; i < array.length; i++) {
if (i % 2 == 1) {
temp[spot] = array[i];
spot++;
}
}
System.arraycopy( temp, 0, array, 0, spot+1 );
}

How to remove duplicates from a list using an auxiliary array in Java?

I am trying to remove duplicates from a list by creating a temporary array that stores the indices of where the duplicates are, and then copies off the original array into another temporary array while comparing the indices to the indices I have stored in my first temporary array.
public void removeDuplicates()
{
double tempa [] = new double [items.length];
int counter = 0;
for ( int i = 0; i< numItems ; i++)
{
for(int j = i + 1; j < numItems; j++)
{
if(items[i] ==items[j])
{
tempa[counter] = j;
counter++;
}
}
}
double tempb [] = new double [ items.length];
int counter2 = 0;
int j =0;
for(int i = 0; i < numItems; i++)
{
if(i != tempa[j])
{
tempb[counter2] = items[i];
counter2++;
}
else
{
j++;
}
}
items = tempb;
numItems = counter2;
}
and while the logic seems right, my compiler is giving me an arrayindexoutofbounds error at
tempa[counter] = j;
I don't understand how counter could grow to above the value of items.length, where is the logic flaw?
You are making things quite difficult for yourself. Let Java do the heavy lifting for you. For example LinkedHashSet gives you uniqueness and retains insertion order. It will also be more efficient than comparing every value with every other value.
double [] input = {1,2,3,3,4,4};
Set<Double> tmp = new LinkedHashSet<Double>();
for (Double each : input) {
tmp.add(each);
}
double [] output = new double[tmp.size()];
int i = 0;
for (Double each : tmp) {
output[i++] = each;
}
System.out.println(Arrays.toString(output));
Done for int arrays, but easily coud be converted to double.
1) If you do not care about initial array elements order:
private static int[] withoutDuplicates(int[] a) {
Arrays.sort(a);
int hi = a.length - 1;
int[] result = new int[a.length];
int j = 0;
for (int i = 0; i < hi; i++) {
if (a[i] == a[i+1]) {
continue;
}
result[j] = a[i];
j++;
}
result[j++] = a[hi];
return Arrays.copyOf(result, j);
}
2) if you care about initial array elements order:
private static int[] withoutDuplicates2(int[] a) {
HashSet<Integer> keys = new HashSet<Integer>();
int[] result = new int[a.length];
int j = 0;
for (int i = 0 ; i < a.length; i++) {
if (keys.add(a[i])) {
result[j] = a[i];
j++;
}
}
return Arrays.copyOf(result, j);
}
3) If you do not care about initial array elements order:
private static Object[] withoutDuplicates3(int[] a) {
HashSet<Integer> keys = new HashSet<Integer>();
for (int value : a) {
keys.add(value);
}
return keys.toArray();
}
Imagine this was your input data:
Index: 0, 1, 2, 3, 4, 5, 6, 7, 8
Value: 1, 2, 3, 3, 3, 3, 3, 3, 3
Then according to your algorithm, tempa would need to be:
Index: 0, 1, 2, 3, 4, 5, 6, 7, 8, ....Exception!!!
Value: 3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 5, 6, 7, 8, 6, 7, 8, 7, 8, 8
Why do you have this problem? Because the first set of nested for loops does nothing to prevent you from trying to insert duplicates of the duplicate array indices!
What is the best solution?
Use a Set!
Sets guarantee that there are no duplicate entries in them. If you create a new Set and then add all of your array items to it, the Set will prune the duplicates. Then it is just a matter of going back from the Set to an array.
Alternatively, here is a very C-way of doing the same thing:
//duplicates will be a truth table indicating which indices are duplicates.
//initially all values are set to false
boolean duplicates[] = new boolean[items.length];
for ( int i = 0; i< numItems ; i++) {
if (!duplicates[i]) { //if i is not a known duplicate
for(int j = i + 1; j < numItems; j++) {
if(items[i] ==items[j]) {
duplicates[j] = true; //mark j as a known duplicate
}
}
}
}
I leave it to you to figure out how to finish.
import java.util.HashSet;
import sun.security.util.Length;
public class arrayduplication {
public static void main(String[] args) {
int arr[]={1,5,1,2,5,2,10};
TreeSet< Integer>set=new TreeSet<Integer>();
for(int i=0;i<arr.length;i++){
set.add(Integer.valueOf(arr[i]));
}
System.out.println(set);
}
}
You have already used num_items to bound your loop. Use that variable to set your array size for tempa also.
double tempa [] = new double [num_items];
Instead of doing it in array, you can simply use java.util.Set.
Here an example:
public static void main(String[] args)
{
Double[] values = new Double[]{ 1.0, 2.0, 2.0, 2.0, 3.0, 10.0, 10.0 };
Set<Double> singleValues = new HashSet<Double>();
for (Double value : values)
{
singleValues.add(value);
}
System.out.println("singleValues: "+singleValues);
// now convert it into double array
Double[] dValues = singleValues.toArray(new Double[]{});
}
Here's another alternative without the use of sets, only primitive types:
public static double [] removeDuplicates(double arr[]) {
double [] tempa = new double[arr.length];
int uniqueCount = 0;
for (int i=0;i<arr.length;i++) {
boolean unique = true;
for (int j=0;j<uniqueCount && unique;j++) {
if (arr[i] == tempa[j]) {
unique = false;
}
}
if (unique) {
tempa[uniqueCount++] = arr[i];
}
}
return Arrays.copyOf(tempa, uniqueCount);
}
It does require a temporary array of double objects on the way towards getting your actual result.
You can use a set for removing multiples.

Categories

Resources