首页 > 试题广场 >

蛇形矩阵

[编程题]蛇形矩阵
  • 热度指数:166702 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解

蛇形矩阵是由1开始的自然数依次排列成的一个矩阵上三角形。

例如,当输入5时,应该输出的三角形为:

1 3 6 10 15

2 5 9 14

4 8 13

7 12

11



输入描述:

输入正整数N(N不大于100)



输出描述:

输出一个N行的蛇形矩阵。

示例1

输入

4

输出

1 3 6 10
2 5 9
4 8
7
n = int(input())
# 生成一个n*n矩阵
lst = []
# 无numpy库,循环生成
for i in range(n):
    lst.append([])
    for j in range(n):
        lst[i].append(0)
# 初始化第一个数
lst[0][0] = 1
# 初始化第0列
for i in range(1, n):
    lst[i][0] = lst[i-1][0] + i
# 从第一列开始,生成蛇形矩阵
i, j = 0, 1
for i in range(n):
    for j in range(1, n):
        if i+j < n:
            # 后一列 = 前一列+行数+列数+1
            lst[i][j] = lst[i][j-1] + i + j + 1
# 打印蛇形矩阵
for i in range(n):
    for j in range(n):
        # 上对角元素
        if i+j < n:
            # 每一行最后一个元素
            if i+j == n-1:
                print(int(lst[i][j]))
            # 每一行非最后元素
            else:
                print(int(lst[i][j]), end=' ')

发表于 2022-07-27 19:39:22 回复(0)
思路超详细!

//接收整数
//第一步,先写双循环的计数器相关信息,做好排列形状
//第二步,确定任意行的第任意个数
//通过观察得知
//同行的数并不是等差数列,但是他们的差值是等差数列,所以差值用先赋值再自增的形式, (下一个数=上一个数+差值 差值自增)
//换句话说,我们知道行的第一个数,和初始差值,就能知道后面的数
//又因为,每一行的第一个数之间,他们的差值是等差数列,我们知道第一行的第一个数,和它与第二行的第一个数的差值,
//我们就可以知道任意行的第一个数
//到此,所有思路全部落地

import java.util.*;

public class Main{
    public static void main(String []args){
       int n=new Scanner(System.in).nextInt();
        //当前行的第一个数,1是初始值,代表第一行第一个数
        int h1=1;
        
        //当前行的第一个数与下一行的第一个数的差值,1是初始值,代表第一行第一个数与第二行第一个数的差值是1
        int h1d=1;
        
        //确定形状,一共有n行,第一行的长度是n,但后面的都是减少1,所以,由第一行推出任意行的长度应该是n-(i-1)
        for(int i=1 ;i<=n;i++){
            //h代表行的任意一个数,h1是初始值
            
               int h=h1;
               //hd代表当前数与下一个数的差值,由于后面数之间的差值是等差数列,
               //所以我们只需要知道观察不同行中,第一个和第二个数之间的差值就会发现,他们都和i有关系
               int hd=i+1;
            
            
            //以上两个既然是每一行的初始值,所以要在外层
           for(int j=1;j<=n-(i-1);j++){
               
               //输出当前数
               System.out.print(h+" ");
               //做好同行的下一个数 自己加上差值,差值自增(差值是等差数列嘛)
               //也可以写成h+=hd++
               h=h+(hd++);
                }
            //换行
            System.out.println();
            
            //做下一行的第一个数,同样的,自己加上差值,差值自增(差值是等差数列),你也可以直接用i去替代h1d
            h1=h1+(h1d++);
            
             }
        
        
        
        
 
    }
}


