我遇到了一个面试问题,要求应聘者对数组中所有具有相同数字的数字进行计数。 例如:
计算与int输入= 394共享相同数字的所有数字 int [] arr = {1,14,101,349,439,745,934}
该函数将返回3,因为439、934、349共享相同的数字。 问题是如何在O(log n)时间内解决这个问题?我对Big O概念仍然陌生,除了O(n)和O(n ^ 2)...我在理解如何归档O(log n)时遇到困难。
我的第一个想法如下: 我将计算数组中所有元素的数字总和。如果总和相等,则它们包含的数字与输入数字相同。
int counter = 0;
while (num > 0) {
int digitSum += num % 10;
num = num / 10;
}
for(int i = 0; i < arr.length; i++) {
int k = arr[i];
while (k > 0) {
int sumOfDigits += k % 10;
k = k/10;
}
if(sumOfDigits == digitSum) {
counter++;
}
}
我知道这至少需要O(n)时间,但是我很难找到更好的解决方案。
答案 0 :(得分:0)
您可以对数组进行预处理,以通过映射到该规范化表示形式的数组中数字的“字符串代表排序数字”来构建Map。完成该步骤后,根据选择的地图,分别进行jq: error: Project/0 is not defined at <top-level>, line 1:
map(if .ParameterKey == Project
jq: 1 compile error
或O(1)
的查找。匹配多少个数字都没有关系,因为您只是返回一个预先构造的数组。
因此查找确实可以非常快速地进行。但是,只有在您取消预处理步骤或通过多次查找将其摊销的情况下。
答案 1 :(得分:0)
该解决方案几乎为O(n),因为与给定数组大小(n)相比,输入中的位数非常小。
想法是从每个元素中获取尽可能少的数字,并与输入数字的相应值进行比较
public static void main(String []args){
int input = 394;
int[] arr = {1, 14, 101, 349, 439, 745, 934};
int ans = 0;
int hold = getMin(input);
for(int i = 0; i < arr.length; i++)
{
if(hold == getMin( arr[i] ))
{
ans++;
}
}
System.out.println(ans);
}
public static int getMin(int n)
{
int hold[] = new int[10];
while( n > 0)
{
hold[n % 10]++;
n /= 10;
}
int ans = 0;
for(int i = 0; i < hold.length; i++)
{
while(hold[i] > 0)
{
ans = ans * 10 + i;
hold[i]--;
}
}
return ans;
}
答案 2 :(得分:0)
最好的答案是安迪·特纳(Andy Turner)和JB尼泽特(JB Nizet),但不幸的是,这只是一个评论:
为此,我们必须假设:输入数字的大小是有界的,数组中的整数是不相交的,而n是数组中元素的数量。
总的运行时间为O(log n)。
请注意,这仅在输入数字的界限很低的情况下才可行。如果输入数字可以说20位数,则最好使用O(n)方法,除非n确实很大。