题目1:打印杨辉三角形(二维数组)
输入格式
输入包含一个数n。
输出格式
输出杨辉三角形的前n行。每一行从这一行的第一个数开始依次输出,中间使用一个空格分隔。请不要在前面输出多余的空格。
样例输入
4
样例输出
1
1 1
1 2 1
1 3 3 1
数据规模与约定
1 <= n <= 34。
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[][] num = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < i+1; j++) {
if(j==0||i==j){
num[i][j]=1;
}else {
num[i][j]=num[i-1][j-1]+num[i-1][j];
}
System.out.printf(num[i][j]+" ");
}
System.out.println();
}
}
}
题目2:输出某个数第一次在杨辉三角形中出现的位置
思路:刚读题在想用什么数据结构存储这些值?用多大的空间?遍历数据结构也太复杂了吧!没有头绪。
首先,杨辉三角第m行第n列的公式是:
仔细观察杨辉三角会发现其有规律可循:首先其是轴对称的,因此我们只关注左半部分,以奇数行的中心列为开头的斜行是递增的。此外,第一次出现的元素一定是从斜行大的里开始寻找,如果没有就循环从上一斜行找。
思路一:search方法可以寻找合适的起始斜行,比如2,6,20这些斜行的开头元素如果比目标n大,那么n必不在该斜行。
思路二:因为
C
35
−
1
18
−
1
C_{35-1}^{18-1}
C35−118−1比1e+10大,
C
33
−
1
17
−
1
C_{33-1}^{17-1}
C33−117−1比1e+10小,因此直接从第33行的中间列的斜行开始遍历。
比如n=10,10比20小比6大,所以从6的斜行开始找,如果没找到从2开头的斜行开始找。
下面代码采用了思路一。
首先直接用递推公式中间值会超出long的大小,所以我首先使用了BigInteger对象来计算存储。
代码如下:
import java.math.BigInteger;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
long n = scanner.nextLong();
if(n==1) {
System.out.println(1);
return;
}
int x = search(n);//返回起始遍历的斜行
for (int i = x; i > 1; i-=2) { //循环斜行,每次横行-2
int a = i;//每一斜行的起始横行
int b = i/2+1;//列数
long p = jiSuan(a-1,b-1);
while (p<n){
a++;
p = jiSuan(a-1,b-1);
}
if(p==n){
System.out.println((long)(1+a-1)*(a-1)/2+b);
return;
}
}
}
//返回起始遍历的斜行
private static int search(long n) {
int i = 3;
while(!(jiSuan(i-1,i/2)>n)){
i+=2;
}
return i-2;
}
//计算杨辉三角值
private static long jiSuan(int i, int m) {
long sum = 0;
BigInteger bigInteger = new BigInteger("1");
BigInteger x = null;
for (int j = 0; j < m; j++) {
x = BigInteger.valueOf(i-j);
bigInteger = bigInteger.multiply(x);
}
for (int j = 2; j <= m; j++) {
x = BigInteger.valueOf(j);
bigInteger = bigInteger.divide(x);
}
sum = bigInteger.longValue();
return sum;
}
}
结果出现了内存超限和超时问题,用BigInteger计算消耗很大,因此我又采用了递归方法算杨辉三角值
private static long jiSuan(int i, int m) {
if(m==0||m==i) return 1;
return jiSuan(i-1,m)+jiSuan(i-1,m-1);
}
结果还是超时。
因此对我对递推公式算法进行修改:在jiSuan方法中让乘和除同时进行,这样能避免中间出现超过long的数值。
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
long n = scanner.nextLong();
if(n==1) {
System.out.println(1);
return;
}
int x = search(n);
for (int i = x; i > 1; i-=2) {
int a = i;
int b = i/2+1;
long p = jiSuan(a-1,b-1);
while (p<n){
a++;
p = jiSuan(a-1,b-1);
}
if(p==n){
System.out.println((long)(1+a-1)*(a-1)/2+b);
return;
}
}
}
private static int search(long n) {
int i = 3;
while(!(jiSuan(i-1,i/2)>n)){
i+=2;
}
return i-2;
}
private static long jiSuan(int i, int m) {
long sum = 1;
int q = m;
for (int j = 0; j < m; j++) {
sum *= i-j;
//这个判断条件必须有,如果不加结果会出现错误。比如5/2有余数,不能除。
if(q>1 && sum%q==0){
sum/=q;
q--;
}
}
//这个条件是当过程中如果因为第一个条件阻塞很多次导致q没有为1,也就是sum还需要除。
while (q>1){
sum/=q;
q--;
}
return sum;
}
}
终于通过了!
题目3:杨辉三角形的变形
链接:杨辉三角形的变形
以上三角形的数阵,第一行只有一个数1,以下每行的每个数,是恰好是它上面的数、左上角数和右上角的数,3个数之和(如果不存在某个数,认为该数就是0)。
求第n行第一个偶数出现的位置。如果没有偶数,则输出-1。例如输入3,则输出2,输入4则输出3,输入2则输出-1。
数据范围:
1 <= n <= 10^9
找规律题。
行数是4的倍数第三个数是偶数;行数是奇数第二个数是偶数;行数<=2的没有偶数,剩下的都是第四个数是偶数。
代码
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
if(n<=2){
System.out.println(-1);
}else if((n-1)%2==0){
System.out.println(2);
}else if(n%4==0){
System.out.println(3);
}else {
System.out.println(4);
}
}
}