发表于 2022-05-24 15:04:50 回复(0)
0.5*(x+y+1)(x+y+2)-y
发表于 2022-05-20 11:12:29 回复(0)
发表于 2022-05-03 17:13:59 回复(1)
问题不复杂可以尝试几种方式做:
1.像蛇形走位一样将数值放入数组,比较好理解
import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        int[][] arr = set(n);
        //System.out.println(n);
        StringBuilder sb = new StringBuilder();
        for(int i=0; i<n; i++){
            for(int j=0; j<n-i; j++){
                sb.append(arr[i][j]).append(" ");
            }
            sb.append("\r\n");
        }
        System.out.println(sb.toString());
        br.close();
    }
    
    public static int[][] set(int n){
        int[][] arr = new int[n][n];
        int y=0, m=0;//y为横坐标,m表示坐标上的值
        for(int i=0; i<n; i++){//i为斜着的行
            y = i;
            while(y>=0){
                arr[y][i-y] = ++m;
                y--;
            }
        }
        return arr;
    }
    
}
2.硬方法,线下计算得出坐标公式,求公式比较难
import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        StringBuilder sb = new StringBuilder();
        int number = 0;
        for(int x=1; x<=n; x++){//横坐标x
            for(int y=1; y<=n-x+1; y++){//纵坐标y
                //线下计算得出坐标公式
                number = (x*x + y*y -y -3*x)/2 + x*y + 1;
                sb.append(number).append(" ");
            }
            sb.append("\r\n");
        }
        System.out.println(sb.toString());
        br.close();
    }
}
3.定义一个横向步长(x+y+1)和一个纵向步长(x),每一行计算后接着计算下一行
import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        StringBuilder sb = new StringBuilder();
        int base = 1;//每一行的初始值
        for(int x=0; x<n; x++){//横坐标x,从0开始
            base += x;//初始值累积
            int number = base;//坐标值
            for(int y=0; y<n-x; y++){//纵坐标y,从0开始
                if(y>0){
                    number += x+y+1;//x+y+1为横坐标步长
                }
                sb.append(number).append(" ");
            }
            sb.append("\r\n");
        }
        System.out.println(sb.toString());
        br.close();
    }
}




发表于 2022-04-22 15:38:25 回复(0)
第一行[1 3 6 10]依次相加 2 3 4
第二行[2 5 9]     依次相加    3 4
第三行[4 8]        依次相加       4
第四行[7]           依次相加
每行第一个依次相加1 2 3 ...
a = int(input())
for i in range(1, a + 1):
    num = 1 + sum(range(i))
    for j in range(1 + i, a + 2):
        print(num, end=' ')
        num = num + j
    print()
发表于 2022-03-28 17:54:58 回复(0)
num = int(input())
#dic = {}
first = 1
for i in range(0,num):
    li = []
    first = first + i
    li.append(str(first))
#    print(first, end = " ")
    val = first
    for j in range(i+2, num+1):
        val = val + j
        li.append(str(val))
        #       print(val, end = " ")
#   print(li)
    print(" ".join(li))

发表于 2022-03-23 10:38:07 回复(1)
while True:
    try:
        n=int(input())
        for i in range(n):
            an=int(1+i*(i+1)/2)
            p=2
            for j in range(n-i):
                print(an,end=' ')
                x=i+p
                an=an+x
                p+=1
            print()
    except:
        break

发表于 2021-12-19 22:05:02 回复(0)
没找到通项公式,所以干脆用递推公式,因为是嵌入式出身,比较舍不得用内存,所以就用了一行的buffer。
#include <stdio.h>

int iLineBuff[101];

void genFirstLine(int *buf, int len)
{
    int i;
    int temp = 0;
    for(i=1;i<=len;++i)
    {
        buf[i] = i * i - temp;
        temp = buf[i];
    }
}
void printTriangle(int *buff, int len)
{
    int i, j;
    for(i=1;i<=len;++i)
    {
        for(j=i;j<=len;++j)
        {
            printf("%d ", buff[j]--);
        }
        printf("\n");
    }
}

int main()
{
    int len;
    while(EOF != scanf("%d", &len))
    {
        genFirstLine(iLineBuff, len);
        printTriangle(iLineBuff, len);
    }
    return 0;
}


发表于 2021-09-17 23:07:17 回复(0)
while True:
    try:
        a =int(input())

        b = []
        s = 0
        for i in range(0,a+1):
            b.append([])
            for j in range(0,i):
                s+=1
                b[i].append(s)
        b = b[1::]


        
        for i in range(a):
            for j in range(i,a): #(0,3)  (1,3) (2,3) (3)
                print(b[j][j-i],end=' ')
            print()  
    except:
        break


