如何使用std :: find查找唯一编号

时间:2013-07-25 16:46:21

标签: c++ c++builder

嘿,这是今天课堂上提出的一个技巧问题,我想知道是否有办法在数组中找到一个唯一的数字,通常的方法是使用两个for循环并获得与之不匹配的唯一数字所有其他我在C ++中使用std :: vectors作为我的数组,并想知道find是否能找到唯一的数字,因为我不知道数组中唯​​一的数字在哪里。

6 个答案:

答案 0 :(得分:2)

假设我们知道向量至少有三个 元素(因为否则,这个问题没有意义), 只是寻找与第一个不同的元素。如果它 恰好是第二个,当然,我们必须检查第三个 看它是第一个还是第二个是独一无二的, 这意味着一些额外的代码,但粗略地说:

std::vector<int>::const_iterator
findUniqueEntry( std::vector<int>::const_iterator begin,
                 std::vector<int>::const_iterator end )
{
    std::vector<int>::const_iterator result
        = std::find_if(
            next( begin ), end, []( int value) { return value != *begin );
    if ( result == next( begin ) && *result == *next( result ) ) {
        -- result;
    }
    return result;
}

(未经测试,但你明白了。)

答案 1 :(得分:1)

正如其他人所说,排序是一种选择。然后,您的唯一值将在任何一方具有不同的值。

这是使用std :: find在O(n ^ 2)时间内解决它的另一个选项(向量的一次迭代,但每次迭代遍历整个向量,减去一个元素。) - 不需要排序。

vector<int> findUniques(vector<int> values)
{
    vector<int> uniqueValues;

    vector<int>::iterator begin = values.begin();
    vector<int>::iterator end = values.end();
    vector<int>::iterator current;

    for(current = begin ; current != end ; current++)
    {
        int val = *current;
        bool foundBefore = false;
        bool foundAfter = false;
        if (std::find(begin, current, val) != current)
        {
            foundBefore = true;
        }
        else if (std::find(current + 1, end, val) != end)
        {
            foundAfter = true;
        }

        if(!foundBefore && !foundAfter)
            uniqueValues.push_back(val);
    }
    return uniqueValues;
}

基本上这里发生的是,我正在运行::在当前元素之前查找向量中的元素,并在当前元素之后运行:: find元素。由于我的当前元素已经存储在'val'中的值(即,它已经在向量中已经存在),如果我在当前值之前或之后找到它,那么它不是唯一值。

无论有多少唯一值,都应该找到向量中不唯一的所有值。

这是运行它的一些测试代码,并看到:

void printUniques(vector<int> uniques)
{
    vector<int>::iterator it;
    for(it = uniques.begin() ; it < uniques.end() ; it++)
    {
            cout << "Unique value: " << *it << endl;
    }
}

void WaitForKey()
{
    system("pause");
}

int main()
{
    vector<int> values;
    for(int i = 0 ; i < 10 ; i++)
    {
            values.push_back(i);
    }
    /*for(int i = 2 ; i < 10 ; i++)
    {
            values.push_back(i);
    }*/
    printUniques(findUniques(values));
    WaitForKey();
    return -13;
}

作为额外奖励:

这是一个使用地图的版本,不使用std :: find,并且在O(nlogn)时间内完成工作 - n为for循环,log(n)为map :: find(),它使用红黑树。

map<int,bool> mapValues(vector<int> values)
{
    map<int, bool> uniques;
    for(unsigned int i = 0 ; i < values.size() ; i++)
    {
        uniques[values[i]] = (uniques.find(values[i]) == uniques.end());
    }
    return uniques;
}

void printUniques(map<int, bool> uniques)
{
    cout << endl;
    map<int, bool>::iterator it;
    for(it = uniques.begin() ; it != uniques.end() ; it++)
    {
        if(it->second)
            cout << "Unique value: " << it->first << endl;
    }
}

并作出解释。迭代vector<int>中的所有元素。如果当前成员不在地图中,请将其值设置为true。如果地图中 ,请将值设置为false。之后,值true的所有值都是唯一的,而false的所有值都有一个或多个重复值。

答案 2 :(得分:0)

假设您获得了一个数组size>=3,其中包含一个值A的实例,而所有其他值都是B,那么您可以使用一个for循环执行此操作。

int find_odd(int* array, int length) {
  // In the first three elements, we are guaranteed to have 2 common ones.
  int common=array[0];
  if (array[1]!=common && array[2]!=common) 
    // The second and third elements are the common one, and the one we thought was not.
    return common;

  // Now search for the oddball.
  for (int i=0; i<length; i++) 
    if (array[i]!=common) return array[i];
}

修改

  

K如果5个数组中的2个以上不同,那该怎么办? - 超级

啊......这是一个不同的问题。所以你有一个大小为n的数组,它不止一次包含公共元素c,而所有其他元素只包含一次。目标是找到一组非共同(即唯一)元素吗?

然后你需要看看上面的西尔万的答案。我认为他正在回答一个不同的问题,但它会起作用。最后,您将拥有一个充满每个值计数的哈希映射。循环遍历哈希映射,每次看到值1时,您都会知道键是输入数组中的唯一值。

答案 3 :(得分:0)

此示例使用地图计算出现次数。唯一的号码只能看一次:

#include <iostream>
#include <map>
#include <vector>

int main ()
{
  std::map<int,int> mymap;
  std::map<int,int>::iterator mit;

  std::vector<int> v;
  std::vector<int> myunique;

  v.push_back(10);  v.push_back(10);
  v.push_back(20);  v.push_back(30);
  v.push_back(40);  v.push_back(30);

  std::vector<int>::iterator vit;

  // count occurence of all numbers
  for(vit=v.begin();vit!=v.end();++vit)
  {
      int number = *vit;
      mit = mymap.find(number);
      if( mit == mymap.end() )
      {
          // there's no record in map for your number yet
          mymap[number]=1; // we have seen it for the first time
      } else {
          mit->second++; // thiw one will not be unique
      }
  }

  // find the unique ones
  for(mit=mymap.begin();mit!=mymap.end();++mit)
  {
      if( mit->second == 1 ) // this was seen only one time
      {
          myunique.push_back(mit->first);
      }
  }

  // print out unique numbers
  for(vit=myunique.begin();vit!=myunique.end();++vit)
      std::cout << *vit << std::endl;


  return 0;
}

此示例中的唯一数字是20和40.不需要为此算法排序列表。

答案 4 :(得分:0)

如果你有两个以上的值(其中一个必须是唯一的),你可以通过在阵列中第一次迭代并填充一个具有关键字的地图,在时间和空间上在O(n)中完成值,并且值是键的出现次数。

然后你只需遍历地图就可以找到一个值1.这将是一个唯一的数字。

答案 5 :(得分:0)

你的意思是在一个只出现一次的向量中找到一个数字吗?如果简单的解决方案,嵌套循环。我认为std::findstd::find_if在这里非常有用。另一种选择是对矢量进行排序,这样您只需要找到两个不同的连续数字。它看起来有点过分,但它实际上是O(nlogn)而不是O(n ^ 2)作为嵌套循环:

void findUnique(const std::vector<int>& v, std::vector<int> &unique)
{
  if(v.size() <= 1) 
  {
    unique = v;
    return;
  }

  unique.clear();

  vector<int> w = v;
  std::sort(w.begin(), w.end()); 

  if(w[0] != w[1]) unique.push_back(w[0]);
  for(size_t i = 1; i < w.size(); ++i)
    if(w[i-1] != w[i]) unique.push_back(w[i]);

  // unique contains the numbers that are not repeated
}