Finding uniques integers in an array - java

i have an array of integers like this one :
A={1,1,4,4,4,1,1}
i want to count the each number once , for this example the awnser is 2 becuase i want to count 1 once and 4 once
i dont want to use sorting methods
i am unable to find a way to solve it using java.
i did this but it gives me 0
public static void main(String args[]) {
int a[] = { 1,1,4,4,4,4,1,1};
System.out.print(new Test4().uniques(a));
}
public int uniques(int[] a) {
int unique = 0;
int tempcount = 0;
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a.length; j++) {
if (a[i] == a[j]) {
tempcount++;
}
}
if (tempcount <= 2) {
unique=a[i];
}
tempcount = 0;
}
return unique;
}
the purpose of the question is to understand the logic of it but not solving it using ready methods or classes

This one should work. I guess this might be not the most elegant way, but it is pretty straightforward and uses only simple arrays. Method returns number of digits from array, but without counting duplicates - and this I believe is your goal.
public int uniques(int[] a) {
int tempArray[] = new int[a.length];
boolean duplicate = false;
int index = 0;
int digitsAdded = 0;
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < tempArray.length; j++) {
if (a[i] == tempArray[j]) {
duplicate = true;
}
}
if(!duplicate) {
tempArray[index] = a[i];
index++;
digitsAdded++;
}
duplicate = false;
}
//this loop is needed if you have '0' in your input array - when creating temp
//array it is filled with 0s and then any 0 in input is treated as a duplicate
//again - not most elegant solution, maybe I will find better later...
for(int i = 0; i < a.length; i++) {
if(a[i] == 0) {
digitsAdded++;
break;
}
}
return digitsAdded;
}

Okay first of all in your solution you are returning the int unique, that you are setting as the value that is unique a[i]. So it would only return 1 or 4 in your example.
Next, about an actual solution. You need to check if you have already seen that number. What you need to check is that for every number in the array is only appears in front of your position and not before. You can do this using this code below.
public int uniques(int[] a) {
int unique = 1;
boolean seen = false;
for (int i = 1; i < a.length; i++) {
for (int j = 0; j < i; j++) {
if (a[i] == a[j]) {
seen = true;
}
}
if (!seen) {
unique++;
}
seen = false;
}
return unique;
}
In this code you are iterating over the number you have seen and comparing to the number you are checking (a[i]). You know that for it to be unique you cant have seen it before.

I see two possible solutions:
using set
public int unique(int[] a) {
Set<Integer> set = new HashSet<>();
for (int i : a) {
set.add(i);
}
return set.size();
}
using quick sort
public int unique(int[] a) {
Arrays.sort(a);
int cnt = 1;
int example = a[0];
for (int i = 1; i < a.length; i++) {
if (example != a[i]) {
cnt++;
example = a[i];
}
}
return cnt;
}
My performance tests say that second solution is faster ~ 30%.

if restricted to only arrays, consider trying this:
Lets Take a temporary array of the same size of orignal array, where we store each unique letter and suppose a is your orignal array,
int[] tempArray= new int[a.length];
int tempArraycounter = 0;
bool isUnique = true;
for (int i = 0; i < a.length; i++)
{
isUnique = true;
for (int j = 0; j < tempArray.length; j++)
{
if(tempArray[j] == a[i])
isUnique = false;
}
if(isUnique)
{
tempArray[tempArraycounter] = a[i];
tempArraycounter++;
isUnique = false;
}
}
now tempArraycounter will be your answer ;)

Try Following code:
int test[]={1,1,4,4,4,1,1};
Set<Integer> set=new LinkedHashSet<Integer>();
for(int i=0;i<test.length;i++){
set.add(test[i]);
}
System.out.println(set);
Output :
[1, 4]
At the end set would contain unique integers.

Related

Finding the same elements in an array and preventing duplicate counting

