Skip to content

Latest commit

 

History

History
280 lines (261 loc) · 6.66 KB

0038.填充矩阵I.md

File metadata and controls

280 lines (261 loc) · 6.66 KB

38.填充矩阵I

题目链接

C++

// 与java题解思路一致
// 直接模拟
#include <bits/stdc++.h>
using namespace std;

int n, m;

void solve() {
    vector<vector<int>> res(n,vector<int>(m,0));
    int xHead = 0; // x的最小值
    int yHead = 0; // y的最小值
    int xEnd = n - 1; // x的最大值
    int yEnd = m - 1; // y的最大值
    int x = 0;
    int y = 0;
    int cur = n * m; // 当前应赋的值
    while(cur > 0)
    {
        // 从左到右
        for(; y <= yEnd; ++y)
        {
            // 以下的(cur > 0)都是为了防止把负数赋值上去
            if(cur > 0) 
            res[x][y] = cur--;
        }
        // 以下改变x, y的操作都是为了把越界的或者跑到已经赋值的位置的x, y拉回来
        --y;
        ++x;
        // 从上到下
        for(; x <= xEnd; ++x)
        {
            if(cur > 0)
            res[x][y] = cur--;
        }
        --x;
        --y;
        // 从右到左
        for(; y >= yHead; --y)
        {
            if(cur > 0)
            res[x][y] = cur--;
        }
        ++y;
        --x;
        // 从下到上, 但是不能覆盖已经赋值的部分
        // 所以到xhead为止
        for(; x > xHead; --x)
        {
            if(cur > 0)
            res[x][y]=cur--;
        }
        ++x;
        ++y;
        // 跑完一圈,范围缩紧
        xHead++;
        yHead++;
        yEnd--;
        xEnd--;
    }
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < m; ++j) {
            cout << res[i][j] << " ";
        }
        cout << endl;
    }
}

int main()
{
    while(cin >> n >> m) {
        solve();
    }
    return 0;
}

Java

/**
 * 思路:从内到外模拟过于麻烦,观察到可以从左上角到右下角进行逆向打印。
*/

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int m = scanner.nextInt();
        int[][] array = generate2dArray2(n, m);
        print2dArray(array, n, m);
    }
    public static int[][] generate2dArray2(int n, int m) {
        int stop = 0;  // 结束条件
        int count = n * m;  // 用于填充二维数组的元素
        int startX = 0;
        int startY = 0;  
        int endX = n;
        int endY = m;
        int[][] twoDArray = new int[n][m];
        while (count > stop) {
            int i = startX;
            int j = startY;
            while (count > stop && j < endY) {  // 从左上到右上
                twoDArray[i][j++] = count--;
            }
            // 每 行/列 循环结束后,调整下一 行/列 开始遍历的位置。
            i++;
            j--;
            while (count > stop && i < endX) {  // 从右上到右下
                twoDArray[i++][j] = count--;
            }
            i--;
            j--;
            while (count > stop && j >= startY) { // 从右下到左下
                twoDArray[i][j--] = count--;
            }
            i--;
            j++;
            // i > startX 的原因是不能覆盖掉本次循环第一个填充的元素
            while (count > stop && i > startX) {  // 从左下到左上
                twoDArray[i--][j] = count--;
            }
            // 调整下一圈开始循环的位置
            startX++;
            startY++;
            endX--;
            endY--;
        }
        return twoDArray;
    }
    public static void print2dArray(int[][] twoDArray, int n, int m) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m - 1; j++) {
                System.out.printf("%d ", twoDArray[i][j]);
            }
            System.out.printf("%d\n", twoDArray[i][m - 1]);
        }
    }
}

Python

# 思路:这个很明显就是考察代码随想录中螺旋数组那道题,但是做过很久了,已经忘记当时怎么设置的边界条件了,于是使用了下面一种类似于手动dfs的策略,先向右,再向下,再向左, 再向上的策略
def get_new(res, m, n):
    current = m*n
    x = 0
    y = 0
    count = 0
    while current > 0:
        while y<n and res[x][y] == 0 and current > 0:
            res[x][y] = current
            current -= 1
            y += 1
        y -= 1
        x += 1
        while x<m and res[x][y] == 0 and current > 0:
            res[x][y] = current
            current -= 1
            x += 1
        x -= 1
        y -= 1
        while y>-1 and res[x][y] == 0 and current > 0:
            res[x][y] = current
            current -= 1
            y -= 1
        y += 1
        x -= 1
        while x>-1 and res[x][y] == 0 and current > 0:
            res[x][y] = current
            current -= 1
            x -= 1
        x += 1
        y += 1

m, n = map(int, input().split(" "))
if m == 1 and n == 1:
     print(1)
else:
    res = [[0 for _ in range(n)] for _ in range(m)]
    get_new(res, m, n)
    for i in res:
        tmp = ""
        for k in range(len(i)):
            if k!=len(i)-1:
                tmp += str(i[k]) + " "
            else:
                 tmp += str(i[k])
        print(tmp)

Go

JS

C

#include<stdio.h>
#include<stdlib.h>

int n, m;

void solve() {
    int res[100][100];
    int xHead = 0; // x的最小值
    int yHead = 0; // y的最小值
    int xEnd = n - 1; // x的最大值
    int yEnd = m - 1; // y的最大值
    int x = 0;
    int y = 0;
    int cur = n * m; // 当前应赋的值
    while(cur > 0)
    {
        // 从左到右
        for(; y <= yEnd; ++y)
        {
            // 以下的(cur > 0)都是为了防止把负数赋值上去
            if(cur > 0) 
            res[x][y] = cur--;
        }
        // 以下改变x, y的操作都是为了把越界的或者跑到已经赋值的位置的x, y拉回来
        --y;
        ++x;
        // 从上到下
        for(; x <= xEnd; ++x)
        {
            if(cur > 0)
            res[x][y] = cur--;
        }
        --x;
        --y;
        // 从右到左
        for(; y >= yHead; --y)
        {
            if(cur > 0)
            res[x][y] = cur--;
        }
        ++y;
        --x;
        // 从下到上, 但是不能覆盖已经赋值的部分
        // 所以到xhead为止
        for(; x > xHead; --x)
        {
            if(cur > 0)
            res[x][y]=cur--;
        }
        ++x;
        ++y;
        // 跑完一圈,范围缩紧
        xHead++;
        yHead++;
        yEnd--;
        xEnd--;
    }
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < m; ++j) {
            printf("%d ", res[i][j]);
        }
        printf("\n");
    }
}

int main()
{
    while(scanf("%d %d", &n, &m) != EOF) {
        solve();
    }
    return 0;
}