《剑指offter》第十九题(js)

第十九题 顺时针打印矩阵

题目描述

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

思路一

顺时针打印,也就是按这个顺序: 从左到右 → 从上到下 → 从右到左 → 从下到上 ,再接着下一轮的这个顺序。每一边都有一个起点和终点,而每一轮的相同边的起点和终点是有规律的。我们用四个变量控制它们的位置。

function printMatrix(matrix)
{
    // write code here
    // 行数和列数
    var row = matrix.length;
    var column = matrix[0].length;
    if (row === 0 || column === 0) return false;
    var newMatrix = [];
    // 四个位置控制位
    var top = left = 0, right = column - 1, bottom = row - 1;
    while (top <= bottom && left <= right ){
        // 从左到右
        for (var i = left; i <= right; i++) {
            newMatrix.push(matrix[top][i]);
        }
        // 从上到下 要注意该列的第一个数已经被上一轮遍历了,所以这一轮从top+1开始
        for (var i = top + 1; i <= bottom; i++) {
            newMatrix.push(matrix[i][right]);
        }
        // 从右到左 第一个数同理,同时还要考虑只有一行的情况,否则会重复输出这一行
        if (top != bottom) {
            for (var i = right - 1; i >= left; i--) {
                newMatrix.push(matrix[bottom][i]);
            }
        }
        // 从下到上 第一个数、最后一个数同理,且还有考虑只有一列的情况
        if (left != right) {
            for (var i = bottom - 1; i > top; i--) {
                newMatrix.push(matrix[i][top]);
            }
        }
        // 改变位置控制位,以判断是否需要进行下一轮
        top++; left++; right--; bottom--; 
    }
    return newMatrix;
}

运行时间:13ms,占用内存:5344k

思路二

和思路一差不多的想法,但不用四个控制位,而是根据圈数来定起点

function printMatrix(matrix)
{
    // write code here
    var row = matrix.length;
    var column = matrix[0].length;
    if (row === 0 || column === 0) return false;
    var newMatrix = [],i,j;
    // 圈数
    var circle = Math.floor(((row <= column ? row : column) - 1 ) / 2 )+ 1;
    for (i = 0; i < circle; i++) {
        // 从左到右 
        for (j = i; j < column - i; j++) {
            newMatrix.push(matrix[i][j]);
        }
        // 从上到下
        for (j = i+1; j < row-i; j++) {
            newMatrix.push(matrix[j][column-1-i]);
        }
        // 从右到左
        for (j = column-2-i; (j >= i)&&(row-1-i != i); j--) {
            newMatrix.push(matrix[row-1-i][j]);
        }
        // 从下到上
        for (j = row-2-i; (j > i)&&(column-1-i != i); j--) {
            newMatrix.push(matrix[j][i]);
        }
    }
    return newMatrix;
}

运行时间:12ms,占用内存:5420k

Q1:圈数的计算
-  2 \* 2:1 圈; 2 / 2 = 1
-  3 \* 3:2 圈; 3 / 2 = 1.5
-  4 \* 4:2 圈; 4 / 2 = 2
-  5 \* 5:3 圈; 5 / 2 = 2.5
-  6 \* 6:3 圈; 6 / 2 = 3
-  ...

也就是说,2、3向下取整能取到相同的整数(4、5,6、7同理),但圈数相同的是 3、4,那么我们将 3、4 减一再向下取整,就能得到相同的整数啦,这个整数和它们的圈数差了 1 ,所以要给它加回去。由于矩阵不一定行列相同,我们取得两者间的较小值来计算。那么,圈数就是: Math.floor(((row <= column ? row : column) - 1 ) / 2 )+ 1;

Q2:从右到左为什么 j = column-2-i

row 为行数,column 为列数,所以右下的那个值是 matrix[row-1][column-1],记得要减 1 呀。那么从右到左:

  1. 第 1 圈:i = 0;起点位置在 matrix[row-1][column-2],为什么是 - 2 ,因为前面那个数已经被上一轮遍历了好吧。
  2. 第 2 圈:i = 1;起点位置在 matrix[row-1-i][column-2-1]
  3. 第 n 圈:i = n-1; 起点位置在 matrix[row-1-(n-1)][column-2-n]

其他边的情况也是一样的,就是要记得减去已经被上一边遍历的数,再结合与圈数的关系,即可得到答案。

Q3:row-1-i != i 和 column-1-i != i 什么意思

跟思路一一样,就是要考虑矩阵只有一列或者一行的情况,否则会出现平行的边重复读(比如从左到右已经读过,从右到左会重复读)。当只有一行时,也就是上边和下边重合,根据圈数 i ,上边为 i ,下边为 row - 1 - i,一列的情况同理。

好绕…多想几遍就好了QAQ

在前端开发的面试中,通常会涉及以下几个方面的问: 1. 前端基础知识:这是面试的重点部分,包括HTML、CSS和JavaScript的基础知识。面试官可能会问你关于标签语义化、盒模型、浮动、定位、继承、闭包等概念和原理。 2. 编程:面试官可能会给你一些编程,用来考察你的编码能力和解决问的能力。这些目可能涉及算法、数据结构、字符串处理等方面的知识。在回答问时,你可以通过举例、伪代码或具体的编程语言来展示你的解决思路。 3. 项目经验:面试官可能会询问你在大学期间参与的前端项目经验。他们会关注你在项目中承担的角色、所使用的技术栈、遇到的挑战以及你是如何解决问的。 4. 职业规划和跳槽原因:面试官还可能会问你关于你的职业规划和跳槽原因。他们想了解你对前端发展的看法,以及你是否有长期发展的计划。 总的来说,在前端开发的面试中,除了基础知识和编程能力,也会注重沟通能力和项目经验。因此,在准备面试时,除了复习基础知识和做一些编程外,还要思考自己的项目经验,并准备好相关的问答案。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [大学生前端,毕业面试知道这几点,offter拿到手软](https://blog.youkuaiyun.com/weixin_56815481/article/details/116306202)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值