查找数组重复单位的最简单方法是什么?

时间:2016-05-10 02:58:46

标签: c++ arrays algorithm language-agnostic

例如,重复单位

1,1,1,1,1

是1,

重复单位

1,3,2,1,3,2,1,3,2

是1,3,2

重复单位

1,3,2,1,3,9,1,3,2

是1,3,2,1,3,9,1,3,2

我尝试这样的想法:

1.重复单元测试的数量从1开始,直到数组的大小

2.只能尝试数字大小的倍数,例如:n

3.检查n是否是重复单位的大小,例如:假设测试重复单位是3,然后检查是否

a[0]==a[3*1],a[1]==a[1+3*1],a[2]==a[2+3*1]
a[0]==a[3*2],a[1]==a[1+3*2],a[2]==a[2+3*2]
a[0]==a[3*r],a[1]==a[1+3*r],a[2]==a[2+3*r]
  1. 如果当前测试编号是重复单位,则中断,并且i的当前值是重复单位的大小
  2. 我尝试将其转换为代码:

    #include <stdio.h>
    int main(){
        int a[]={1,3,2,1,3,2,1,3,2};
        int i;
        //1.try number of repeat unit test from 1,until the size of array
        for(i=1;i<=sizeof(a)/sizeof(int);i++){
            //2.only try number which is multiple of the size of array,e.g.: n
            int n=sizeof(a)/sizeof(int);
            if(n%i==0){
                //3.check if n is the size of repeat unit
                bool isRepeat=true;
                for(int j=0;j<n;j++){
                    for(int r=1;r<i;r++){
                        if(a[j]!=a[j+r*n]){
                            isRepeat=false;
                            break;
                        }
                    }
                }
                //4.if the current testing number is repeat unit, break, and the current value of i is the size of repeat unit
                if(isRepeat){
                    break;
                }
            }
        }
    
        //print the result using repeat unit n
        for(int n=0;n<i;n++){
            printf("%d ",a[n]);
        }
    };
    

    但它显示1,3,2,1,3,2,1,3,2的重复单位是1而不是1,3,2。我认为这个解决方案太复杂了,因为它有太多的循环。是否有更简单的方法或算法来找到数组的重复单元?

3 个答案:

答案 0 :(得分:0)

好像你有if(a[j]!=a[j+r*n])

中的错误

为什么要按n添加?不应该是:if(a[j]!=a[j+r*i])

此外,算法有点慢,另一种解决方法是将每个数字视为字符串中的不同字符,并使用Knuth Morris-Pratt(KMP)算法。 (https://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm

将尽快为答案添加更多信息。

更新:

免责声明:语法和变量可能不完整

KMP实施:

int F[MAX_N];
int main(void){
    int P[MAX_N], T[MAX_N];
    //1. get input, put it into P array, not coded.
    //....
    //2. insert content of P array to T twice.
    int ptr = 0;
    for(int i = 0;i<2;i++)
        for(int j = 0;j<length_of_p;j++){
            T[ptr++] = P[j];
        }
    //3. get length of repeated unit.
    int repeated = kmp(P, T, 1);
    //4. print the numbers of repeated unit. i.e. done
    cout<<"REPEATED UNIT: ";
    for(int i = 0;i<repeated;i++)
        cout<< P[i] << " ";
    cout<<endl;

    return 0;
}
void kmp_init(int P[]) {
    F[0] = 0;  F[1] = 0;  
    int i = 1, j = 0;
    while(i<P.size()) {
        if (P[i] == P[j])
            F[++i] = ++j;
        else if (j == 0)
            F[++i] = 0;
        else
            j = F[j];
    }
}

int kmp(int P[], int T[], int start) {
    kmp_init(P);
    int i = start, j = 0;
    int n = T.size(), m = P.size();

    while(i-j <= n-m) {
        while(j < m) {
            if (P[j] == T[i]) {
                i++; j++;
            } else break;
        }
        if (j == m) return i-m;
        else if (j == 0) i++;
        j = F[j];
    }
}

答案 1 :(得分:0)

这里的错误是你首先检查我是1的情况,当然这将被检测为你的重复单位。 这是因为行

for(int r=1;r<i;r++)
如果i=1(您的第一个案例),

会立即中断。

如果你确定你的数字在0到9之间(即只有一位数)并且你想要一个“简单”的解决方案(正如你在标题中所说的那样),你可以使用数字构建一个字符串,将字符串拆分为子串并检查它们是否彼此相等。

#include <stdio.h>
#include <string.h>

int main(){
    int nums[]={1,3,2,1,3,2,1,3,2};
    char initial_string[255];
    char string_list[255][255];
    int i, j, k, l;
    int found = 0;

    memset(initial_string, 0, 255);
    for(i=0; i < sizeof(nums)/sizeof(int); i++) {
        initial_string[i] = '0' + nums[i];
    }

    int n = sizeof(nums)/sizeof(int);
    memset(string_list, 0, 255*255);

    for(i = 1; i <= n; i++) {
        if (n%i == 0) {
            int count = (int)n/i;
            for (k = 0, j = 0; k < n; k+=i, j++) {
                strncpy(string_list[j], &initial_string[k], i);
            }
            found = 1;
            for (k = 0; k < count; k++) {
                if (strcmp(string_list[0], string_list[k])) {
                    // Different strings!
                    found = 0;
                    break;
                }
            }
        }
        if (found) {
            break;
        }
    }

    printf("Repeat unit: %d\n", i);
}

请注意,此代码 NOT 最优,有几点需要改进,请将其作为一般概念。

答案 2 :(得分:0)

您可以在此处使用STL设置功能。像那样,

int main()
{
set< int > s;
  s.insert(1);
  s.insert(3);
  s.insert(2);
  s.insert(1);
  s.insert(3);
  s.insert(2);
  s.insert(1);
  s.insert(3);
  s.insert(2);

   set< int > :: iterator it;
   for(it = s.begin(); it != s.end(); it++) {
    cout << *it << endl;
}

它将打印不同的元素,因此您将找到任何数组的重复单元。 快乐的编码!