发表于 2021-09-12 15:12:37 回复(0)
#include <bits/stdc++.h>
using namespace std;


int main(){
    /*
    蛇形矩阵是由1开始的自然数依次排列成的一个矩阵上三角形。
    例如,当输入5时,应该输出的三角形为:
    1 3 6 10 15
    2 5 9 14
    4 8 13
    7 12
    11
    */
    /*  N = 5
    第一行,依次+2 +3 +4 +5
    第二行,依次+3 +4 +5
    第三行,依次+4 +5
    第四行,+5
    第五行,第四行最后一个减1
    每排开头的第一个 等于 上一排第二个减一
    */
    //可以创建一个二维数组,i为行数,每行第二个数为  第一个数+i+1,
    int inputNum;
    while(cin >> inputNum){
        vector<vector<int>> vec;
        vec.resize(inputNum);//初始化二维数组的行数
        int i = 0 , n = inputNum;
        int num = 1;
        while(n > 0){
            for(int j = i + 1; j <= inputNum; j++){//插入一行数组
                vec[i].push_back(num);
                num = num + j + 1;
            }
            i++;//控制数组插入行数
            n--;
            num = vec[i - 1][1] - 1;
        }
        for(int f = 0; f < inputNum; f++){
            for(int t = 0; t < vec[f].size(); t++){
                cout << vec[f][t] << " ";
            }
            cout << endl;
        }
    }
    return 0;
}

发表于 2021-09-02 13:42:08 回复(0)
#include<iostream>
#include<vector>
using namespace std;

int main(){
    int n;
    while(cin>>n){
        vector<vector<int>>snake(n,vector<int>(n,0));
        //初始化第一行
        for(int i=0;i<n;i++){
            snake[0][i]=(i+1)*(i+2)/2;
        }
        //递推
        for(int i=1;i<n;i++){
            for(int j=0;j<n-i;j++){
                snake[i][j]=snake[i-1][j+1]-1;
            }
        }
        //输出
        for(int i=0;i<n;i++){
            for(int j=0;j<n-i;j++){
                cout<<snake[i][j]<<" ";
            }
            cout<<endl;
        }
    }
    return 0;
}

发表于 2021-08-16 14:55:30 回复(0)
#include<iostream>
#include<vector>
using namespace std;
int main() {
	int n;
	while (cin >> n){
        //初始化矩阵
		vector<vector<int>> vvi( n,vector<int>(n,0) );
		int cnt = 1;
        //按规律在矩阵中填写数字
		for (int i = 0; i < n; i++) {
			for (int j = i; j >= 0; j--) {
				vvi[j][i -j ] = cnt++;
			}
		}
        //打印有意义部分的矩阵
		for (int i = 0; i < n;i++) {
			for (int j = 0; j < n-i;j++) {
				cout << vvi[i][j] << " ";
			}
			cout << endl;
		}
	}
}

发表于 2021-08-15 22:58:28 回复(0)
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while(in.hasNextInt()){
            int n = in.nextInt(), a = 0, k = 1;
            for(int i=1;i<=n;i++){
                k += i-1;
                a = k;
                System.out.print(a+" ");
                for(int j=1,k2=1+i;j<=n-i;j++){  // 注意:j<=n-i是使每行输出的个数递减,k2=1+i是每行的初始都会加1
                    a += (k2++);
                    System.out.print(a+" ");
                }
                System.out.println();
            }
        }
    }
}

发表于 2021-08-11 23:19:49 回复(0)
这个题需要找到首列元素和每一行元素之间的规律,之后就好写了
import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        int lines = 0;

        while (scanner.hasNext()){
            lines = scanner.nextInt();
            printSnakeNum(lines);
        }
    }

    public static void printSnakeNum(int lines){
        int head = 1;    // 从 1 开始
        for (int i = 0; i < lines; i++){
            head += i;    // 首列元素之间相差 1 2 3 4.... 以此类推
            System.out.print(head + " ");
            int body = head;
            for (int j = i + 2; j <= lines; j++){    // 第一行元素从2相差开始递增,第二行从3开始递增,每一行都比上一行的差值增1
                body += j;
                System.out.print(body + " ");
            }
            System.out.println();
        }
    }
}


