如何在一堆数字中找到一个不同的值

时间:2012-09-07 01:09:55

标签: c++ algorithm

这是一个大数据,包含1亿个整数,但其中有一个不同的值与其他相同的整数,例如:1,1,1,1,1,1,1,42,1,1 ,1,1 ..但是,我不知道下面的代码发生了什么。

int main() {

    vector <int> data;
    cout << "Enter same numbers " << " and a different one( negative to be end) :" << endl;
    int value;
    while (cin >> value && value > 0) {
        data.push_back(value);
    }
    int unique_value;
    int size = data.size();
    if (data[0] != data[size - 1]) {
        if (data[0] != data[2]) {
            unique_value = data[0];
        } else {
            unique_value = data[size - 1];
        }
        cout << "found the unique number: " << unique_value << endl;
        exit(0);
    }
    int low = 1;
    int high = size - 2;
    while (high > low) {
        if (data[high] != data[low]) {
            //其中必有一个是不同的,只要和data[0]就能得到结果
            if (data[high] != data[0]) {
                unique_value = data[high];
            } else {
                unique_value = data[low];
            }
            break;
        }
    }
    if (high == low) {
        unique_value = data[high];
    }
    cout << "found the unique number: " << unique_value << endl;
    return 0;
}

4 个答案:

答案 0 :(得分:9)

排序前三个元素,然后取中间元素。这是你的非唯一号码。浏览列表,查找与其不同的数字:

int data[] = {7,7,7,7,7,7,42,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
size_t N = sizeof(data)/sizeof(data[0]);
sort(data, data+3);
int non_unique = data[1];
for (int i = 0 ; i != N ; i++) {
    if (data[i] != non_unique) {
        cout << data[i] << endl;
        break;
    }
}

Link to ideone.

答案 1 :(得分:0)

假设只允许输入两个可能的数字(“与其他整数有一个不同的值”),则不需要将它们全部存储起来。在这种情况下,您会输入1,1,1,1,1,1,1,42,1,1,1,1

如果是这种情况,您可以使用类似(伪代码)的内容:

firstNum = 0; firstCount = 0
secondNum = 0; secondCount = 0
while true:
    num = getNumber()
    if num < 0:
        break while

    if firstCount == 0:                  # first unique number
        firstNum = num
        firstCount = 1
        next while

    if num == firstNum:                  # copy of first
        firstCount++
        next while

    if secondCount == 0:                 # second unique number
        secondNum = num
        secondCount = 1
        next while

    if num <> secondNum:                 # third unique number (disallowed)
        print "Only two numbers allowed"
        stop run

    secondNum++                          # was the second unique number

if secondNum == 0:                       # there was < 2 unique numbers
    print "Not enough different numbers"
    stop run

if firstCount > 1 and secondCount > 1:   # there were no unique numbers
    print "No one unique number"
    stop run

if firstCount == 1:                      # Choose number with count of 1
    print "Unique number is " firstNum
else
    print "Unique number is " secondNum

如果相反,可能有许多不同的数字,您需要一个解决方案,检查每个数字与其他所有数字。

这可以通过多种方式完成(可能还有其他方式,这些只是前面提到的几个方面):

  • 慢速O(n ^ 2)检查每个号码与其他(后续)号码的对比。
  • 稍快一点的排序(可能是O(log N),然后通过排序列表检查相邻的数字。
  • 如果输入范围有限,您可以为每个可能的数字使用计数数组,并查找最终计数为1的数字(确保没有其他人也这样做)。

根据您的问题文本,我不认为是这种情况,但我认为我也会更好地涵盖这一方面。

答案 2 :(得分:0)

首先是您的代码出了什么问题。你有一个while循环由两个变量highlow控制,这些变量在循环中没有更新,因此它将永远旋转。

对于算法,您不需要存储数字来找到不同的数字,而是您可以读取前两个数字,如果它们不同则读取第三个数字并且您有答案。如果它们是相同的,请保留其中一个并继续读取数字,直到找到不同的数字:

// omitting checks for i/o errors, empty list and single number list:
// and assuming that there is one that is different
int main() {
   int first;
   int current;
   std::cin >> first >> current; 
   if (first != current) {
      int third;
      std::cin >> third;
      if (first==third) {
         std::cout << current << "\n";
      } else {
         std::cout << first << "\n";
      }
      return 0;
   }
   while (std::cin >> current && current == first) ;
   std::cout << current << "\n";
}

在该草图的基础上,您将需要处理输入错误,以及不由该通用算法管理的边角情况(空列表,1个元素列表,2个元素列表)。

答案 3 :(得分:0)

每个人都告诉过你他们会怎么做,但没有回答你的问题:你的代码出了什么问题?

问题是您的代码永远不会终止,因为您永远不会更改循环中的highlow值。您正在从数组的两端工作,并将两个值与数组中的第一个元素进行比较。现在,这使你的第一个if-block冗余,实际上有点奇怪,因为它检查第三个数组元素(没有任何边界检查)。

所以......把这部分拿出来:

//if (data[0] != data[size - 1]) {
//    if (data[0] != data[2]) {
//        unique_value = data[0];
//    } else {
//        unique_value = data[size - 1];
//    }
//    cout << "found the unique number: " << unique_value << endl;
//    exit(0);
//}

修复循环:

int low = 1;
int high = size - 1;
while (high >= low) {
    if( data[high] != data[0] )
    {
        if (data[low] == data[high]) {
            unique_value = data[high];
        } else {
            unique_value = data[0];
        }
        break;
    }
    else if( data[low] != data[0] )
    {
        unique_value = data[low];
        break;
    }
    low++;
    high--;
}

// Take out the part that compares high==low.  It was wrong, and has been made
// redundant by looping while high >= low (instead of high > low).

那应该有用。但这很奇怪。

现在,请注意,由于缓存局部性,以这种方式搜索数组是一个坏主意。出于优化原因,您希望将搜索约束到内存的相同部分,对于此算法,没有理由不应该只检查数组中的三个相邻值。

事实上,您只需要检查前三个,在此之后您将确定非唯一值,或两者。如果前三个元素都是相同的,你只需对数组的其余部分进行线性搜索,直到找到不同的值......已经指出你甚至不必将值读入数组中。你可以动态地做到这一点。

size_t size = data.size();

if( size < 3 ) {
    cerr << "Not enough data\n";
    exit(0);
}

int unique_val = 0;

if( data[1] == data[0] && data[2] == data[0] ) {
    int common_val = data[0];
    for( int i = 3; i < size; i ++ ) {
        if( data[i] == common_val ) continue;
        unique_val = data[i];
        break;
    } 
}
else if( data[1] != data[0] ) {
    if( data[2] == data[1] )
       unique_val = data[0];
    else
       unique_val = data[1];
}
else {
    unique_val = data[2];
}

if( unique_val == 0 ) {
    cout << "No unique value found\n";
} else {
    cout << "Unique value is " << unique_val << "\n";
}