Given the following code:
public static int countSames(Object[] a) {
int count = 0;
for (int i = 0; i < a.length; i++) {
for (int k = 0; k < a.length; k++) {
if (a[i].equals(a[k]) && i != k) {
count += 1;
break; //Preventing from counting duplicate times, is there way to replace this?
}
}
}
return count;
}
I would like to know if there is a solution which doesn't use break statement since I've heard its bad practice.
But without the break this method returns 6 instead of wanted 3 for array {'x', 'x', 'x'}.
If you're trying to find the number of unique elements in the array try using this approach as it has only one loop and hence efficient.
private static int findNUmberOfUnique(String[] array) {
Set<String> set=new HashSet<>();
for(int i=0;i<array.length;i++){
if(!set.contains(array[i])){
set.add(array[i]);
}
}
return set.size();
}
Let me know if I did not understand your requirement clearly.
You can always use a flag instead of break:
public static int countSames(Object[] a) {
int count = 0;
for (int i = 0; i < a.length; i++) {
boolean found = false;
for (int k = 0; k < a.length && !found; k++) {
if (a[i].equals(a[k]) && i != k) {
count += 1;
found = true;
}
}
}
return count;
}
You can use a hashmap to find the same elements in an array and preventing duplicate counting.
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
HashSet<Integer>hs=new HashSet<Integer>();
for(int i:nums1)
hs.add(i);
HashSet<Integer>hs1=new HashSet<Integer>();
for(int j:nums2){
if(hs.contains(j)){
hs1.add(j);
}
}
int[] res=new int[hs1.size()];
int j=0;
for(int k:hs1)
res[j++]=k;
return res;
}
}

JAVA - Compare two arrays and create a new array with only the unique values from the first

I have to solve an exercise with the following criteria:
Compare two arrays:
int[] a1 = {1, 3, 7, 8, 2, 7, 9, 11};
int[] a2 = {3, 8, 7, 5, 13, 5, 12};
Create a new array int[] with only unique values from the first array. Result should look like this: int[] result = {1,2,9,11};
NOTE: I am not allowed to use ArrayList or Arrays class to solve this task.
I'm working with the following code, but the logic for the population loop is incorrect because it throws an out of bounds exception.
public static int[] removeDups(int[] a1, int[] a2) {
//count the number of duplicate values found in the first array
int dups = 0;
for (int i = 0; i < a1.length; i++) {
for (int j = 0; j < a2.length; j++) {
if (a1[i] == a2[j]) {
dups++;
}
}
}
//to find the size of the new array subtract the counter from the length of the first array
int size = a1.length - dups;
//create the size of the new array
int[] result = new int[size];
//populate the new array with the unique values
for (int i = 0; i < a1.length; i++) {
int count = 0;
for (int j = 0; j < a2.length; j++) {
if (a1[i] != a2[j]) {
count++;
if (count < 2) {
result[i] = a1[i];
}
}
}
}
return result;
}
I would also love how to solve this with potentially one loop (learning purposes).
I offer following soulution.
Iterate over first array, and find out min and max it's value.
Create temporary array with length max-min+1 (you could use max + 1 as a length, but it could follow overhead when you have values e.g. starting from 100k).
Iterate over first array and mark existed values in temorary array.
Iterate over second array and unmark existed values in temporary array.
Place all marked values from temporary array into result array.
Code:
public static int[] getUnique(int[] one, int[] two) {
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (int i = 0; i < one.length; i++) {
min = one[i] < min ? one[i] : min;
max = one[i] > max ? one[i] : max;
}
int totalUnique = 0;
boolean[] tmp = new boolean[max - min + 1];
for (int i = 0; i < one.length; i++) {
int offs = one[i] - min;
totalUnique += tmp[offs] ? 0 : 1;
tmp[offs] = true;
}
for (int i = 0; i < two.length; i++) {
int offs = two[i] - min;
if (offs < 0 || offs >= tmp.length)
continue;
if (tmp[offs])
totalUnique--;
tmp[offs] = false;
}
int[] res = new int[totalUnique];
for (int i = 0, j = 0; i < tmp.length; i++)
if (tmp[i])
res[j++] = i + min;
return res;
}
For learning purposes, we won't be adding new tools.
Let's follow the same train of thought you had before and just correct the second part:
// populate the new array with the unique values
for (int i = 0; i < a1.length; i++) {
int count = 0;
for (int j = 0; j < a2.length; j++) {
if (a1[i] != a2[j]) {
count++;
if (count < 2) {
result[i] = a1[i];
}
}
}
}
To this:
//populate the new array with the unique values
int position = 0;
for (int i = 0; i < a1.length; i++) {
boolean unique = true;
for (int j = 0; j < a2.length; j++) {
if (a1[i] == a2[j]) {
unique = false;
break;
}
}
if (unique == true) {
result[position] = a1[i];
position++;
}
}
I am assuming the "count" that you implemented was in attempt to prevent false-positive added to your result array (which would go over). When a human determines whether or not an array contains dups, he doesn't do "count", he simply compares the first number with the second array by going down the list and then if he sees a dup (a1[i] == a2[j]), he would say "oh it's not unique" (unique = false) and then stop going through the loop (break). Then he will add the number to the second array (result[i] = a1[i]).
So to combine the two loops as much as possible:
// Create a temp Array to keep the data for the loop
int[] temp = new int[a1.length];
int position = 0;
for (int i = 0; i < a1.length; i++) {
boolean unique = true;
for (int j = 0; j < a2.length; j++) {
if (a1[i] == a2[j]) {
unique = false;
break;
}
}
if (unique == true) {
temp[position] = a1[i];
position++;
}
}
// This part merely copies the temp array of the previous size into the proper sized smaller array
int[] result = new int[position];
for (int k = 0; k < result.length; k++) {
result[k] = temp[k];
}
Making your code work
Your code works fine if you correct the second loop. Look at the modifications I did:
//populate the new array with the unique values
int counter = 0;
for (int i = 0; i < a1.length; i++) {
for (int j = 0; j < a2.length; j++) {
if (a1[i] == a2[j]) {
result[counter] = a1[i];
counter++;
}
}
}
The way I would do it
Now, here is how I would create a method like this without the need to check for the duplicates more than once. Look below:
public static int[] removeDups(int[] a1, int[] a2) {
int[] result = null;
int size = 0;
OUTERMOST: for(int e1: a1) {
for(int e2: a2) {
if(e1 == e2)
continue OUTERMOST;
}
int[] temp = new int[++size];
if(result != null) {
for(int i = 0; i < result.length; i++) {
temp[i] = result[i];
}
}
temp[temp.length - 1] = e1;
result = temp;
}
return result;
}
Instead of creating the result array with a fixed size, it creates a new array with the appropriate size everytime a new duplicate is found. Note that it returns null if a1 is equal a2.
You can make another method to see if an element is contained in a list :
public static boolean contains(int element, int array[]) {
for (int iterator : array) {
if (element == iterator) {
return true;
}
}
return false;
}
Your main method will iterate each element and check if it is contained in the second:
int[] uniqueElements = new int[a1.length];
int index = 0;
for (int it : a1) {
if (!contains(it, a2)) {
uniqueElements[index] = it;
index++;
}
}

