Q:对于一个自然数组,数组元素范围从1到n+2,一共n个元素,找到缺失的两个元素。
A:遍历一次,可以得到整个数组的和以及平方和;当不缺失元素时,1到n+2的和以及平方和当然是已知的。对于缺失的两个元素x和y,则有如下关系:x + y=m,x^2 + y^2=n;m为和的差,n为平方和的差。
import java.util.*;
import java.util.concurrent.*;
public class 自然数组里面缺失的两个数
{
/**
*@param arr 输入数组
*@param n 数组元素的范围从1到n
*@return 缺失的两个数组成的数组
*/
public static int[] findMissingTwo(int[] arr,int n)
{
long sum=0;
long sum2=0;
for (int i=0;i<arr.length ;i++ )
{
sum+=arr[i];
sum2+=(long)Math.pow(arr[i],2);
}
long sum_all=0;
long sum2_all=0;
for (int i=1;i<=n ;i++ )
{
sum_all+=i;
sum2_all+=i*i;
}
int diff=(int)(sum_all-sum);
int diff2=(int)(sum2_all-sum2);
int[] res=new int[2];
for (int i=1;i<=n ;i++ )
{
if (i*i+(diff-i)*(diff-i)==diff2)
{
res[0]=Math.min(i,diff-i);
res[1]=Math.max(i,diff-i);
break;
}
}
return res;
}
public static int[] findMissingTwoBad(int[] arr,int n)
{
int[] helper=new int[n];
for (int i=0;i<arr.length ;i++)
{
helper[arr[i]-1]=1;
}
int[] res=new int[2];
int index=0;
for (int i=0;i<helper.length ;i++ )
{
if (helper[i]!=1)
{
res[index++]=i;
}
}
return res;
}
public static void main(String[] args)
{
Set<Integer> set=new HashSet<>();
ThreadLocalRandom rand=ThreadLocalRandom.current();
for (int times=0;times<500 ;times++ )
{
int end=rand.nextInt(3,200);
while (set.size()<end-2)
{
int temp=rand.nextInt(1,end);
set.add(temp);
}
int[] arr=new int[end-2];
int i=0;
for (int temp:set )
arr[i++]=temp;
int[] res=findMissingTwo(arr,end);
int[] resBad=findMissingTwo(arr,end);
String str=Arrays.toString(res);
String strBad=Arrays.toString(resBad);
if (!str.equals(strBad))
System.out.println("fuck man");
set.clear();
}
}
}
如果上来就是想到常规的排序,数组的各种华丽操作,是无法解题的。颇有点智力题的意味,需要的知识储备最多是高中水平,还是在于考察一个人逻辑思维能力。