algo-geeks
algo-geeks

Reputation: 5438

recursive removal of elements in array

Given an array of n elements, remove any adjacent pair of elements which are equal. Repeat this operation until there are no more adjacent pairs to remove; that will be the final array.

For e.g 1 2 2 3 4 should return the array 1 3 4. please note array need not to be sorted.

check this test case also: 1,2,2,3,4,4,3,5 o/p should be 1,5. (2,2) and (4,4) gets removed, then (3,3) which became adjacent after the removal of (4,4)

Upvotes: 1

Views: 2785

Answers (9)

ThomasMcLeod
ThomasMcLeod

Reputation: 7769

Here is the stack based algorithm based upon the edited question.

// pseudo code, not tested
void RemoveDupp(vector<int> & vin, vector<int> & vout)
{
    int i = 0, int j = -1;
    vout.resize(vin.size());

    while (i < vin.size())
    {
        if (j == -1 || vout[j] != vin[i])
            vout[++j] = vin[i++]; //push
        else
            j--, i++;             //pop
    }
    vout.resize(j + 1);
}

Upvotes: 0

Guo
Guo

Reputation: 1

I think we could use a stack to check adjacent duplicated elements. Scan the array. For each new element, if it is equal to the top element in the stack, drop it and pop the top element from the stack. Otherwise, push it into the stack.

Upvotes: 0

dawg
dawg

Reputation: 103874

In Python:

>>> l=[1,2,2,3,4,4,3,5]
>>> [x for x in l if not l.count(x) > 1]
[1, 5]

This removes all integers that occur more than once in the list. This is a correct result for your example but I think that you are really trying to state something different. I think you are saying:

list:=(an unsorted list of integers)
while adjacent_pairs(list) is True:
    remove_adjacent_pairs(list)

Once again, in Python:

#!/usr/bin/env python

def dedupe_adjacent(l):
    for i in xrange(len(l) - 1, 0, -1):
        if l[i] == l[i-1]:
            del l[i-1:i+1]
            return True

    return False

def process_list(l):
    print "input list: ",l
    i=1
    while(dedupe_adjacent(l)):
        print "   loop ",i,":",l
        i+=1

    print "processed list=",l    
    print 

process_list([1,2,2,3,4,4,3,5])
process_list([1,2,2,3,4,4,6,3,5])

Output:

input list:  [1, 2, 2, 3, 4, 4, 3, 5]
   loop  1 : [1, 2, 2, 3, 3, 5]
   loop  2 : [1, 2, 2, 5]
   loop  3 : [1, 5]
processed list= [1, 5]

input list:  [1, 2, 2, 3, 4, 4, 6, 3, 5]
   loop  1 : [1, 2, 2, 3, 6, 3, 5]
   loop  2 : [1, 3, 6, 3, 5]
processed list= [1, 3, 6, 3, 5]

Upvotes: 1

Philip JF
Philip JF

Reputation: 28539

I love Java, but functional solutions should get more time on this site.
In Haskell, doing things the way the question asks:

compress lst = if (length lst == length b) then lst else (compress b) where
    b = helper lst
    helper [] = []
    helper [x] = [x]
    helper (x:y:xs) = if (x == y) then (helper xs) else (x:helper (y:xs))

You can solve this problem in O(n) time, although it is a bit more complicated

compress' lst = reverse (helper [] lst) where
    helper xs [] = xs
    helper [] (x:xs) = helper [x] xs
    helper (a:as) (x:xs)
        | a == x = helper as xs
        | otherwise = helper (x:a:as) xs

Upvotes: 0

oosterwal
oosterwal

Reputation: 1479

The following Python 3 code will remove duplicates from a list (array). It does this by scanning the array from start towards end and compares the target element with the element one larger. If they are the same they are removed. If the element pointer is not pointing at 0, then it is reduced by 1 in order to catch nested pairs. If the two compared elements are different then the pointer is incremented.