发表于 2021-08-06 16:11:20 回复(0)
while True:
    try:
        n=int(input())
        res={}
        count=1
        for ii in range(0,n):
            for jj in range(0,ii+1):
                res[(ii-jj,jj)]=count
                count+=1
        for r in range(0,n):
            for c in range(0,n-r):
                print (str(res[(r,c)]),end=' ')
            print (end='\n')
    except:
        break

编辑于 2021-07-09 12:22:42 回复(0)
#include <stdio.h>
#include <stdlib.h>

#define N 100

int mat[N][N];

int main(void) {
  int n, i, j, k, num;
  while (scanf("%d", &n) != EOF) {
    num = 1;
    for (k = 0; k < n; ++k)
      for (i = k, j = 0; i >= 0; --i, ++j)
        mat[i][j] = num++;
    
    for (i = 0; i < n; ++i) {
      for (j = 0; j < n - i; ++j)
        printf("%d ", *(*(mat + i) + j));
      putchar('\n');
    }
  }
  return 0;
}

发表于 2021-07-06 19:25:46 回复(0)
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<vector>
using namespace std;
int main()
{
    int n;
    while(cin>>n) {
        vector<vector<int>> matrix;
        int id=1;
        n=(1+n)*n/2; //输出的数字总数
        while(id<=n) {
            matrix.push_back(vector<int>(1,id++));
            int div=matrix.size();
            div-=1;
            while(--div>=0) {
                matrix[div].push_back(id++);
            }
        }
        for(int i=0;i<matrix.size();++i) {
            for(int x:matrix[i]) {
                cout<<x<<" ";
            }
            cout<<endl;
        }
    }
    return 0;
}
发表于 2021-06-26 11:41:19 回复(0)
 public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        while(in.hasNext()){
            int num = in.nextInt();
            //记录所有行第一个元素的值
            int[] first = new int[num];
            first[0] = 1;
            for(int i = 0;i < num;i++){
                if(i > 0){
                    first[i] = first[i - 1] + i;
                }
                //记录这一行的值
                int[] rows = new int[num - i];
                rows[0] = first[i];
                for(int j = 0;j < num - i;j++){
                    if(j > 0){
                        //找规律,该值与i和j都有关系
                        rows[j] = rows[j - 1] + i + j + 1; 
                    }
                    System.out.print(rows[j] + " ");
                }
                System.out.println();
            }
        }
    }
发表于 2021-04-14 16:03:32 回复(0)
其实是有规律的
(1) 对于行:第一行第一个数为1,之后每行的第一个数按照增幅1,2,3,4,...进行变化。
(2) 对于列:每列的数以该行的第一个数为基准,也是按照有规律的增幅进行变化,第i行的初始增幅为i+1,往后的增幅每列自增1。
(3) 第一行n个数,第二行n-1个数,......
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line;
        while((line = br.readLine()) != null){
            int N = Integer.parseInt(line.trim());
            int rowBeginNum = 1;           // 第一行的第一个数
            int stepRow = 1;               // 每行第一个数的增幅
            for(int i = 1; i <= N; i++){
                int row = rowBeginNum;     // 每行的第一个数
                int n = N - i + 1;         // 每行的数个数
                StringBuilder sb = new StringBuilder();
                int stepCol = i + 1;       // 每列的初始增幅
                int count = 0;
                while(count++ < n){
                    sb.append(row + " ");
                    row += stepCol;        // 更新本行的下一个数
                    stepCol ++;            // 更新每列数的增幅
                }
                rowBeginNum += stepRow;    // 更新下一行的第一个数
                stepRow ++;                // 更新每行第一个数的增幅
                System.out.println(sb.toString().trim());
            }
        }
    }
}
发表于 2021-03-22 16:28:15 回复(0)