给定大小为n的数组,找到数组中出现n / k次以上的所有元素。例如,如果输入数组为{3,1,2,2,1,2,2,3,3},k为4,则输出应为[2,3]。请注意,数组的大小为8(或n = 8),因此我们需要查找所有出现超过2(或8/4)次的元素。有两个元素出现两次以上,分别是2和3。
一种简单的方法是一个接一个地选择所有元素。对于每个拾取的元素,通过遍历数组来计数其出现的次数,如果count大于n / k,则打印该元素。该方法的时间复杂度为O(n 2 )。
更好的解决方案是使用排序。首先,使用O(nLogn)算法对所有元素进行排序。对数组进行排序后,我们可以在数组的线性扫描中找到所有必需的元素。因此,此方法的总体时间复杂度为O(nLogn)+ O(n),即O(nLogn)。
以下是一个有趣的O(nk)解决方案:
我们可以使用O(k-1)的额外空间在O(nk)时间内解决上述问题。请注意,输出中的元素不得超过k-1个(为什么?)。该算法主要包括三个步骤。
1)创建一个大小为(k-1)的临时数组来存储元素及其计数(输出元素将在这k-1个元素中)。以下是临时数组元素的结构。
struct eleCount {
int element;
int count;
};
struct eleCount temp[];
此步骤需要O(k)时间。
2)遍历输入数组,并为每个遍历的元素更新temp [](添加/删除元素或增加/减少计数)。数组temp []在每个步骤中存储潜在(k-1)个候选对象。此步骤需要O(nk)时间。
3)遍历最终(k-1)个潜在候选对象(存储在temp []中)。或每个元素,请检查其实际计数是否大于n / k。此步骤需要O(nk)时间。
主要步骤是步骤2,如何在每个点上保持(k-1)个潜在候选者?步骤2中使用的步骤类似于著名的游戏:Tetris。我们在Tetris中将每个数字视为一个部分,这属于我们的临时数组temp []。我们的任务是尝试将相同的数字堆叠在同一列上(临时数组中的计数增加)。
Consider k = 4, n = 9
Given array: 3 1 2 2 2 1 4 3 3
i = 0
3 _ _
temp[] has one element, 3 with count 1
i = 1
3 1 _
temp[] has two elements, 3 and 1 with
counts 1 and 1 respectively
i = 2
3 1 2
temp[] has three elements, 3, 1 and 2 with
counts as 1, 1 and 1 respectively.
i = 3
- - 2
3 1 2
temp[] has three elements, 3, 1 and 2 with
counts as 1, 1 and 2 respectively.
i = 4
- - 2
- - 2
3 1 2
temp[] has three elements, 3, 1 and 2 with
counts as 1, 1 and 3 respectively.
i = 5
- - 2
- 1 2
3 1 2
temp[] has three elements, 3, 1 and 2 with
counts as 1, 2 and 3 respectively.
现在出现了一个问题,当temp []满时该怎么办,我们看到一个新元素–我们从元素堆栈中删除了底行,即,我们在temp []中将每个元素的数量减少1。我们忽略当前元素。
i = 6
- - 2
- 1 2
temp[] has two elements, 1 and 2 with
counts as 1 and 2 respectively.
i = 7
- 2
3 1 2
temp[] has three elements, 3, 1 and 2 with
counts as 1, 1 and 2 respectively.
i = 8
3 - 2
3 1 2
temp[] has three elements, 3, 1 and 2 with
counts as 2, 1 and 2 respectively.
最后,我们在temp []中最多有k-1个数字。 temp中的元素为{3,1,2}。请注意,temp []中的计数现在已无用,仅在步骤2中才需要计数。现在我们需要检查temp []中元素的实际计数是否大于n / k(9/4)。元素3和2的计数大于9/4。因此,我们打印3和2。
请注意,该算法不会丢失任何输出元素。可能有两种可能性,许多事件在一起或分布在整个阵列中。如果出现的次数在一起,则count将很高,并且不会变为0。如果出现的次数分散,则该元素将在temp []中再次出现。以下是上述算法的实现。
C++
// A C++ program to print elements with count more than n/k
#include
using namespace std;
// A structure to store an element and its current count
struct eleCount {
int e; // Element
int c; // Count
};
// Prints elements with more
// than n/k occurrences in arr[]
// of size n. If there are no
// such elements, then it prints
// nothing.
void moreThanNdK(int arr[], int n, int k)
{
// k must be greater than
// 1 to get some output
if (k < 2)
return;
/* Step 1: Create a temporary
array (contains element
and count) of size k-1.
Initialize count of all
elements as 0 */
struct eleCount temp[k - 1];
for (int i = 0; i < k - 1; i++)
temp[i].c = 0;
/* Step 2: Process all
elements of input array */
for (int i = 0; i < n; i++)
{
int j;
/* If arr[i] is already present in
the element count array,
then increment its count
*/
for (j = 0; j < k - 1; j++)
{
if (temp[j].e == arr[i])
{
temp[j].c += 1;
break;
}
}
/* If arr[i] is not present in temp[] */
if (j == k - 1) {
int l;
/* If there is position available
in temp[], then place arr[i] in
the first available position and
set count as 1*/
for (l = 0; l < k - 1; l++)
{
if (temp[l].c == 0)
{
temp[l].e = arr[i];
temp[l].c = 1;
break;
}
}
/* If all the position in the
temp[] are filled, then decrease
count of every element by 1 */
if (l == k - 1)
for (l = 0; l < k; l++)
temp[l].c -= 1;
}
}
/*Step 3: Check actual counts of
* potential candidates in temp[]*/
for (int i = 0; i < k - 1; i++)
{
// Calculate actual count of elements
int ac = 0; // actual count
for (int j = 0; j < n; j++)
if (arr[j] == temp[i].e)
ac++;
// If actual count is more than n/k,
// then print it
if (ac > n / k)
cout << "Number:" << temp[i].e
<< " Count:" << ac << endl;
}
}
/* Driver code */
int main()
{
cout << "First Test\n";
int arr1[] = { 4, 5, 6, 7, 8, 4, 4 };
int size = sizeof(arr1) / sizeof(arr1[0]);
int k = 3;
moreThanNdK(arr1, size, k);
cout << "\nSecond Test\n";
int arr2[] = { 4, 2, 2, 7 };
size = sizeof(arr2) / sizeof(arr2[0]);
k = 3;
moreThanNdK(arr2, size, k);
cout << "\nThird Test\n";
int arr3[] = { 2, 7, 2 };
size = sizeof(arr3) / sizeof(arr3[0]);
k = 2;
moreThanNdK(arr3, size, k);
cout << "\nFourth Test\n";
int arr4[] = { 2, 3, 3, 2 };
size = sizeof(arr4) / sizeof(arr4[0]);
k = 3;
moreThanNdK(arr4, size, k);
return 0;
}
Java
// A Java program to print elements with count more than n/k
import java.util.*;
class GFG{
// A structure to store an element and its current count
static class eleCount {
int e; // Element
int c; // Count
};
// Prints elements with more
// than n/k occurrences in arr[]
// of size n. If there are no
// such elements, then it prints
// nothing.
static void moreThanNdK(int arr[], int n, int k)
{
// k must be greater than
// 1 to get some output
if (k < 2)
return;
/* Step 1: Create a temporary
array (contains element
and count) of size k-1.
Initialize count of all
elements as 0 */
eleCount []temp = new eleCount[k - 1];
for (int i = 0; i < k - 1; i++)
temp[i] = new eleCount();
for (int i = 0; i < k - 1; i++) {
temp[i].c = 0;
}
/* Step 2: Process all
elements of input array */
for (int i = 0; i < n; i++)
{
int j;
/* If arr[i] is already present in
the element count array,
then increment its count
*/
for (j = 0; j < k - 1; j++)
{
if (temp[j].e == arr[i])
{
temp[j].c += 1;
break;
}
}
/* If arr[i] is not present in temp[] */
if (j == k - 1) {
int l;
/* If there is position available
in temp[], then place arr[i] in
the first available position and
set count as 1*/
for (l = 0; l < k - 1; l++)
{
if (temp[l].c == 0)
{
temp[l].e = arr[i];
temp[l].c = 1;
break;
}
}
/* If all the position in the
temp[] are filled, then decrease
count of every element by 1 */
if (l == k - 1)
for (l = 0; l < k-1; l++)
temp[l].c -= 1;
}
}
/*Step 3: Check actual counts of
* potential candidates in temp[]*/
for (int i = 0; i < k - 1; i++)
{
// Calculate actual count of elements
int ac = 0; // actual count
for (int j = 0; j < n; j++)
if (arr[j] == temp[i].e)
ac++;
// If actual count is more than n/k,
// then print it
if (ac > n / k)
System.out.print("Number:" + temp[i].e
+ " Count:" + ac +"\n");
}
}
/* Driver code */
public static void main(String[] args)
{
System.out.print("First Test\n");
int arr1[] = { 4, 5, 6, 7, 8, 4, 4 };
int size = arr1.length;
int k = 3;
moreThanNdK(arr1, size, k);
System.out.print("\nSecond Test\n");
int arr2[] = { 4, 2, 2, 7 };
size = arr2.length;
k = 3;
moreThanNdK(arr2, size, k);
System.out.print("\nThird Test\n");
int arr3[] = { 2, 7, 2 };
size = arr3.length;
k = 2;
moreThanNdK(arr3, size, k);
System.out.print("\nFourth Test\n");
int arr4[] = { 2, 3, 3, 2 };
size = arr4.length;
k = 3;
moreThanNdK(arr4, size, k);
}
}
// This code contributed by Princi Singh .
Python3
# A Python3 program to print elements with
# count more than n/k
# Prints elements with more than n/k
# occurrences in arrof size n. If
# there are no such elements, then
# it prints nothing.
def moreThanNdK(arr, n, k):
# k must be greater than 1
# to get some output
if (k < 2):
return
# Step 1: Create a temporary array
# (contains element and count) of
# size k-1. Initialize count of all
# elements as 0
temp = [[0 for i in range(2)]
for i in range(k)]
for i in range(k - 1):
temp[i][0] = 0
# Step 2: Process all elements
# of input array
for i in range(n):
j = 0
# If arr[i] is already present in
# the element count array, then
# increment its count
while j < k - 1:
if (temp[j][1] == arr[i]):
temp[j][0] += 1
break
j += 1
# If arr[i] is not present in temp
if (j == k - 1):
l = 0
# If there is position available
# in temp[], then place arr[i]
# in the first available position
# and set count as 1*/
while l < k - 1:
if (temp[l][0] == 0):
temp[l][1] = arr[i]
temp[l][0] = 1
break
l += 1
# If all the position in the
# tempare filled, then decrease
# count of every element by 1
if (l == k - 1):
while l < k:
temp[l][0] -= 1
l += 1
# Step 3: Check actual counts
# of potential candidates in temp[]
for i in range(k - 1):
# Calculate actual count of elements
ac = 0 # Actual count
for j in range(n):
if (arr[j] == temp[i][1]):
ac += 1
# If actual count is more
# than n/k, then prit
if (ac > n // k):
print("Number:",
temp[i][1],
" Count:", ac)
# Driver code
if __name__ == '__main__':
print("First Test")
arr1 = [4, 5, 6, 7, 8, 4, 4]
size = len(arr1)
k = 3
moreThanNdK(arr1, size, k)
print("Second Test")
arr2 = [4, 2, 2, 7]
size = len(arr2)
k = 3
moreThanNdK(arr2, size, k)
print("Third Test")
arr3 = [2, 7, 2]
size = len(arr3)
k = 2
moreThanNdK(arr3, size, k)
print("Fourth Test")
arr4 = [2, 3, 3, 2]
size = len(arr4)
k = 3
moreThanNdK(arr4, size, k)
# This code is contributed by mohit kumar 29
C#
// A C# program to print elements
// with count more than n/k
using System;
class GFG
{
// A structure to store an element
// and its current count
public class eleCount {
public int e; // Element
public int c; // Count
};
// Prints elements with more
// than n/k occurrences in []arr
// of size n. If there are no
// such elements, then it prints
// nothing.
static void moreThanNdK(int []arr, int n, int k)
{
// k must be greater than
// 1 to get some output
if (k < 2)
return;
/* Step 1: Create a temporary
array (contains element
and count) of size k-1.
Initialize count of all
elements as 0 */
eleCount []temp = new eleCount[k - 1];
for (int i = 0; i < k - 1; i++)
temp[i] = new eleCount();
for (int i = 0; i < k - 1; i++)
{
temp[i].c = 0;
}
/* Step 2: Process all
elements of input array */
for (int i = 0; i < n; i++)
{
int j;
/* If arr[i] is already present in
the element count array,
then increment its count
*/
for (j = 0; j < k - 1; j++)
{
if (temp[j].e == arr[i])
{
temp[j].c += 1;
break;
}
}
/* If arr[i] is not present in []temp */
if (j == k - 1)
{
int l;
/* If there is position available
in []temp, then place arr[i] in
the first available position and
set count as 1*/
for (l = 0; l < k - 1; l++)
{
if (temp[l].c == 0)
{
temp[l].e = arr[i];
temp[l].c = 1;
break;
}
}
/* If all the position in the
[]temp are filled, then decrease
count of every element by 1 */
if (l == k - 1)
for (l = 0; l < k-1; l++)
temp[l].c -= 1;
}
}
/*Step 3: Check actual counts of
* potential candidates in []temp*/
for (int i = 0; i < k - 1; i++)
{
// Calculate actual count of elements
int ac = 0; // actual count
for (int j = 0; j < n; j++)
if (arr[j] == temp[i].e)
ac++;
// If actual count is more than n/k,
// then print it
if (ac > n / k)
Console.Write("Number:" + temp[i].e
+ " Count:" + ac + "\n");
}
}
/* Driver code */
public static void Main(String[] args)
{
Console.Write("First Test\n");
int []arr1 = { 4, 5, 6, 7, 8, 4, 4 };
int size = arr1.Length;
int k = 3;
moreThanNdK(arr1, size, k);
Console.Write("\nSecond Test\n");
int []arr2 = { 4, 2, 2, 7 };
size = arr2.Length;
k = 3;
moreThanNdK(arr2, size, k);
Console.Write("\nThird Test\n");
int []arr3 = { 2, 7, 2 };
size = arr3.Length;
k = 2;
moreThanNdK(arr3, size, k);
Console.Write("\nFourth Test\n");
int []arr4 = { 2, 3, 3, 2 };
size = arr4.Length;
k = 3;
moreThanNdK(arr4, size, k);
}
}
// This code is contributed by 29AjayKumar
C++
// C++ code to find elements whose
// frequency yis more than n/k
#include
using namespace std;
void morethanNbyK(int arr[], int n, int k)
{
int x = n / k;
// unordered_map initialization
unordered_map freq;
for(int i = 0; i < n; i++)
{
freq[arr[i]]++;
}
// Traversing the map
for(auto i : freq)
{
// Checking if value of a key-value pair
// is greater than x (where x=n/k)
if (i.second > x)
{
// Print the key of whose value
// is greater than x
cout << i.first << endl;
}
}
}
// Driver Code
int main()
{
int arr[] = { 1, 1, 2, 2, 3, 5,
4, 2, 2, 3, 1, 1, 1 };
int n = sizeof(arr) / sizeof(arr[0]);
int k = 4;
morethanNbyK(arr, n, k);
return 0;
}
// This code is contributed by chayandas018
Java
// Java Code to find elements whose
// frequency yis more than n/k
import java.util.*;
public class Main
{
public static void morethanNdK(int a[], int n, int k)
{
int x = n / k;
// Hash map initialization
HashMap y = new HashMap<>();
// count the frequency of each element.
for (int i = 0; i < n; i++)
{
// is element doesn't exist in hash table
if (!y.containsKey(a[i]))
y.put(a[i], 1);
// if lement does exist in the hash table
else
{
int count = y.get(a[i]);
y.put(a[i], count + 1);
}
}
// iterate over each element in the hash table
// and check their frequency, if it is more than
// n/k, print it.
for (Map.Entry m : y.entrySet())
{
Integer temp = (Integer)m.getValue();
if (temp > x)
System.out.println(m.getKey());
}
}
// Driver Code
public static void main(String[] args)
{
int a[] = new int[] { 1, 1, 2, 2, 3, 5, 4,
2, 2, 3, 1, 1, 1 };
int n = 12;
int k = 4;
morethanNdK(a, n, k);
}
}
Python3
# Python3 code to find elements whose
# frequency yis more than n/k
def morethanNbyK(arr, n, k) :
x = n // k
# unordered_map initialization
freq = {}
for i in range(n) :
if arr[i] in freq :
freq[arr[i]] += 1
else :
freq[arr[i]] = 1
# Traversing the map
for i in freq :
# Checking if value of a key-value pair
# is greater than x (where x=n/k)
if (freq[i] > x) :
# Print the key of whose value
# is greater than x
print(i)
# Driver code
arr = [ 1, 1, 2, 2, 3, 5, 4, 2, 2, 3, 1, 1, 1 ]
n = len(arr)
k = 4
morethanNbyK(arr, n, k)
# This code is contributed by mohit kumar 29
C#
// C# code to find elements whose
// frequency yis more than n/k
using System;
using System.Collections.Generic;
class GFG{
public static void morethanNdK(int []a, int n,
int k)
{
int x = n / k;
// Hash map initialization
Dictionary y = new Dictionary();
// Count the frequency of each element.
for(int i = 0; i < n; i++)
{
// Is element doesn't exist in hash table
if (!y.ContainsKey(a[i]))
y.Add(a[i], 1);
// If lement does exist in the hash table
else
{
int count = y[a[i]];
y[a[i]] = count + 1;
}
}
// Iterate over each element in the hash table
// and check their frequency, if it is more than
// n/k, print it.
foreach(KeyValuePair m in y)
{
int temp = (int)m.Value;
if (temp > x)
Console.WriteLine(m.Key);
}
}
// Driver Code
public static void Main(String[] args)
{
int []a = new int[]{ 1, 1, 2, 2, 3, 5, 4,
2, 2, 3, 1, 1, 1 };
int n = 12;
int k = 4;
morethanNdK(a, n, k);
}
}
// This code is contributed by Princi Singh
Python3
# Python3 implementation
from collections import Counter
# Function to find the number of array
# elements with frequency more than n/k times
def printElements(arr, n, k):
# Calculating n/k
x = n//k
# Counting frequency of every
# element using Counter
mp = Counter(arr)
# Traverse the map and print all
# the elements with occurrence
# more than n/k times
for it in mp:
if mp[it] > x:
print(it)
# Driver code
arr = [1, 1, 2, 2, 3, 5, 4, 2, 2, 3, 1, 1, 1]
n = len(arr)
k = 4
printElements(arr, n, k)
# This code is contributed by vikkycirus
First Test
Number:4 Count:3
Second Test
Number:2 Count:2
Third Test
Number:2 Count:2
Fourth Test
Number:2 Count:2
Number:3 Count:2
时间复杂度: O(nk)
辅助空间: O(k)
通常会问到此问题的变体,找到所有在O(n)时间复杂度和O(1)额外空间中出现n / 3次或n / 4次的元素。
另一种方法:
散列也可以是一种有效的解决方案。有了良好的哈希函数,我们平均可以在O(n)时间内解决上述问题。散列所需的额外空间将大于O(k)。同样,哈希不能用于解决O(1)额外空间的上述变化。
下面是上述想法的实现:
C++
// C++ code to find elements whose
// frequency yis more than n/k
#include
using namespace std;
void morethanNbyK(int arr[], int n, int k)
{
int x = n / k;
// unordered_map initialization
unordered_map freq;
for(int i = 0; i < n; i++)
{
freq[arr[i]]++;
}
// Traversing the map
for(auto i : freq)
{
// Checking if value of a key-value pair
// is greater than x (where x=n/k)
if (i.second > x)
{
// Print the key of whose value
// is greater than x
cout << i.first << endl;
}
}
}
// Driver Code
int main()
{
int arr[] = { 1, 1, 2, 2, 3, 5,
4, 2, 2, 3, 1, 1, 1 };
int n = sizeof(arr) / sizeof(arr[0]);
int k = 4;
morethanNbyK(arr, n, k);
return 0;
}
// This code is contributed by chayandas018
Java
// Java Code to find elements whose
// frequency yis more than n/k
import java.util.*;
public class Main
{
public static void morethanNdK(int a[], int n, int k)
{
int x = n / k;
// Hash map initialization
HashMap y = new HashMap<>();
// count the frequency of each element.
for (int i = 0; i < n; i++)
{
// is element doesn't exist in hash table
if (!y.containsKey(a[i]))
y.put(a[i], 1);
// if lement does exist in the hash table
else
{
int count = y.get(a[i]);
y.put(a[i], count + 1);
}
}
// iterate over each element in the hash table
// and check their frequency, if it is more than
// n/k, print it.
for (Map.Entry m : y.entrySet())
{
Integer temp = (Integer)m.getValue();
if (temp > x)
System.out.println(m.getKey());
}
}
// Driver Code
public static void main(String[] args)
{
int a[] = new int[] { 1, 1, 2, 2, 3, 5, 4,
2, 2, 3, 1, 1, 1 };
int n = 12;
int k = 4;
morethanNdK(a, n, k);
}
}
Python3
# Python3 code to find elements whose
# frequency yis more than n/k
def morethanNbyK(arr, n, k) :
x = n // k
# unordered_map initialization
freq = {}
for i in range(n) :
if arr[i] in freq :
freq[arr[i]] += 1
else :
freq[arr[i]] = 1
# Traversing the map
for i in freq :
# Checking if value of a key-value pair
# is greater than x (where x=n/k)
if (freq[i] > x) :
# Print the key of whose value
# is greater than x
print(i)
# Driver code
arr = [ 1, 1, 2, 2, 3, 5, 4, 2, 2, 3, 1, 1, 1 ]
n = len(arr)
k = 4
morethanNbyK(arr, n, k)
# This code is contributed by mohit kumar 29
C#
// C# code to find elements whose
// frequency yis more than n/k
using System;
using System.Collections.Generic;
class GFG{
public static void morethanNdK(int []a, int n,
int k)
{
int x = n / k;
// Hash map initialization
Dictionary y = new Dictionary();
// Count the frequency of each element.
for(int i = 0; i < n; i++)
{
// Is element doesn't exist in hash table
if (!y.ContainsKey(a[i]))
y.Add(a[i], 1);
// If lement does exist in the hash table
else
{
int count = y[a[i]];
y[a[i]] = count + 1;
}
}
// Iterate over each element in the hash table
// and check their frequency, if it is more than
// n/k, print it.
foreach(KeyValuePair m in y)
{
int temp = (int)m.Value;
if (temp > x)
Console.WriteLine(m.Key);
}
}
// Driver Code
public static void Main(String[] args)
{
int []a = new int[]{ 1, 1, 2, 2, 3, 5, 4,
2, 2, 3, 1, 1, 1 };
int n = 12;
int k = 4;
morethanNdK(a, n, k);
}
}
// This code is contributed by Princi Singh
1
2
方法2:使用内置的Python函数:
- 使用Counter()函数计算每个元素的频率。
- 遍历频率阵列并打印所有出现在n / k次以上的元素。
下面是实现:
Python3
# Python3 implementation
from collections import Counter
# Function to find the number of array
# elements with frequency more than n/k times
def printElements(arr, n, k):
# Calculating n/k
x = n//k
# Counting frequency of every
# element using Counter
mp = Counter(arr)
# Traverse the map and print all
# the elements with occurrence
# more than n/k times
for it in mp:
if mp[it] > x:
print(it)
# Driver code
arr = [1, 1, 2, 2, 3, 5, 4, 2, 2, 3, 1, 1, 1]
n = len(arr)
k = 4
printElements(arr, n, k)
# This code is contributed by vikkycirus
输出:
1
2
时间复杂度: O(N)
辅助空间: O(N)