I'm sure there's a more pythonic way to remove two adjacent elements from a list, but I'm new to Python and haven't figured that out yet. Also, you'll want to get rid of the print(indx, SampleArray) statement--I left it in there to let you follow the progress in the output listing below.

# Algorithm to remove duplicates in a semi-sorted list

def CompressArray(SampleArray):
    indx=0

    while(indx < len(SampleArray)-1):
        print(indx, SampleArray)
        if(SampleArray[indx]==SampleArray[indx+1]):
            del(SampleArray[indx])
            del(SampleArray[indx])
            if(indx>0):
                indx-=1
        else:
            indx+=1
    return SampleArray

Here are sample runs for:

  • [1, 2, 2, 3, 4]
  • [1, 2, 2, 3, 4, 4, 3, 5]
  • [1, 2, 2, 3, 3, 3, 3, 4, 3, 3, 5, 6, 7, 8, 8]
  • [1, 2, 2, 3, 4, 6, 7, 7, 6, 4, 3, 8, 8, 5, 9, 10, 10, 9, 11]
  • [1, 1, 2, 3, 3, 2, 4, 5, 6, 6, 5, 7, 8, 8, 7, 4, 9]

================================
0 [1, 2, 2, 3, 4]
1 [1, 2, 2, 3, 4]
0 [1, 3, 4]
1 [1, 3, 4]
[1, 3, 4]
================================
0 [1, 2, 2, 3, 4, 4, 3, 5]
1 [1, 2, 2, 3, 4, 4, 3, 5]
0 [1, 3, 4, 4, 3, 5]
1 [1, 3, 4, 4, 3, 5]
2 [1, 3, 4, 4, 3, 5]
1 [1, 3, 3, 5]
0 [1, 5]
[1, 5]
================================
0 [1, 2, 2, 3, 3, 3, 3, 4, 3, 3, 5, 6, 7, 8, 8]
1 [1, 2, 2, 3, 3, 3, 3, 4, 3, 3, 5, 6, 7, 8, 8]
0 [1, 3, 3, 3, 3, 4, 3, 3, 5, 6, 7, 8, 8]
1 [1, 3, 3, 3, 3, 4, 3, 3, 5, 6, 7, 8, 8]
0 [1, 3, 3, 4, 3, 3, 5, 6, 7, 8, 8]
1 [1, 3, 3, 4, 3, 3, 5, 6, 7, 8, 8]
0 [1, 4, 3, 3, 5, 6, 7, 8, 8]
1 [1, 4, 3, 3, 5, 6, 7, 8, 8]
2 [1, 4, 3, 3, 5, 6, 7, 8, 8]
1 [1, 4, 5, 6, 7, 8, 8]
2 [1, 4, 5, 6, 7, 8, 8]
3 [1, 4, 5, 6, 7, 8, 8]
4 [1, 4, 5, 6, 7, 8, 8]
5 [1, 4, 5, 6, 7, 8, 8]
[1, 4, 5, 6, 7]
================================
0 [1, 2, 2, 3, 4, 6, 7, 7, 6, 4, 3, 8, 8, 5, 9, 10, 10, 9, 11]
1 [1, 2, 2, 3, 4, 6, 7, 7, 6, 4, 3, 8, 8, 5, 9, 10, 10, 9, 11]
0 [1, 3, 4, 6, 7, 7, 6, 4, 3, 8, 8, 5, 9, 10, 10, 9, 11]
1 [1, 3, 4, 6, 7, 7, 6, 4, 3, 8, 8, 5, 9, 10, 10, 9, 11]
2 [1, 3, 4, 6, 7, 7, 6, 4, 3, 8, 8, 5, 9, 10, 10, 9, 11]
3 [1, 3, 4, 6, 7, 7, 6, 4, 3, 8, 8, 5, 9, 10, 10, 9, 11]
4 [1, 3, 4, 6, 7, 7, 6, 4, 3, 8, 8, 5, 9, 10, 10, 9, 11]
3 [1, 3, 4, 6, 6, 4, 3, 8, 8, 5, 9, 10, 10, 9, 11]
2 [1, 3, 4, 4, 3, 8, 8, 5, 9, 10, 10, 9, 11]
1 [1, 3, 3, 8, 8, 5, 9, 10, 10, 9, 11]
0 [1, 8, 8, 5, 9, 10, 10, 9, 11]
1 [1, 8, 8, 5, 9, 10, 10, 9, 11]
0 [1, 5, 9, 10, 10, 9, 11]
1 [1, 5, 9, 10, 10, 9, 11]
2 [1, 5, 9, 10, 10, 9, 11]
3 [1, 5, 9, 10, 10, 9, 11]
2 [1, 5, 9, 9, 11]
1 [1, 5, 11]
[1, 5, 11]
================================
0 [1, 1, 2, 3, 3, 2, 4, 5, 6, 6, 5, 7, 8, 8, 7, 4, 9]
0 [2, 3, 3, 2, 4, 5, 6, 6, 5, 7, 8, 8, 7, 4, 9]
1 [2, 3, 3, 2, 4, 5, 6, 6, 5, 7, 8, 8, 7, 4, 9]
0 [2, 2, 4, 5, 6, 6, 5, 7, 8, 8, 7, 4, 9]
0 [4, 5, 6, 6, 5, 7, 8, 8, 7, 4, 9]
1 [4, 5, 6, 6, 5, 7, 8, 8, 7, 4, 9]
2 [4, 5, 6, 6, 5, 7, 8, 8, 7, 4, 9]
1 [4, 5, 5, 7, 8, 8, 7, 4, 9]
0 [4, 7, 8, 8, 7, 4, 9]
1 [4, 7, 8, 8, 7, 4, 9]
2 [4, 7, 8, 8, 7, 4, 9]
1 [4, 7, 7, 4, 9]
0 [4, 4, 9]
[9]
================================

