0

I have an array let's say with 5 items, if element[i] is less than 3 need to move element[i+1] in place of element[i].

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

    for (int i = 0; i < number; i++)
    {
        if (array[i] > number)
        {
           for (int j = 0; j < i - 1; j++)
           {
               array[j] = array[j + 1];
           }
           number = number - 1;
        }
    }

expected result is array = {2, 3, 1, anyNumber, anyNumber};

Lrrr
  • 4,755
  • 5
  • 41
  • 63
Mike Smith
  • 1
  • 1
  • 2
  • You cannot remove elements from a plain array. – juanchopanza Oct 20 '14 at 17:04
  • smell of garbage collection algorithm... – Haris Oct 20 '14 at 17:04
  • 3
    You cannot remove items from an array. Arrays are fixed in size. Instead, use a container such as `std::vector`. – PaulMcKenzie Oct 20 '14 at 17:05
  • I need to overwrite elements, that are less than 3 – Mike Smith Oct 20 '14 at 17:05
  • @MikeSmith - Overwrite those elements with what value? Using a vector would result in a 2 or 3 line solution, and would fit better wrt to your initial request of "removing items". – PaulMcKenzie Oct 20 '14 at 17:08
  • Question edited. I understand, that vectors would be easy solution. However I need to use arrays. – Mike Smith Oct 20 '14 at 17:14
  • @MikeSmith - But your "resulting array" doesn't work since again, you cannot remove items from an array. You need to edit your question more as to exactly state what a `5` element array will look like after the items are changed. – PaulMcKenzie Oct 20 '14 at 17:16
  • Like the others say, you can't remove elements from an array, but if you insist on working with an array, you can "operate on a range". Use a pair of iterators or set elements that you don't care about to a certain value. –  Oct 20 '14 at 17:17
  • Just an aside, the algorithm you've chosen is slower than optimal, it ends up being N^2 when N is possible. – Mark Ransom Oct 20 '14 at 17:19
  • So after your edit, what exactly is the question? – Mark Ransom Oct 20 '14 at 17:20
  • So as I mentioned I need to put left all array elements that are less than 3. – Mike Smith Oct 20 '14 at 17:23
  • @MikeSmith - Still hard to understand your requirements. Your code shows that you have 2,3, and 1 and left out 4 and 5. So do you want all elements <= 3 on the "left side" of the array, and other elements on the "right side"? – PaulMcKenzie Oct 20 '14 at 17:46

6 Answers6

1

A O(n) working code for the above problem.. But as others pointed out in the comments.. You end up with an array that is using less space then allocated to it..

#include<stdio.h>

int main()
{

        int arr[] = {4, 2, 3, 5, 1};

        int* temp1 = arr;
        int* temp2 = arr;
        int i, n1 = 5, n2 = 5;

        for(i = 0; i < n1; i++)
        {
                if(*temp2 >= 3)
                {
                        *temp1 = *temp2;
                        temp1++;
                        temp2++;
                }
                else
                {
                        n2--; //the number of elements left in the array is denoted by n2
                        temp2++;
                }
        }
}
Haris
  • 12,120
  • 6
  • 43
  • 70
1

Nested loops give you O(n2) complexity, and non-obvious code.

Better use std::remove_if:

int array[5] = {4, 2, 3, 5, 1};
int number = 3;
remove_if( begin( array ), end( array ), [=]( int x ) { return x>number; } );

Disclaimer: code untouched by compiler's hands.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
0

Try this code. You should not decrease number at each step. Also, the second loop should start at i and stop at the end of array:

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

for (int i = 0; i < number; i++)
{
    if (array[i] > number)
    {
       for (int j = i; j < 5; j++)
       {
           array[j] = array[j + 1];
       }
    }
}
Laura Maftei
  • 1,863
  • 1
  • 15
  • 25
0

Here's a more compact and idiomatic (that's how I view it anyway) way to remove items from an array:

#include <iostream>
#include <algorithm>
#include <iterator>

