我想要创建比较两个数组的函数,这样如果它们按特定顺序(可能会移位)具有相同的值,则返回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
。
有什么想法吗?
答案 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::array
和std::vector
一样愉快地使用struct Foo
和int
:
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})
;
}