Best implementation to remove duplicates JAVA array [duplicate] - java

This question already has answers here:
Java Remove Duplicates from an Array?
(10 answers)
Closed 8 years ago.
Found this solution to make this method:
int[] withoutDuplicates(int[] a){
int n = a.length;
if (n < 2) {
return a;
}
for (int i = 0; i < n-1; i++) {
for (int j = i+1; j < n; j++) {
if (a[j] == a[i]) {
--n;
System.arraycopy(a, j+1, a, j, n-j);
--j;
}//end if
} //end for
}//end for
int[] aa = new int[n];
System.arraycopy(a, 0, aa, 0, n);
return aa;
}//end method
I do not understand why it is using an array of length n. Shouldn't it be of size n minus the number of duplicates erased?
Is this the most optimal way of implementing the method? or is there any java resource I could use?

I am, by nature, lazy. I would do this:
-- EDIT --
private int[] withoutDuplicates(int[] a){
Set<Integer> set = new LinkedHashSet<Integer>();
for (int x : a) {
set.add(x);
}
int[] newArray = new int[set.size()];
int ii = 0;
for (Integer x : set) {
newArray[ii++] = x;
}
return newArray;
}

Here is an algorithm for removing duplicates and maintaining the relative order.
Time: O(n)
Space: O(n)
public static void dupCheck(int [] a){
int j=0;
HashMap<Integer,Boolean> map = new HashMap<Integer,Boolean>();
int [] b = new int [a.length];
for(int i=0;i<a.length;i++){
if(!map.containsKey(a[i])){
map.put(a[i],true);
b[j++]=a[i];
}
}
for(int i=0;i<j;i++)
System.out.print(b[i]+" ");
}

Related

Java beginner here getting non zero numbers

I just want to ask why the temp in my method NonZeros does not change its elements even though I explicitly assign each element of temp whenever the source has a nonzero element. Here's my work.
package nonzeros;
public class NonZeros {
public static void main(String[] args) {
int [] B = {0,1,2,3,2};
int [] newone = NonZeros(B);
for(int q = 0; q < newone.length; q++){
System.out.println(newone[q]);
}
}
public static int[] NonZeros(int [] A){
int [] temp = new int[4];
for(int i = 0; i < A.length;i++){
if(A[i] != 0){
int j = 0;
temp[j] = A[i];
j++;
}
}
return temp;
}
}
Here's the result:
run:
2
0
0
0
However, the result should be: 1 2 3 2
Step one, count the non zero values. Step two, create the new array. Step three, fill it with non-zero values like
public static int[] NonZeros(int[] A) {
int count = 0;
for (int i = 0; i < A.length; i++) {
if (A[i] != 0) {
count++;
}
}
int[] temp = new int[count];
int p = 0;
for (int i = 0; i < A.length; i++) {
if (A[i] != 0) {
temp[p++] = A[i];
}
}
return temp;
}
Alternatively, use a lambda and filter like
public static int[] NonZeros(int[] A) {
return Arrays.stream(A).filter(i -> i != 0).toArray();
}
You declare int j=0; inside the loop, so all assignments go to the same place.
You need to move the j index outside of the loop:
public static int[] NonZeros(int [] A){
int [] temp = new int[4];
int j = 0;
for (int i=0; i < A.length; i++) {
if (A[i] != 0) {
temp[j] = A[i];
j++;
}
}
return temp;
}
The reason why your current output happens to be [2, 0, 0, 0] is that the final element in the input array is 2, and gets written to the first entry in the output array. In fact, currently all values are being written to the first entry of the output array.
The scope of the "j" variable that you are defining is the if block that contains it because you are declaring it inside the condition which results in you overwriting the first element in your temp array each time you find a non-zero number in the source while the rest of your temp elements remain unchanged.
The solution is to move the declaration of "j" to the body of the method just before the loop, that is:
public static int[] NonZeros(int [] A){
int [] temp = new int[4];
int j = 0;
for(int i = 0; i < A.length;i++){
if(A[i] != 0){
temp[j] = A[i];
j++;
}
}
return temp;
}

Find longest subarray whose sum divisible by 3 with O(N) Complexity

i have big question here , if you can see below the code you will see code with O(N) complexity. im only try to decrease it to O(N^2),
Im treid to do it with O(N) but without any secces .
private static int f (int[]a, int low, int high)
{
int res = 0;
for (int i=low; i<=high; i++)
res += a[i];
return res;
}
public static int what (int []a)
{
int temp = 0;
for (int i=0; i<a.length; i++)
{
for (int j=i; j<a.length; j++)
{
int c = f(a, i, j);
if (c%3 == 0)
{
if (j-i+1 > temp)
temp = j-i+1;
}
}
}
return temp;
}
couple of exemple :
int[] a={1,2,4,1}; output : 2 ==> if you can see (1+2= 3 ) ,(2+4=6) so those is %3=0 ==> beacuse that the number is 2 beacuse is two subarray that giving me %3 to be =0.
int[] a={3,4,4,2}; output : 2
int[] a={3,3,3,3,0,1}; output : 5
int[] a={3,2,7,6,6,1}; output : 5

