finding distinct elements of an unsorted string array - java

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

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

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

Use indexOf for 2D array in java

Hello I create a 2D array and i want to find the position from the first 2 in the array. And after to add the index in a new ArrayList. But this code doesn't work. Any idea for the problem?
import java.util.ArrayList;
class Test {
public static void main(String[] args) {
ArrayList<Integer> tableau = new ArrayList<Integer>();
int[][] tab = {
{1,1,1,1,1,1,2,1,1,2,1,1,1,2,1,2,1,1,1,1,1},
{1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1},
};
for (int i = 0; i < tab.length; i++) {
int j = tab[i].indexOf(2);
for (int k = j ; k < tab[i].length; k++) {
if (tab[i][j] == 2){
tableau.add(j);
}
}
}
for (Integer row : tableau) {
System.out.println("row = "+ Arrays.toString(tableau));
}
}
}
As others have mentioned, regular arrays do not have an indexOf method, meaning that you will get an error when you compile.
However, you can easily create your own method to use as a substitute.
private static int indexOf(int value, int[] array)
{
for (int i=0; i<array.length; i++)
{
if (array[i] == value)
return i;
}
return -1;
}
Then you can just replace this line:
int j = tab[i].indexOf(2);
With this one:
int j = indexOf(2, tab[i]);

Least Common Subsequence with optimized space (two columns, since it's Markovian)

I'm trying to write LCS of two String objects using bottom-up dynamic programming. I'm able to get it to work properly with O(mn) space. However, as I could see, I don't need all the previous columns. So, I tried to modify it to get it fit in 2 columns so space become O(m). However, it's not working for all inputs (for example, to this: abcabc and abcbcca). What am I missing here? NOT HW, NOT CONTEST nothing. Practicing DP.
public int longestCommonSubsequence(String input) {
char[] firstStr = this.string.toCharArray();
char[] secondStr = input.toCharArray();
int[][] maxLength = new int[firstStr.length+1][2];
for(int i=0; i <= firstStr.length; i++) {
maxLength[i][0] = 0;
}
for(int j=0; j < 2; j++) {
maxLength[0][j] = 0;
}
for(int i=0; i < firstStr.length; i++) {
for(int j=0; j < secondStr.length; j++) {
if(firstStr[i] == secondStr[j]) {
maxLength[i+1][1] = 1 + maxLength[i][0];
}
else {
maxLength[i+1][1] = maxLength[i][1]>maxLength[i+1][0]?maxLength[i][1]:maxLength[i+1][0];
}
}
//Copy second row to first row
for(int l =0; l < firstStr.length; l++) {
maxLength[l][0] = maxLength[l][1];
}
}
return maxLength[firstStr.length -1][0];
}
This has two problems:
if(firstStr[i] == secondStr[j]) {
maxLength[i+1][1] = 1 + maxLength[i][0];
// check here if maxLength[i+1][1] is greather than the last max length
}
else {
maxLength[i+1][1] = maxLength[i][1]>maxLength[i+1][0]?maxLength[i][1]:maxLength[i+1][0];
// absolutely wrong: maxLength[i+1][1] = 0;
}
Here can see the algorithm with micro optimization.
public static int lcs(String s0, String s1) {
int maxLength = 0;
int [][]lengths = new int[2][s1.length()+1];
for (int i = 0; i < s0.length(); i++) {
for (int j = 0; j < s1.length(); j++) {
if (s0.charAt(i) == s1.charAt(j)) {
lengths[0][j+1] = lengths[1][j] + 1;
if (lengths[0][j+1] > maxLength) {
maxLength = lengths[0][j+1];
}
} else {
lengths[0][j+1] = 0;
}
}
int []temp = lengths[0];
lengths[0] = lengths[1];
lengths[1] = temp;
}
return maxLength;
}

Finding uniques integers in an array

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.

Categories

Resources