整数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语言代码多次遍历数组即可完成。
答案 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;
}
快如地狱