0

Here is the information I have

63974241
63974241
63974241
68936124
68936124
74513945
74513945
76343943
76343943
76343943
85028969
85028969
91809014
109367944
109367944
109367944

I would like to remove those triplicates but keep singletons and duplicates. Therefore, the expect output should be as below,

68936124
68936124
74513945
74513945
85028969
85028969
91809014

Here are the script I have now :

for (int row = 0; row < row_number; row++) {
    if (array[row].equals(array[row+1]) && array[row+1].equals(array[row+2]) ) {                    
    }
    else if (array[row].equals(array[row+1]) && array[row-1].equals(array[row]) ) {
    }
    else if (array[row].equals(array[row-1]) && array[row-1].equals(array[row-2]) ) {
    }
    else{ 
        System.out.println(array[row+1]);
        }               
}

I will be grateful if any help from here.

user3631848
  • 433
  • 1
  • 6
  • 14

5 Answers5

1

For each element check:

  • two previous element
  • two subsequent elements
  • one previous and one following element

If none of the previous has a duplicate add to your results.

As an example, consider the star as the current element:

 A*, A, A, B, C    Don't add because two following elements are equals
 A, A*, A, B, C    Don't add because previous and next elements are equlas
 A, A, A*, B, C    Don't add because previous two elements are equals
 A, A, A, B*, C    Add because no condition is true
 A, A, A, B, C*    Add because no condition is true           

Here is the same code:

// Assuming rows is ordered so that equals elements are close each other

public List noTriplicates(Object[] rows) {
    List results = new ArrayList();
    for (int i = 0; i < rows.length; i++) {
        boolean add = true;

        // Check for two previous
        if (i >= 2 && rows[i-2].equals(rows[i])) {
           add = false;

        // Check previous and next
        } else if (i >= 1 && i < rows.length - 1
                       && rows[i-1].equals(rows[i]) 
                       && rows[i+1].equals(rows[i])) {
           add = false;

        // Check for two next
        } else if (i < rows.length - 2 && rows[i+2].equals(rows[i])) {
           add = false;
        }
        if (add) {
            results.add(rows[i]);
        }

    }
    // Here results has no triplicates
    return results;
}

Note that is also possible to combine all conditions with or operator, but the code will be less readable.

Davide Lorenzo MARINO
  • 26,420
  • 4
  • 39
  • 56
0

You may want to have 3 nested loops, but time should be O(n log^2 n):

    boolean triplicates;
    int[] array = initArray();

    // track triplicates. If you don't, then time is O(n^3), as you need to start over for every nested loop
    boolean[] triplicatesPositions = new boolean[array.length];
    Arrays.fill(triplicatesPositions, false); // not necessary, default is false
    for (int j = 0; j < array.length; j++) {
        if (!triplicatesPositions[j]) {
            triplicates = false;
            // no need to start from the beginning
            for (int k = j + 1; k < array.length; k++) {
                if (array[k] == array[j]) {
                    // no need to start from the beginning
                    for (int i = k + 1; i < array.length; i++) {
                        if (array[i] == array[k]) {
                            triplicates = true; // got it!
                            // remember for the future these are triplicates
                            triplicatesPositions[k] = true; 
                            triplicatesPositions[i] = true;
                        }
                    }
                }
            }
            // this way, you don't print the triplicates at all. If you want to print the first and second time they appear, then simply remove the if statement and print anyway
            if (!triplicates)
        }
    }

Elements are not required to be ordered. Adapting this.

Community
  • 1
  • 1
Manu
  • 4,019
  • 8
  • 50
  • 94
0

If the array is ordered I'll do like this:

 String lastTriplet="";   
    for (int row = 0; row < row_number; row++) {
     if ((row>=row_number-2) || ( row+2<row_number && !array[row].equals(array[row+2]))){
       if (!lastTriplet.equals(array[row])) System.out.println(array[row]);
    }else{
        lastTriplet=array[row];
        row=row+2;
      }
    }
Marco
  • 47
  • 4
0

If array is ordered, then We can modify the code as below:

String row_data = array[0];
int count = 0;
if(array.length == 1) 
    System.out.println(row_data);
else
    for (int row = 1; row < array.length; row++) {
        if(row_data == array[row]) {
            count++;
        } else {
            if(count < 3) {
                print(row_data, count);
            }
            row_data = array[row];
            count = 1;
        }
        if(row+1 == array.length && count < 3) {
            print(row_data, count);
        }
    }

Below is the print() method:

   void print(String row_Data, int count) {
       for(int i=0; i<count; i++) {
           System.out.println(row_Data);
       }
   }

Output:

68936124
68936124
74513945
74513945
85028969
85028969
91809014
pbajpai
  • 1,303
  • 1
  • 9
  • 24
0

I'm not good with streams, but something like this could work?

Map m = IntStream.of(array).boxed().
        collect(Collectors.groupingBy(n -> n, Collectors.counting()));

array = IntStream.of(array).boxed().filter(n -> {
  long v = (long) m.get(n);
  m.put(n, v > 2 ? 1 : v - 1);
  return v > 0;
}).mapToInt(i -> i).toArray();

Order preserved (if 3 equal numbers are found, it will remove the last).

If you have an array like this:

int[] array = { 1, 1, 1, 2, 3, 2, 3, 2, 3 };

You'll have:

{ 1, 1, 2, 3, 2, 3 }
Alex S. Diaz
  • 2,637
  • 2
  • 23
  • 35