在C中的数组中查找不规则可重复的整数模式(不多次遍历数组)

时间:2016-02-15 10:55:32

标签: c arrays

整数2,1,4的模式在5000个元素的数组中不规则地重复,数组中的其余元素为0.但是2总是后跟1,1后面总是4,然后又是2等等......

例如: -

  

0 0 0 0 0 0 0 2 0 0 0 0 0 1 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 4 0 0 0 0 0 2 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 4 0 0 0 0 0 ......等等。

我想检查数组中是否重复了这个2-1-4模式,而不管元素之间的数量是多少。

如果重复这种模式,不管是不规则的,那么我有一个正确的数组。否则我错过了一些元素。

我怎么能这样做?

编辑: - 无需使用简单的C语言代码多次遍历数组即可完成。

5 个答案:

答案 0 :(得分:3)

我会找一个找到第一个不匹配元素的函数;如果没有发现不匹配,则返回输入结束指针。

在C:

int *mismatch(int *arr, size_t len)
{
    int expected = 2;
    int *end = arr + len;
    for (; arr < end; ++arr) {
        if (*arr != 0 && *arr != expected) {
            return arr;
        }

        switch (*arr) {
            case 2: expected = 1; break;
            case 1: expected = 4; break;
            case 4: expected = 2; break;
            default: break;
        }
    }
    return arr;
}

更多的C ++'esque版本不会使用原始指针,而是使用一些迭代器类型,即..它也会使用范围(即结束迭代器)而不是长度:

template <typename Iterator>
Iterator mismatch(Iterator begin, Iterator end)
{
    typename Iterator::value_type expected = 2;
    for (; begin != end; ++begin) {
        if (*begin != 0 && *begin != expected) {
            return begin;
        }

        // dito
    }
}

您还应该考虑如何处理空序列(即长度为零)或全零序列。或者不完整的序列(例如,仅2)。

答案 1 :(得分:2)

从集合(1, 2, 4)中走出累积整数的序列,并跳过所有其他数字。每次累积三个数字时,请检查您是否有(2, 1, 4)个序列。如果这样做,丢弃累积的数字,然后继续;否则,声明序列无效,并停止处理。

到达序列结束时检查您没有累积的数字。如果您这样做,请确保它只是一个数字2或两个数字(2, 1)。否则,序列无效。

这可以通过一个非常简单的程序进行翻译:

bool checkValid(std::vector<int> &data) {
    int acc = 0;
    bool res = false;
    for (auto &n : data) {
        // Skip numbers other than 1, 2, 4
        if (n != 1 && n != 2 && n != 4) {
            continue;
        }
        // Do accumulation in an int
        acc = 10*acc + n;
        // If we reach the target, zero out and continue
        if (acc == 214) {
            acc = 0;
            // Now that we found 2, ... , 1, ..., 4,
            // the sequence may be considered valid,
            // unless we find an error later on.
            res = true;
            continue;
        }
        // Check if the partial accumulation is valid
        if (acc != 2 && acc != 21) {
            return false;
        }
    }
    return res;
}

答案 2 :(得分:2)

您的数据位于vector integers。解决方案可能类似于(C ++ 11):

std::vector<int> data;
//fill your data here
data.erase(std::remove(data.begin(), data.end(), 0), data.end());
auto is_ok=true;
for(auto it=data.begin();it!=data.end();it=std::advance(it,3)){
    if(*it!=2 && *(std::next(it))!=1 && *(std::advance(it,2))!=4){
        is_ok=false;   
        break;
    }
    if(std::next(it)==data.end() || std::advance(it,2)==data.end()){
          //This is a special case that you should do it by yourself depending on the requirement 
          break;
    }
}

答案 3 :(得分:2)

简单的方法是在循环中读取数组的每个元素,并将最后一个有趣的元素(2,1或4)存储在临时变量中。当另一个有趣的元素发生时,你检查这是你想要的那个,你继续,否则,你的数组是坏的。

int isArrayBad(int * array, int arraySize)
{
int temp = 0;
for(int i = 0; i<arraySize; i++)
{
    if(!temp && array[i])
        temp = array[i];
    else if(array[i])
    {
        switch(temp)
        {
        case 2:
            if(array[i] != 1)
                return -1;
            break;
        case 1:
            if(array[i] != 4)
                return -1;
            break;
        case 4:
            if(array[i] != 2)
                return -1;
            break;
        }
        temp = array[i];
    }
}
return 0;
}

答案 4 :(得分:1)

我写了这个,但IMO更好的方法是(1)通过创建一个没有零或不需要的值的新数据来过滤数组,以及(2)一个通过新数组,与(x,y)进行比较,z)作为循环链表。

$ g ++ main.cc -o main&amp;&amp; ./main

// main.cc
#include <stdio.h>

class Checker {
private:
  static int pattern[];
  static int* const lastElem;
  static int ignore;
  int* next;
  int* advance(int*);
public:
  Checker();
  bool isCorrect(int* const, int* const);
};

int Checker::pattern[] = {2, 1, 4};
int* const Checker::lastElem = &pattern[2];
int Checker::ignore = 0;

Checker::Checker() {
  next = &pattern[0];
}

int* Checker::advance(int* cursor) {
  if(cursor != lastElem) {
    return ++cursor;
  }
  return &pattern[0];
}

bool Checker::isCorrect(int* const begin, int* const end) {
  for(int* pArr = begin; pArr != end; ++pArr) {
    if(*pArr == ignore) {
      continue;
    }

    if(*pArr != *next) {
      return false;
    }

    next = advance(next);
  }
  return true;
}

int main(int argc, char** argv) {
  int testArr[] = {0, 0, 0, 2, 0, 1, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 4};
  Checker test;
  bool res = test.isCorrect(testArr, &testArr[sizeof(testArr)/sizeof(testArr[0])]);
  printf("Test: %s\n", res ? "passed" : "failed");
  return 0;
}

快如地狱