给出的是一个列表,其中包含1-20之间的所有2个数字(随机排序)。 我需要找到那两个数字。
这是我提出的(工作)计划:
public static void main(String[] args) {
int[] x= {1,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
ArrayList al= new ArrayList();
Map map= new HashMap();
for(int i=0;i<x.length;i++)
{
map.put(x[i], x[i]);
}
for(int i=1;i<=20;i++)
{
if(map.get(i)==null)
al.add(i);
}
for(int i=0;i<al.size();i++)
{
System.out.println(al.get(i));
}
}
我想从性能的角度来看程序是否合适(内存和bigO(n))?
答案 0 :(得分:7)
您不需要地图。只是一个大小为20的额外布尔数组。
for (int i = 0; i < input.length; i++)
arr[input[i]] = true;
for (int i = 1; i <= 20; i++)
if (arr[i] == false) {
//number `i` is missing
}
现在我将展示一个简单的数学解决方案。
首先对数组中的所有数字求和。例如,您5, 1, 4
的数字为1, 2, 3, 4, 5
。因此缺少2
和3
。我们可以通过数学轻松找到它们。
5 + 1 + 4 = 10
1 + 2 + 3 + 4 + 5 = 15
所以我们知道x + y = 15 - 10 = 5
现在我们将得到第二个等式:
1 * 4 * 5 = 20
1 * 2 * 3 * 4 * 5 = 120
=> x * y = 120 / 20 = 6
所以:
x + y = 5
x * y = 6
=&GT; x = 2, y = 3 or x = 3, y = 2
这是相同的。
所以x = 2, y = 3
答案 1 :(得分:1)
另一种选择是使用BitSet,其中每个位都设置为数组中的相应数字。
答案 2 :(得分:0)
由于map.put操作,您的代码在O(n)处运行。在最坏的情况下,下面的for循环也将在O(n)处运行,因此总的来说,整个函数在O(n)处运行。
您可以进一步优化代码。例如,您正在使用额外的内存。要改进这一点,你需要提出2个eqns来推断缺少的数字x和y。
Eqn1: 求和(1到20)= n *(n + 1)/ 2 添加数组中的所有数字并存储在temp中。 x + y = n *(n + 1)/ 2 - temp
式2: 乘(1到20)= n! 将所有数字乘以数组并存储在temp中。 x * y = temp / n!
求解方程式得到x和y。
所以这将在没有太多记忆的情况下运行O(n)。
答案 3 :(得分:0)
它不应该比线性时间O(n)更糟糕:一个运行来填充一个标志数组,另一个运行来检查标志数组。