Zipping two arrays in java

I would like to join two arrays but not like the usual way
{1,2,3} {4,5,6}
{1,2,3,4,5,6}
I would like to join them like so
{1,2,3} {4,5,6}
{1,4,2,5,3,6}
any suggestions?
I do not want to concatenate the two arrays but rather zip them
This Program also work for if array size of both is not equals.. Happy to help
public class Assignment{
public static void main(String[] args){
int [] arr1 = new int[]{1,2,3};
int [] arr2 = new int[]{4,5,6,7,8};
int [] arr3 = new int[arr1.length + arr2.length];
int biglength = 0;
if(arr1.length > arr2.length){
biglength = arr1.length;
}else{
biglength = arr2.length;
}
for(int i=0,j=0; i< biglength; i++){
if(i<arr1.length && i<arr2.length){
arr3[j++] = arr1[i];
arr3[j++] = arr2[i];
}else if(i<arr1.length){
arr3[j++] = arr1[i];
}else{
arr3[j++] = arr2[i];
}
}
for(int j= 0 ; j<arr3.length; j++){
System.out.print(arr3[j]);
}
}
}
Here is a technique using Java 8 streams:
int[] mergedArray = IntStream.range(0, Math.min(array1.length, array2.length))
.flatMap(n -> IntStream.of(array1[n], array2[n]))
.toArray();
VerA - on List and Integer, returned Integer[];
VerB - on array and int, returned int[];
Mixes n arrays where the length can be different.
public static Integer[] arraysMixVerA(Integer[]... arrays) {
List<Integer> list = new ArrayList<>();
int max=-1;
for (Integer[] array : arrays) {
max = Math.max(max, array.length);
}
for (int i = 0; i < max*arrays.length; i++) {
list.add(null);
}
for (int i = 0; i < arrays.length; i++) {
for (int j = 0; j < arrays[i].length; j++) {
list.set(j * arrays.length + i, arrays[i][j]);
}
}
for(int i=0;i<list.size();i++){
if(list.get(i)==null)
list.remove(i);
}
return list.toArray(new Integer[list.size()]);
}
public static int[] arraysMixVerB(int[]... arrays) {
int max=-1;
int sumaIndex=0;
for (int[] array : arrays) {
max = Math.max(max, array.length);
sumaIndex=sumaIndex+array.length;
}
Integer[] temp=new Integer[max*arrays.length]; //For an array of
//type int, the default value is 0. For an array of type Integer,
//the default value is null. Thus could not be distinguish zeros with arrays
//that are arguments methods of zeros from the array "temp".
int[] target=new int[sumaIndex];
for (int i = 0; i < arrays.length; i++) {
for (int j = 0; j < arrays[i].length; j++) {
temp[j * arrays.length + i]=arrays[i][j];
}
}
for(int i=0,j=0;i<temp.length;i++){
if(temp[i]!=null){
target[j++]=temp[i];
}
}
return target;
}
O(m) + O(n) is the maximum you can achieve here and accurate answered have already been provided here.
However if array size is extremity higher let's say 10^7 and if you'd want to reduce computation time little more by imposing on your machine cores and comfortable with slight complication in the code you can use concurrency here.
int[] arr1 = new int[10000010];
int[] arr2 = new int[10000000];
int end, endFinal;
int[] output = new int[arr1.length+arr2.length];
if( arr1.length < arr2.length )
end = arr1.length;
else
end = arr2.length;
endFinal = arr1.length + arr2.length;
T obj1 = new T( arr1, output, 0, end );
T obj2 = new T( arr2, output, 1, end );
Thread t1 = new Thread(obj1);
Thread t2 = new Thread(obj2);
t1.start();
t2.start();
t1.join();
t2.join();
for( int j = 2*end; j<endFinal; j++)
{
if(endFinal == arr1.length)
output[j] = arr1[end++];
else
output[j] = arr1[end++];
}
}
class T implements Runnable {
int[] arr, output;
int start, end;
public T ( int[] arr, int[] output, int start, int end)
{
this.arr = arr;
this.output = output;
this.start = start;
this.end = end;
}
public void run (){
int count = 0;
for (int i = start; i< end; i+=2)
output= arr[count++];
}
}
So both the threads will populate m number of elements assuming m is less than n and rest n - m forms will be populated normally. This may seem like a complicated solution and should only be used if necessary. One may not see the difference in smaller arrays.

How do I remove duplicates from two arrays?

