【蓝桥杯】杨辉三角形--Java

文章介绍了如何使用Java编程实现打印杨辉三角形,以及寻找特定数值在三角形中的位置。针对寻找位置的问题,文章讨论了两种策略,并通过优化计算方法解决了超时和内存限制问题。最后,提出了杨辉三角形变形问题的解决方案,即确定偶数出现的位置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


题目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} C351181比1e+10大, C 33 − 1 17 − 1 C_{33-1}^{17-1} C331171比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);
        }
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值