3 Star 61 Fork 5

programmercarl / kamacoder-solutions

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
0038.填充矩阵I.md 11.17 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;
}
#include <iostream>
#include <vector>

using namespace std;

int n, m;

/**
 * 模拟整个向内环绕的填入过程
 * 参考资料:https://leetcode.cn/problems/spiral-matrix-ii/solutions/12594/spiral-matrix-ii-mo-ni-fa-she-ding-bian-jie-qing-x/
 * 只是多了个过程中的num判断
 */
void solve()
{
    vector<vector<int>> arr(n, vector<int>(m));
    int num = n * m;
    int left = 0, right = m - 1;
    int top = 0, bottom = n - 1;
    while (num)
    {
        for (int j = left; j <= right && num; j++) // left -> right
            arr[top][j] = num--;
        top++;
        for (int i = top; i <= bottom && num; i++) // top -> bottom
            arr[i][right] = num--;
        right--;
        for (int j = right; j >= left && num; j--) // right -> left
            arr[bottom][j] = num--;
        bottom--;
        for (int i = bottom; i >= top && num; i--) // bottom -> top
            arr[i][left] = num--;
        left++;
    }
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < m; ++j)
        {
            cout << arr[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]);
        }
    }
}
import java.util.*;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        helper(n, m);
        sc.close();
    }

    /**
     * 初始化一个 n×n 大小的矩阵 mat,然后模拟整个向内环绕的填入过程:
     * 
     * 定义当前左右上下边界 l,r,t,b,初始值 num = n * m,迭代终止值 tar = 1;
     * 当 num >= tar 时,始终按照 从左到右 从上到下 从右到左 从下到上 填入顺序循环,每次填入后:
     * 执行 num -= 1:得到下一个需要填入的数字;
     * 更新边界:例如从左到右填完后,上边界 t += 1,相当于上边界向内缩 1。
     * 使用num >= tar而不是l < r || t < b作为迭代条件,是为了解决当n为奇数时,矩阵中心数字无法在迭代过程中被填充的问题。
     * 最终返回 mat 即可。
     * 
     * 模拟整个向内环绕的填入过程
     * 参考资料:https://leetcode.cn/problems/spiral-matrix-ii/solutions/12594/spiral-matrix-ii-mo-ni-fa-she-ding-bian-jie-qing-x/
     * 只是多了个过程中的num判断
     * 
     */
    static void helper(int n, int m) {
        int[][] arr = new int[n][m];
        int num = n * m;
        int left = 0, right = m - 1;
        int top = 0, bottom = n - 1;
        while (num > 0) {
            for (int j = left; j <= right && num > 0; j++) // left -> right
                arr[top][j] = num--;
            top++;
            for (int i = top; i <= bottom && num > 0; i++) // top -> bottom
                arr[i][right] = num--;
            right--;
            for (int j = right; j >= left && num > 0; j--) // right -> left
                arr[bottom][j] = num--;
            bottom--;
            for (int i = bottom; i >= top && num > 0; i--) // bottom -> top
                arr[i][left] = num--;
            left++;
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                System.out.printf("%d ", arr[i][j]);
            }
            System.out.println();
        }
    }

}

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)
def spiralOrder(n, m):
    """
     模拟整个向内环绕的填入过程
     参考资料:https://leetcode.cn/problems/spiral-matrix-ii/solutions/12594/spiral-matrix-ii-mo-ni-fa-she-ding-bian-jie-qing-x/
     只是多了个过程中的num判断
    """
    matrix = [[0] * m for _ in range(n)]
    num = n * m
    left, right = 0, m - 1
    top, bottom = 0, n - 1

    while num > 0:
        for j in range(left, right + 1):
            if not num:
                break
            matrix[top][j] = num
            num -= 1
        top += 1
        for i in range(top, bottom + 1):
            if not num:
                break
            matrix[i][right] = num
            num -= 1
        right -= 1
        for j in range(right, left - 1, -1):
            if not num:
                break
            matrix[bottom][j] = num
            num -= 1
        bottom -= 1
        for i in range(bottom, top - 1, -1):
            if not num:
                break
            matrix[i][left] = num
            num -= 1
        left += 1

    return matrix


n, m = map(int, input().split())
matrix = spiralOrder(n, m)
for i in range(n):
    for j in range(m):
        print(matrix[i][j], end=" ")
    print()

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;
}
1
https://gitee.com/programmercarl/kamacoder-solutions.git
git@gitee.com:programmercarl/kamacoder-solutions.git
programmercarl
kamacoder-solutions
kamacoder-solutions
main

搜索帮助