一、题目描述
二、题目初步分析
杨辉三角大家都会,这题多了一个判断,相等就输出位置,难点在于:n可以为10亿,运行次数过多会超内存,超时。
三、脑中第一个想法写出的答案(暴力求解,20分)
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
int count = 1;
long[][] a = new long[num+1][];
for(int i=0;i<a.length;i++) {
a[i] = new long[i+1];
for(int j=0;j<a[i].length;j++) {
if(j==0||j==i) {
a[i][j]=1;
}else {
a[i][j] = a[i-1][j-1]+a[i-1][j];
}
}
}
for(int i=0;i<a.length;i++) {
for(int j=0;j<=i;j++) {
if(num==a[i][j]) {
System.out.println(count);
return;
}else {
count++;
}
}
}
}
}
经过多次尝试,暴力破解都无法成功,在网上查阅资料后,找到了一条比较简单容易理解的思路,做个整理,供大家参考学习。
四、满分解答
1.思路分析
逐行求数值,并查找是否有需要查找的值,若有,则输出位置;若没有,则转下一行。
2.具体流程
如上表,黄色部分为默认值或初始值。从i-1那行开始求值,从右往左求,绿色区域部分是可能需要求值的区域。
能够发现,当i=1时,arr[1]=arr[1]+arr[0];当i=2时,arr[2]=arr[2]+arr[1],arr[1]=arr[1]+arr[0];......;当i=n时,arr[n]=arr[n]+arr[n-1],arr[n-1]=arr[n-1]+arr[n-2],...... 。
因为在求出一行的值之后就进行查找,所以如果没有找到,下一行的值可以覆盖这一行的值,就不需要定义二维数组,可以节省不少内存。
由于题目测试数据达到10亿,暴力求解是行不通的,通过观察可以发现,第一列的值都为1,不用管;第二列的值为n-1,要达到10亿,需要的行数还是很多,没法定义;第三列除了起始两个元素为0之外,剩下的元素为1,3,6(1+2+...+i的累加序列)这样有规律的序列,若要使数据值超过10亿,i需要达到44721行,加上起始的两个0,一共需要44723行,此时,使用long类型的数据就可以存下,超过10亿之后,若数值仍没有出现,我们也就不用再算了,直接使用当前行第三列的值(n+1)*n/2+2即可。由此,可得到如下程序:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
long n = scan.nextLong();//输入值,查找
long[] arr =new long[44725];
arr[0]=1;
long k=1L;//k来定义位置(已经查找过的前i-1行)
if (n == 1) {
System.out.println(1);
return;
}
for (int i = 1;i<44725; i++) {
for (int j = i; j>=1; j--) {
arr[j] += arr[j - 1];
if (arr[j] == n) {
System.out.println(k + i-j + 1);//最后的+1是加上最后一行第一个1,因为是默认值,没有参与计算,所以需要加上那个位置,由于杨辉三角是对称的,i-j的关系,稍加思索应该也可以被发现
return;//如果找到了就结束
}
}
k+=(i+1);
}
System.out.println(((1 + n) * n / 2) + 2);
}
}
至此,问题就被完美的解决了。若有些同学只考虑超过10亿的情况,也可以得到50分。