给定两个数组,检查它们是否相似(即具有相同的整数,每个整数的次数相同)。
例如:
int arr1[5] = { 3, 5, 2, 5, 2}
int arr2[5] = { 2, 3, 5, 5, 2}
我不允许使用排序和哈希表。它应该是O(n)并且不应该使用任何额外的空间。
这是一个面试问题。
尝试过如下规则:
但是面试官仍然不高兴。也许我错过了一些角落案件。
答案 0 :(得分:2)
如果元素值是整数并且由n
(1...n
)限定,我可以想到执行此任务的一种方法,其中n
是数组的大小(这适用于你的例子):
在每个数组中,对于每个元素x
,我们执行arr[x%(n+1)-1] += n+1
。我们使用mod,因为元素可能会在整个过程中发生变化,通过使用mod我们得到原始数组中出现的元素。
我们所做的是通过添加v
来计算arr[v]
中值n+1
的出现次数,然后我们可以通过arr[v]%(n+1)
来获取原始值值由n
限制,以及arr[v]/(n+1)
的出现次数。
最后,我们比较了A
和B
中每个值的出现次数,如果对于任何值不同,我们会返回false
。如果所有值的计数相同,我们返回true
。
这是一个需要O(n)
内存的O(1)
时间解决方案。
这是算法:
bool checkIfArraysAreSimilar(int[] A, int[] B)
{
n = A.length; // = B.length
int i;
for (i = 0; i < n; i++)
{
A[(A[i]%(n+1))-1] += n+1;
B[(B[i]%(n+1))-1] += n+1;
}
for (i = 0; i < n; i++)
{
if (A[i] / n+1 != B[i] / n+1)
return false;
}
return true;
}
答案 1 :(得分:1)
在JavaScript中尝试此算法:
var arr11 = [ 3, 5, 2, 5, 2]
var arr22 = [ 2, 3, 5, 5, 2]
console.log(arraySimilar(arr11,arr22));
function arraySimilar(arr1,arr2){
var tempArr = arr2;
// Checking Length if both the arrays are equal
if(arr1.length == arr2.length){
//Running a For Loop for first array
for(i=0; i<arr1.length; i++){
//If the Element is present removing from "tempArr"
if(tempArr.indexOf(arr1[i])!= -1){
tempArr.splice(tempArr.indexOf(arr1[i]),1);
}
else{ return false;}
}
}
else{ return false; }
// Check "tempArr" if it is empty
if(tempArr.length==0){
return true;
}else{
return false;
}
}
答案 2 :(得分:1)
可能他意味着你应该将f与x(x [i])的和除以及f(y [i])的i除以i,其中x和y是数组,f是散列函数。
答案 3 :(得分:0)
第一个数组有两种可能的方式,无论它是否包含非重复元素。让我们说为了简单起见,第一个数组不包含重复的元素,那么这个想法非常简单,跟踪总数,如下面的代码所示
#include <iostream>
int main()
{
int arr1[5] = { 1, 2, 3, 4, 5};
int arr2[5] = { 5, 1, 3, 4, 2};
int total(0);
for (unsigned int i(0); i < 5; ++i)
{
for (unsigned int j(0); j < 5; ++j)
{
if ( arr1[i] == arr2[j] )
{
total += 1;
}
}
}
if ( total == 5 )
std::cout << "Same " << std::endl;
else
std::cout << "not Same " << std::endl;
std::cin.get();
return 0;
}
如果总数小于或大于5,则阵列不相同。现在,在我看来,我们需要提出一个计算正确总数的算法,因此我们需要一个接受数组并检查总数的函数。例如,在您的情况下,总数应为9(3表示1,2表示4,5表示4)。这就是我想到的。我希望这个想法很清楚。这就是我为一般情况所做的事情
#include <iostream>
int getTotal(int arr[], const int size)
{
int *temp = new int[size];
int total(0);
for (int i(0); i < size; ++i)
temp[i] = arr[i];
for (int i(0); i < size; ++i)
{
for (int j(0); j < size; ++j)
{
if ( arr[i] == temp[j] )
total += 1;
}
}
std::cout << total << std::endl;
return total;
}
int main()
{
int arr1[5] = { 3, 5, 2, 5, 2};
int arr2[5] = { 2, 3, 5, 5, 2};
int total = getTotal(arr1, 5);
int track(0);
for (unsigned int i(0); i < 5; ++i)
{
for (unsigned int j(0); j < 5; ++j)
{
if ( arr1[i] == arr2[j] )
{
track += 1;
}
}
}
if ( track == total )
std::cout << "Same " << std::endl;
else
std::cout << "not Same " << std::endl;
std::cin.get();
return 0;
}
使用一个循环的另一种方法。我们的想法是得到一个数组的总数,然后将每个元素除以总数得到新的总数。如果第一个数组的新总数等于第二个数组的新总数,那么它们是相同的。 (注意:我没有为所有情况测试我的代码;但是,我的方法对我来说似乎是明智的。
#include <iostream>
double getTotal(double arr[], const int size)
{
double total1(0), total2(0);
for (int i(0); i < 5; ++i)
{
total1 += arr[i];
}
for (int i(0); i < 5; ++i)
{
total2 += total1/arr[i];
}
std::cout << total2 << std::endl;
return total2;
}
int main()
{
double arr1[5] = { 3, 5, 2, 4, 2};
double arr2[5] = { 2, 3, 5, 5, 2};
double total1 = getTotal(arr1, 5);
double total2 = getTotal(arr2, 5);
if ( total1 == total2 )
std::cout << "Same " << std::endl;
else
std::cout << "not Same " << std::endl;
std::cin.get();
return 0;
}