How to check if two matrices have an identical row?

I'm trying to develop an algorithm in Java, which, given two matrices (let's say a and b), returns true if at least one row is identical in a and b.
Here's my attempt of method:
public static boolean check_row(int a[][], int b[][]){
boolean check = false;
for(int i = 0; i < a.length; i++){
for(int j = 0; j < b[0].length; j++){
if(a[i][j] == b[i][j])
check = true;
}
}
return check;
}
And here's a simple main:
public static void main(String[] args){
int a[][] = {{1,2}, {3,4}};
int b[][] = {{1,2}, {7,8}};
System.out.println(check_row(a, b));
}
Here I get true because first row of both matrices is the same.
But if I change the matrices initialization to this:
int a[][] = {{1,2}, {3,4}};
int b[][] = {{5,6}, {1,2}};
I get false, even though the first row of a and the second row of b are identical.
How should I modify the method in order to get true in both cases?
Your condition is too simple... High level idea is, that for each row from a and b pick a row and then identify whether it is the same, so you need 3 loops...
code:
public class SameRowFinder {
public static void main(String[] args){
int a[][] = {{1,2},{3,4}};
int b[][] = {{1,2}, {7,8}};
System.out.println(hasSameRow(a, b));
int aa[][] = {{1,2},{3,4}};
int bb[][] = {{5,6}, {1,2}};
System.out.println(hasSameRow(aa, bb));
}
private static boolean hasSameRow(int[][] a, int[][] b) {
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < b.length; j++) {
if (isSameRow(a[i], b[j])) {
System.out.printf("Same rows are %d and %d (0-based).%n", i, j);
return true;
}
}
}
return false;
}
private static boolean isSameRow(int[] row1, int[] row2) {
if (row1.length != row2.length) {
throw new IllegalArgumentException("rows with different length");
}
for (int i = 0; i < row2.length; i++) {
if (row1[i] != row2[i]) {
return false;
}
}
return true;
}
}
Also you do not need to write your own function for array compare, but use Arrays.equal(int[], int[]), but it will just hide 3rd loop. Method above throws runtime exception in case of different length of arrays. It's definitelly worth look at Arrays.equal(int[], int[]) implementation for some tips (check for equality + null checks).
You have an error in your 2nd loop.
Change:
for(int j = 0; j < b[0].length; j++)
to
for(int j = 0; j < b.length; j++){
Further, the issue is that you cannot compare the rows like you do it.
You have to check that the rows have the same length and finally compare the rows. You will need an additional for loop for comparing the rows.
This one will do the trick:
public static boolean check_row(int a[][], int b[][]){
boolean check = false;
for(int i = 0; i < a.length; i++){
for(int j = 0; j < b.length; j++){
if (compareRows(a[i], b[j]))
check = true;
}
}
return check;
}
private static boolean compareRows(int[] row1, int[] row2) {
if (row1.length == row2.length) {
for (int i = 0; i < row2.length; i++) {
if (row1[i] != row2[i]) {
return false;
}
}
return true;
}
return false;
}
public static void main(String[] args){
int a[][] = {{1,2},{3,4}};
int b[][] = {{5,6}, {1,2}};
System.out.println(check_row(a, b));
}
In the example provided by OP, the loop over rows in b matrix was missing.
When learning, the algorithm can be written as follows:
public static boolean check_row(int a[][], int b[][]) {
int row_size = a[0].length;
for (int i = 0; i < a.length; i++) {
b: for (int j = 0; j < b.length; j++) {
for (int k = 0; k < row_size; k++) {
if (a[i][k] != b[j][k])
continue b; // move to next row in 'b' matrix
}
return true; // all elements in row were equal if we reached this point
}
}
return false;
}
In real life it would probably look like this:
public static boolean check_row(int[][] a, int[][] b) {
return Arrays.stream(b)
.anyMatch(rowB -> Arrays.stream(a).anyMatch(rowA -> Arrays.equals(rowA, rowB)));
}
i hope this code can help you
public static boolean check_row(int a[][], int b[][])
{
boolean check = false;
for(int i = 0; i < a.length; i++)
{
for(int k = 0 ; k< b.length ; k++)
{
for(int j = 0 ; j<b[0].length ; j++)
{
if(a[i][j]!=b[k][j])
{
break;
}//if even one cell were not similar in both a and b break
else
{
if(j==b[0].length-1)
{
check = true;
}//if you haven't broken the loop yet and if j went till the end
}//else if they are equal
}//j to go through columns
if(check == true)
{
break;
}//for bringing down the time complexity
}//k to go through b rows
if(check == true)
{
break;
}//for bringing down the time complexity
}//i
return check;
}

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
}
}
}

finding distinct elements of an unsorted string array

i have an array of strings, it is unsorted and it has duplicate elements. i want to count the distinct elements,but when i call my method it returns number of all elements, not just the distinct ones. any idea please?
public static double countDistinctString(String[] array) {
double distinctStrings = 0;
for (int j = 0; j < array.length; j++){
String thisString = array[j];
boolean seenThisStringBefore = false;
for (int i = 0; i < j; i++){
if (thisString == array[i]){
seenThisStringBefore = true;
}
}
if (!seenThisStringBefore){
distinctStrings++;
}
}
return distinctStrings;
}
}
The problem is that you're using == to compare strings; see How do I compare strings in Java? for why this doesn't work. Use if (thisString.equals(array[i])) instead.
This should work (I've also improved it a bit - using int instead of double, using break once found the match):
public static double countDistinctString(String[] array) {
int distinctStrings = 0;
for (int j = 0; j < array.length; j++) {
String currentString = array[j];
boolean seenThisStringBefore = false;
for (int i = 0; i < j; i++){
if (currentString.equals(array[i])) {
seenThisStringBefore = true;
break;
}
}
if (!seenThisStringBefore) {
distinctStrings++;
}
}
return distinctStrings;
}

Categories

Resources