我希望创建一个函数,比较两个数组,如果它们在某种顺序下具有相同的值(可能会被移动),则返回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
。
有什么想法吗?
Here you are
#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
m < n
就可以进行比较。这是一种蛮力法,但它能够工作。至于解释:我认为JohnKugelman的意思是您应该在问题中添加注释。个人而言,我没有理解代码的问题,但我怀疑OP不会那么容易理解。 - user4668606#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);
}
memcmp
不是每次都要进行彻底搜索。 - BLUEPIXYmemcmp
是做什么的呢?实际上它在内部使用了一种优化过的穷举搜索方法。 - user4668606如果这些数组只是彼此旋转得到的版本,那么它们必须具有相等的长度,并且必须存在至少一个偏移量,使得 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
<algorithm>
中吗?实际上,它们不可能在其中,因为这是 C,而不是 C++。 - Toby Speight你可能对这个问题的C++等效版本感兴趣。看到标准库提供比C程序员可用的更高级别的抽象是很有启发性的。
首先,我们需要一个合理的函数签名。让我们将其设置为模板,这样我们就可以像使用std::vector
和int
一样愉快地使用std::array
和struct Foo
:
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})
;
}
#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;
}
int arr1[] = {1,1,1}; int arr2[] = {3};
或者 int arr1[] = {-1,2,1}; int arr2[] = {1,1,0};
的情况下,你的函数会返回什么。 - Bob__
arr1
和arr2
的内容是否相同,而不考虑顺序吗? - yanoarr1
向右旋转一个位置,然后使用memcmp
与arr2
进行比较,反复执行此操作,直到找到匹配项或旋转arr1
的长度。但我相信肯定有更优化的解决方案。首先,检查arr1
和arr2
是否具有相同的长度。 - yano