例如,
int num[] = {1, 5, 3, 12, 5, 1, 4};
int len = 7;
int count = 0;
(假设阵列中不超过2个相同的元素)
然后我会做
for(int i=0; i<len-1; i++) {
for(int j=i+1; j<len; j++) {
if(num[i] == num[j]) {
count++;
}
}
}
然后计数为2。
但是这种算法导致O(N ^ 2)的效率
有没有更有效的方法?
提前谢谢!
答案 0 :(得分:5)
比O(n log n)
排序更快,请使用hash table。它的结构是线性的或O(n)
;每次插入时,当您遍历输入数组时,如果哈希表中已存在该键,则可以测试(具有常量O(1)
成本) - 即,“对”。当您找到此“匹配”案例时,您会增加一个计数器。一旦你完成了阵列,你的计数器会告诉你答案。
答案 1 :(得分:0)
你可以这样试试:
#define MAX 99999 // consider your array have largest elemnt < 99999 and >=0
int main () {
int num[] = {1, 5, 3, 12, 5, 1, 4,3};
int len = 8;
int count[MAX+1u] = {0};
int i,pair=0;
for( i=0;i<len;i++){
count[num[i]]++; // here count the frequecy of each number
}
for(i=0;i<MAX;i++){
if(count[i]>1){ // if frequecy is > 1
printf("%d occurs %d times \n",i,count[i]);
pair++; // increment pair
}
}
printf("%d pairs ",pair); // print pair
return 0;
}
答案 2 :(得分:0)
基本上,核心思想保持不变:你必须计算输入数组中每个元素的出现次数。
关键问题是如何实施这一计数过程。您的解决方案完全有效,但正如您所感觉到的那样,它可以得到改进。 您收到一条评论建议对数组进行排序,然后对其执行扫描以计算对数:O(n.ln n)。
您也可以使用哈希表,如@AlexReynolds回答所示。但是你必须处理冲突,因为不同的整数可以散列到同一个密钥。为此,您可以为每个密钥使用一个存储桶。这个桶将存储散列到其键的每个整数,加上所述整数的出现次数。
如何实现这些存储桶:
构建哈希表后,如果数组中出现每个元素,则必须对这些对进行计数。但是,您可以在填充数据结构时保留计数器 以避免执行此额外扫描。这很简单。以下是使用从数组中取出的元素 e 来更新表的基本操作:
在每个计数器更新上执行一个 if 语句比在最后执行简单检查更快?我不确定,请注意你可以测试两者。
让 k 成为哈希表中的槽数。使用均匀分布的散列函数,您将获得每个插槽的 n / k 元素。这导致列表的n²/ k时间复杂度,即O(n²)...... 但如果 k 接近 n 你非常接近线性时间。
堆/树桶也是如此,除了最终你得到O(n.nn)渐近复杂度。如果k足够大,那么你将接近线性时间。
答案 3 :(得分:0)
你不能使用普通的哈希表。我使用了动态编程和哈希表。
您应该像这样设置哈希表:
[数组的值,重复次数,相同对的数量]
例如,我们可以在数组A = [3, 3, 3, 3, 3]
上运行我的算法。
我们走过数组。对于A中的第一个数字,新行将插入哈希表
3,0,0 /* A[i], the number of repetition of 3 so far (Rep[i]),
the number of identical pair so far ( Iden[i]). */
然后是A中的第二个3:
3,1,1
在A中的第三个3:
3,2,3
在A中获得第4名:
3,3,6
6是该数组中相同对的数量。一般来说,我们可以通过以下公式计算相同对的数量:
Iden [i] = Rep [i] + Iden [i-1]
这是C#中的代码示例:
public static int solution(int[] A)
{
int identical = 0;
Dictionary<int, KeyValuePair<int, int>> dic = new Dictionary<int, KeyValuePair<int, int>>(); /* A[i], the number of repetition of 3 so far (Rep[i]),
the number of identical pair so far ( Iden[i]). */
for (int i = 0; i < A.Length; i++)
{
if (!dic.ContainsKey(A[i]))
dic.Add(A[i], new KeyValuePair<int, int>(0,0));
else
{
KeyValuePair<int,int> valDic = dic[A[i]];
KeyValuePair<int, int> newVal;
if (valDic.Key < 1)
newVal = new KeyValuePair<int, int>(1, 1);
else
{
int preIdenticalPair = valDic.Value;
int preReptation = valDic.Key;
int newRepetation = ++preReptation;
int newIdenticalPair = preIdenticalPair + newRepetation;
newVal = new KeyValuePair<int, int>(newRepetation, newIdenticalPair);
}
dic[A[i]] = newVal;
}
}
//summation of all identical pairs
foreach (KeyValuePair<int, KeyValuePair<int, int>> pair in dic)
identical += pair.Value.Value;
return identical;
}