Upvotes: 0

David Weiser
David Weiser

Reputation: 5195

I would:

  1. Sort the array.
  2. From the start of the array, until you are at the last element of the array do:
    1. `count` = count the number of array[i] elements.
    2. remove the first `count` elements of the array if `count` > 1.

Upvotes: 0

Shankar Raju
Shankar Raju

Reputation: 4546

I have a solution to this in Java. You need to use replaceAll method in String class in Java. You can use regular expession to remove such adjacent redundant characters:

public class MyString {
  public static void main(String[] args) {

    String str = "12234435";

    while(!str.replaceAll("(\\w)\\1+", "").equalsIgnoreCase(str))
      str = str.replaceAll("(\\w)\\1+", "");

    System.out.println(str);
  }
}

You can find how to give a regular expression here

Upvotes: 0

MSN
MSN

Reputation: 54614

Any time you remove a pair of elements, you also need to see if you generated another pair that you want to remove.

The algorithm should follow naturally from that observation.

Upvotes: 1

Wayne
Wayne

Reputation: 60414

The following:

function compress(arr) {
    var prev, res = [];
    for (var i in arr) {
        if (i == 0 || (arr[i] != arr[i - 1]))
            res.push(arr[i]);
    }
    return res;
}
compress([1, 2, 2, 3, 3, 3, 3, 4, 3, 3, 5, 6, 7, 8, 8]);

Returns:

[1, 2, 3, 4, 3, 5, 6, 7, 8]

Also (JavaScript 1.6 solution):

[1, 2, 2, 3, 3, 3, 3, 4, 3, 3, 5, 6, 7, 8, 8].filter(function(el, i, arr) {
    return i == 0 || (el != arr[i - 1]);
})

Edit: Removing any item that appears in the array more than once requires a different solution:

function dedup(arr) {
    var res = [], seen = {};
    for (var i in arr)
        seen[arr[i]] = seen[arr[i]] ? ++seen[arr[i]] : 1;
    for (var j in arr) {
        if (seen[arr[j]] == 1)
            res.push(arr[j]);
    }
    return res;
}

The following:

dedup([1, 2, 2, 3, 4, 4, 3, 5]);

Produces:

[1, 5]

Upvotes: 0

Related Questions