I need to have an algorithm that changes values in one array if it is in the second array. The result is that the first array should not have any values that are in the second array.
The arrays are of random length (on average ranging from 0 to 15 integers each), and the content of each array is a list of sorted numbers, ranging from 0 to 90.
public void clearDuplicates(int[] A, int[] B){
for(int i = 0; i < A.length; i++){
for(int j = 0; j < B.length; j++)
if(A[i] == B[j])
A[i]++;
}
}
My current code does not clear all of the duplicates. On top of that it might be possible it will creat an index out of bounds, or the content can get above 90.
Although your question is not very clear, this might do the job. Assumptions:
The number of integers in A and B is smaller than 90.
The array A is not sorted afterwards (use Arrays.sort() if you wish to
fix that).
The array A might contain duplicates within itself afterwards.
public void clearDuplicates(int[] A, int[] B) {
// Initialize a set of numbers which are not in B to all numbers 0--90
final Set<Integer> notInB = new HashSet<>();
for (int i = 0; i <= 90; i++) {
notInB.add(i);
}
// Create a set of numbers which are in B. Since lookups in hash set are
// O(1), this will be much more efficient than manually searching over B
// each time. At the same time, remove elements which are in B from the
// set of elements not in B.
final Set<Integer> bSet = new HashSet<>();
for (final int b : B) {
bSet.add(b);
notInB.remove(b);
}
// Search and remove duplicates
for (int i = 0; i < A.length; i++) {
if (bSet.contains(A[i])) {
// Try to replace the duplicate by a number not in B
if (!notInB.isEmpty()) {
A[i] = notInB.iterator().next();
// Remove the added value from notInB
notInB.remove(A[i]);
}
// If not possible, return - there is no way to remove the
// duplicates with the given constraints
else {
return;
}
}
}
}
You can do it just by using int[ ] although it's a bit cumbersome. The only constraint is that there may not be duplicates within B itself.
public void clearDuplicates(int[] A, int[] B) {
//Number of duplicates
int duplicate = 0;
//First you need to find the number of duplicates
for (int i = 0; i < A.length; i++) {
for (int j = 0; j < B.length; j++)
if (A[i] == B[j])
duplicate++;
}
//New A without duplicates
int[] newA = new int[A.length-duplicate];
//For indexing elements in the new A
int notDuplicate = 0;
//For knowing if it is or isn't a duplicate
boolean check;
//Filling the new A (without duplicates)
for (int i = 0; i < A.length; i++) {
check = true;
for (int j = 0; j < B.length; j++) {
if (A[i] == B[j]) {
check = false;
notDuplicate--;//Adjusting the index
}
}
//Put this element in the new array
if(check)
newA[notDuplicate] = A[i];
notDuplicate++;//Adjusting the index
}
}
public class DuplicateRemove {
public static void main(String[] args) {
int[] A = { 1, 8, 3, 4, 5, 6 };
int[] B = { 1, 4 };
print(clear(A, B));
}
public static int[] clear(int[] A, int[] B) {
int a = 0;
for (int i = 0; i < A.length; i++) {
for (int j = 0; j < B.length; j++) {
if (A[i] == B[j]) {
a++;
for (int k = i; k < A.length - a; k++) {
A[k] = A[k + 1];
}
}
}
}
int[] C = new int[A.length - a];
for (int p = 0; p < C.length; p++)
C[p] = A[p];
return C;
}
public static void print(int[] A) {
for (int i = 0; i < A.length; i++)
System.out.println("Element: " + A[i]);
}
}
Here is an example.. I compiled and its working. For any question just let me know :)
maybe you should try the following code:
public void clear (int[] A, int[] B)
{
for (int i=0; i<A.length;i++)
{
for (int j=0; j<B.length; j++)
if(A[i]==B[j])
{
for (int k=i; k<A.length;k++)
A[k]=A[k+1];
j=B.length-1; //so that the cycle for will not be executed
}
}
}

Recursion - Adding the subset of an array

I'm trying to decide if the sum of subset is a set num or not)...
I've read through most of the questions so far here on stackoverflow and have come up with nothing. I think the issue I'm finding is that I want to add together the elements in the combitorial subsets created. All together this should be done recursively. With the current code I have, I'm getting a stackoverflow error for recursion. (ironic)
So to clarify:
int[] array = {1,2,3,4,5};
the subset would be the size of say 2 and combinations would be
{1,2},{1,3},{1,4},{1,5},{2,3},{2,4},{2,5},{3,4},{3,5},{4,5}
from this data I want to see if the subset say... equals 6, then the answers would be: {1,5} and {2,4} leaving me with true as a answer. In respect to the signature I would like to keep it the same because it corresponds with another method (outside of the issue because it only sends the array, n, and num to the method)
public static boolean subset(int[] array, int n, int num) {
int count = 0;
int sum = 0;
int[] subarray = new int[n];
int[] temp = new int[array.length - 1];
int[] copy = array;
subarray[count] = array[0];
for (int i = 0; i < n; i++) {
subarray[count] = array[i];
count++;
System.arraycopy(array, i, temp, 0, n);
}
for (int j = 0; j < subarray.length; j++) {
sum += subarray[j];
if (sum == num)
return true;
}
subset(copy, n, goal);
return false;
}
Not an answer but a plausible idea for one?
for (int i = 0; i < array.length; i++) {
// New sublist to store values from 0 to i
int[] list = new int[array.length - 1];
for (int j = 0; j < array.length; j++) {
list[j] = array[j+1];
}
// Here you call this recursively with your Parent list from i+1
// index and working list from 0 to i
subsetSum(list, n, goal);
}
int sum = 0;
for (int i = 0; i < array.length; i++) {
sum += array[i];
}
if (sum == goal) {
return true;
}
return false;

Categories

Resources