int main()
{
   int array[] = {4, 2, 3, 5, 1};
   int* begin = array;
   int* end = begin + sizeof(array)/sizeof(array[0]);
   int number = 3;

   end = std::remove_if(begin, end, [&number](int v) {return v > number;});
   std::copy(begin, end, std::ostream_iterator<int>(std::cout, " "));
   std::cout << std::endl;

   return 0;
}

Just for comparison, here's a version using std::vector:

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>

int main()
{
   std::vector<int> array = {4, 2, 3, 5, 1};
   int number = 3;

   auto end = std::remove_if(array.begin(), array.end(), [&number](int v) {return v > number;});
   std::copy(array.begin(), end, std::ostream_iterator<int>(std::cout, " "));
   std::cout << std::endl;

   return 0;
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Tips: (1) Instead of the pointer variables and the generally unsafe C idiom for computing size of array, you can use `std::begin` and `std::end`. That would also reduce the code by 50%, since `vector` example then identical. (2) You can use `const` to ensure that values are not changed, and to communicate that to a reader. (3) For the purpose of just using a simple value in a lambda, bind by value (`=` instead of `&`). (4) You can omit `return 0;` at the end of `main`, since it is the default for `main`. (5) Consider range based `for` rather than `copy`: simpler, shorter, more clear. ;-) – Cheers and hth. - Alf Oct 20 '14 at 18:35
  • @Cheersandhth.-Alf, Agree with (1). About (2), not sure what where you suggest the use of`const`. Agree with (3). About (4), no harm either way, I think. About (5), can't use a range based `for` loop. The containers are not shrunk by `remove_if`. It just returns an iterator that serves as the `end` of the container after the items have been removed. – R Sahu Oct 20 '14 at 18:59
  • Oh. Yeah, a conundrum: the range based loop is unable to deal with the most common kind of range, represented by two iterators. Very easy to work around but still decidedly annoying. I just thought of outputting the whole array. Didn't see that you output only the cleaned part. Discussion & code: http://stackoverflow.com/questions/6167598/why-was-pair-range-access-removed-from-c11 – Cheers and hth. - Alf Oct 21 '14 at 00:08
0

As an alternative, if you want to keep your items, but denote what will be at some later time, "removed", the algorithm that can be used is stable_partition:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <functional>

int main()
{
    int vValues[] = {4,2,3,5,1};

    // partition the values on left and right.  The left side will have values
    // <= 3, and on right >3.  The return value is the partition point.
    int *p = std::stable_partition(vValues, vValues + 5, 
                                   std::bind2nd(std::less_equal<int>(), 3));
    // display information 
    std::cout << "Partition is located at vValues[" << std::distance(vValues, p) << "]\n";
    std::copy(vValues, vValues + 5, std::ostream_iterator<int>(std::cout, " "));
}

Output:

Partition is located at vValues[3]
2 3 1 4 5

You will see that 2,3,1 are on the left of partition p, and 4,5 are on the right of the partition p. So the "removed" items start at where p points to. The std::partition ensures the elements are still in their relative order when done.

PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45
0

I created my own example, hope this helps people as a reference:

// Removing an element from the array. Thus, shifting to the left.
void remove(){
    int a[] = {1, 2, 3, 4, 5, 6};
    int size = sizeof(a)/sizeof(int);               // gives the size
    for(int i = 0; i < size; i++){
        cout << "Value: " << a[i] << endl;
    }

    int index = 2;                                  // desired index to be removed

    for(int i = 0; i < size; i++){
        if(i == index){
            for(int j = i; j < size; j++){
                a[j] = a[j+1];
            }
        }
    }

    size--;                                        // decrease the size of the array

    cout << "\nTesting output: " << endl;
    for(int i = 0; i < size; i++){
        cout << "Value: " << a[i] << endl;
    }

}

int main(){
    remove();
    return 0;    
}
Agent 0
  • 361
  • 1
  • 5
  • 17
  • This is a reference for how to implement your own version of the problem, pay attention to the algorithm code in the middle. – Agent 0 Aug 14 '17 at 05:33