复制并取消int数组

时间:2016-07-27 12:39:06

标签: c++ arrays algorithm pointers

我有两个数组,两个都已排序。一个数组填充重复值,另一个数组填充应在第一个数组中取消的值。例如:

int * val = new int[11];
val[0] = 1; val[1] = 1;
val[2] = 2; val[3] = 2; val[4] = 2; val[5] = 2; 
val[6] = 3; 
val[7] = 4; 
val[8] = 5; val[9] = 5; val[10] = 5;

int * invalid = new int[2]; invalid[0] = 2; invalid[1] = 5;

然后输出应该是这样的

int * valid = new int[4];
valid[0] = 1; valid[1] = 1;
valid[2] = 3; 
valid[3] = 4;

如何使用for循环有效地实现此目的?我想指出,我不想切换到vectorlist这样的容器,因为我知道会有朝这个方向发表评论。我明确地希望使用数组。

4 个答案:

答案 0 :(得分:3)

如果两者都被排序,这只是一个简单的O(N + M)算法:从零索引处的两个数组开始,并递增指向较小值的数组。如果增加目标数组,则复制,除非它等于无效数组。

此外,由于您只是删除项目,因此如果您不必保留原始数据,则可以避免使用某些副本:您可以保留计数器丢弃的项目数,并将相同的数组复制到{ {1}}如果currentIdx-discardedCount大于零。

答案 1 :(得分:1)

首先,您应该计算源数组中满足条件的元素数量,然后为元素分配足够的内存。

这是一个示范程序

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

int main() 
{
    const size_t N1 = 11;
    const size_t N2 = 2;
    int * val = new int[N1] { 1, 1, 2, 2, 2, 2, 3, 4, 5, 5, 5 };
    int * invalid = new int[N2] { 2, 5 };
    int *valid = nullptr;

    auto n = std::count_if( val, val + N1, 
                            [=]( int x ) { return !std::binary_search( invalid, invalid + N2, x ); } );

    if ( n )
    {
        valid = new int[n];

        std::copy_if( val, val + N1, valid, 
                      [=]( int x ) { return !std::binary_search( invalid, invalid + N2, x ); } );
    }

    if ( valid ) std::copy( valid, valid + n, std::ostream_iterator<int>( std::cout, " " ) );
    std::cout << std::endl;

    return 0;
}

它的输出是

1 1 3 4 

如果无效数组包含许多元素,您可以使用标准算法std::binary search,或者只需编写lambda表达式,如

[=]( int x ) { return x != invalid[0] && x != invalid[1]; }

例如

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

int main() 
{
    const size_t N1 = 11;
    const size_t N2 = 2;
    int * val = new int[N1] { 1, 1, 2, 2, 2, 2, 3, 4, 5, 5, 5 };
    int * invalid = new int[N2] { 2, 5 };
    int *valid = nullptr;

    auto is_valid_element = [=]( int x ) { return x != invalid[0] && x != invalid[1]; };
    auto n = std::count_if( val, val + N1, is_valid_element );

    if ( n )
    {
        valid = new int[n];

        std::copy_if( val, val + N1, valid, is_valid_element );
    }

    if ( valid ) std::copy( valid, valid + n, std::ostream_iterator<int>( std::cout, " " ) );
    std::cout << std::endl;

    return 0;
}

编译器应支持C ++ 2011。

答案 2 :(得分:0)

#include <iostream>
const int SIZE_1 = 11;
const int SIZE_2 = 2;

/*find out if item should be exclude from result array; this take linear time over the size of the invalids array*/

bool doNotInclude(int item, int invalids[], int size)
{
    bool remove = false;
    for(int i = 0; i < size; i++)
    {
        if(invalids[i] == item)
        {
            remove = true;
        }
    }
    return remove;
}

int main() {

    //array of values
    int * val = new int[SIZE_1] { 1, 5, 2, 2, 2, 2, 3, 4, 1, 5, 5 };

    //values to ignore
    int * invalid = new int[SIZE_2] { 2, 5 };

    //result array
    int *valid = new int[SIZE_1];

    //keep track of result array current index/ size
    int currentIndex = 0;

    /*check if elements of input array are in invalids, if not put them in the result array*/

    for(int i = 0; i < SIZE_1; i++)
    {
        if(!doNotInclude(val[i], invalid, SIZE_2))
        {
            valid[currentIndex] = val[i];
            currentIndex++;
        }
    }

    //print result
    //currentIndex is now the size of the valid array
    for(int n = 0; n < currentIndex; n++)
    {
        std::cout << valid[n] << ' ';
    }

}

这种方法是O(N * M)数组是否排序。

答案 3 :(得分:-3)

从概念上讲,算法就像这个伪代码:

int i, j;

j = 0;
for (i=0; i < length(val); i++) {
  if (val[i] != VALUE_TO_DELETE) {
    val[j++] = val[i];
  }
}
... now discard, or ignore, anything in "val" beyond element #j.

我们只是遍历数组,复制任何我们想要摆脱的值。 i是用于查找值的光标,j表示放置它们的位置。

元素#j 之外的值仍然存在,在物理上,但你忽略它们。

为了完整起见,如果我们正在寻找invalid个数字:

int i, j, k;
boolean delete_me;

j = 0;
for (i=0; i < length(val); i++) {

  // search the "invalid" list to see if the number is in it
  delete_me = false;
  for (k = 0; k < length(invalid); k++) {
    if (val[i] == invalid[k]) {
      delete_me = true;
      break;              // quit the loop as soon as we know ...
    }
  }

  // copy what is NOT in it
  if (!delete_me) {       // notice: "if NOT" ...
    val[j++] = val[i];
  }
}