将数组整数值与移位值进行比较

时间:2016-12-07 19:28:01

标签: c arrays algorithm

我想要创建比较两个数组的函数,这样如果它们按特定顺序(可能会移位)具有相同的值,则返回true

例如

int arr1[] = {1,2,3,4,5}
int arr2[] = {3,4,5,1,2}

相同,或true

,而

int arr1[] = {1,2,3,4,5}
int arr2[] = {3,4,5,2,1}

不一样,所以false

有什么想法吗?

5 个答案:

答案 0 :(得分:2)

你在这里

#include <stdio.h>

int is_equivalent(const int a[], const int b[], size_t n)
{
    int success = 0;

    for ( size_t m = 0; !success && m < n;  )
    {
        // Try to find in the array a the first element of the array b
        // If there is no such an element then the arrays are different.
        // Otherwise compare elements of the arrays starting from the
        // found element in a and the first element in b
        while (m < n && a[m] != b[0]) ++m;

        if (m != n)
        {
            size_t i = 1;
            size_t j = ++m % n;

            while (i < n && b[i] == a[j])
            {
                ++i; ++j;
                j %= n;
            }

            success = i == n;
        }
    }

    return success;
}

int main( void )
{
    {
        int a[] = { 1, 2, 3, 4, 5 };
        int b[] = { 3, 4, 5, 1, 2 };

        printf("The arrays are equivalent: %d\n",
            is_equivalent(a, b, sizeof(a) / sizeof(*a)));
    }

    {
        int a[] = { 1, 2, 3, 4, 5 };
        int b[] = { 3, 4, 5, 2, 1 };

        printf("The arrays are equivalent: %d\n",
            is_equivalent(a, b, sizeof(a) / sizeof(*a)));
    }

    return 0;
}

程序输出

The arrays are equivalent: 1
The arrays are equivalent: 0

答案 1 :(得分:1)

试试这个

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

bool check(size_t size, int arr1[], int arr2[]){
    int *temp = malloc(size * 2 * sizeof *temp);
    memcpy(temp, arr1, size * sizeof *temp);
    memcpy(temp+size, arr1, size * sizeof *temp);//[1,2,3] --> [1,2,3,1,2,3]

    size_t i;
    for(i = 0; i < size; ++i)
        if(memcmp(temp+i, arr2, size * sizeof *temp) == 0)
            break;
    free(temp);
    return i != size;
}    

#define TEST(size, a1, a2) puts(check(size, a1, a2) ? "same" : "not same")

int main(void) {
    int arr1[] = {1,2,3,4,5};
    int arr2[] = {3,4,5,1,2};
    int arr3[] = {3,4,5,2,1};
    int arr4[] = {1, 0, 1, 1, 0};
    int arr5[] = {1, 0, 1, 0, 1};
    size_t size = sizeof(arr1)/sizeof(*arr1);

    TEST(size, arr1, arr2);
    TEST(size, arr1, arr3);
    TEST(size, arr4, arr5);
}

答案 2 :(得分:0)

好吧,如果数组只是彼此的旋转版本,它们必须具有相同的长度,并且必须至少存在一个偏移量,例如rotate(arr1, offset) == arr2

因此,我们知道concat(arr2, arr2)必须等同于rotate(concat(arr1, arr1), offset),因此必须包含arr1,而不能在位置offset处进行轮换。

我们遇到了经典的子串匹配问题。对于这个问题,解决前者的算法不是因为它们是等价的,所以没有比这更好的解决方案。

解决这个问题的一个非常简单的方法是消除可能的偏移:

//generate a list of offsets from the first element in arr1
list offsets = indicesOf(arr1[0], arr2)

int i = 0
while !offsets.empty && i < length(arr1):
    //generate the rotational offsets of the next char
    list nextoffsets = indicesOf(arr1[i], arr2)
    //make offsets the list of offsets that are valid for all elements up to arr1[i]
    offsets = intersection(offsets, nextoffsets)

    i++

return !offsets.empty

答案 3 :(得分:0)

#include <stdio.h>

int isArraySame(int arr1[], int arr2[], int len1, int len2){
    int var1=0;
    int var2=0;
    int index=0;

    for (index=0;index<len1;index++){
        var1+=arr1[index];
    }

    for (index=0;index<len2;index++){
        var2+=arr2[index];
    }

    if (var1==var2) return 1;
    return 0;
}

int main(){
    int arr1[] = {1,2,3,4,5};
    int arr2[] = {3,4,5,1,2};
    if (isArraySame(arr1, arr2, 5, 5)) {
        printf("true");
    } else {
        printf("false");
    }
    return 0;
}

答案 4 :(得分:0)

您可能对此C ++等效内容感兴趣。看看标准库如何提供比C程序员更高级别的抽象是有益的。

首先,我们需要一个合理的签名功能。让它成为一个模板,因此我们可以像std::arraystd::vector一样愉快地使用struct Fooint

template<typename T>
bool equals_rotated(const std::vector<T>& a, const std::vector<T>& b);

一些简单的测试:

int main()
{
    const auto e = equals_rotated<int>;
    return !e({}, {})
        +   e({1, 2, 3, 4} , {1, 2, 3})
        +  !e({1, 2, 3}    , {1, 2, 3})
        +   e({1, 2, 3, 4} , {1, 2, 4, 3})
        +  !e({1, 2, 3, 4} , {4, 1, 2, 3})
        ;
}

实施很简单。我们知道,如果数组的长度不同,那么它们就不相同;相反,如果它们是相同的,它们必须是等价的。所以,让我们在这些情况下尽早回归:

if (a.size() != b.size())
    return false;
if (a == b)
    return true;

对于一般情况,我们可以对a和它自己进行连接,然后测试它是否包含b作为子序列。这将对内存需求产生影响,但它实现了一个简单的实现:

auto v = a;
v.reserve(2*a.size());
std::copy(a.begin(), a.end(), std::back_inserter(v));
return std::search(v.begin(), v.end(), b.begin(), b.end()) != v.end();

如果我们把它们放在一起,包括必要的标题,并添加一个包装器,以便我们可以从C调用它,我们得到:

#include <algorithm>
#include <iterator>
#include <vector>

template<typename IterA, typename IterB>
bool equals_rotated(IterA a_begin, IterA a_end, IterB b_begin, IterB b_end)
{
    // trivial tests
    if (a_end - a_begin != b_end - b_begin)
        return false;
    if (std::equal(a_begin, a_end, b_begin, b_end))
        return true;
    // Otherwise, make a copy of a+a
    std::vector<typename std::iterator_traits<IterA>::value_type> v;
    v.reserve(2 * (a_end - a_begin));
    const auto ins = std::back_inserter(v);
    std::copy(a_begin, a_end, ins);
    std::copy(a_begin, a_end, ins);
    // and test whether it contains b
    return std::search(v.begin(), v.end(), b_begin, b_end) != v.end();
}

template<typename T>
bool equals_rotated(const std::vector<T>& a, const std::vector<T>& b)
{
    return equals_rotated(a.begin(), a.end(), b.begin(), b.end());
}

extern "C" {
    bool is_rotated_array(int *a, size_t a_len, int *b, size_t b_len)
    {
        return equals_rotated(a, a+a_len, b, b+b_len);
    }
}

int main()
{
    const auto e = equals_rotated<int>;
    return !e({}, {})
        +   e({1, 2, 3, 4} , {1, 2, 3})
        +  !e({1, 2, 3}    , {1, 2, 3})
        +   e({1, 2, 3, 4} , {1, 2, 4, 3})
        +  !e({1, 2, 3, 4} , {4, 1, 2, 3})
        ;
}