剑指offer04 最多方式实现二维数组中的查找 | 刷题打卡

411 阅读1分钟

题目描述

在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

示例

示例1:

现有矩阵 matrix 如下:

[
  [1,   4,  7, 11, 15],
  [2,   5,  8, 12, 19],
  [3,   6,  9, 16, 22],
  [10, 13, 14, 17, 24],
  [18, 21, 23, 26, 30]
]

给定 target = 5,返回 true。

给定 target = 20,返回 false。

  限制:

0 <= n <= 1000

0 <= m <= 1000

题目分析

根据题目可知:

  • 这是一个二维数组
  • 每一行的数组都是升序的
  • 每一列从上到下递增

解题思路

思路一:两重循环

这个都知道就不说了

思路二:数组扁平化

题目给的是个二维数组,那么我们是不是可以将二维数组变成一个一维数组呢,变成一维数组是不是就方便多了,直接一重循环搞定。

那么怎么让二维变成一维呢?这就需要知道数组扁平化了。实现数组扁平化的方式有很多种,比如数组自带的 flat()等等;

如果对数组扁平化有兴趣的,可以去看看 神三元大佬 写的 JS数组扁平化(flat)方法总结,里面有很多种实现数组扁平化的方法。

思路三: 双指针

没错哈,又又又是双指针。可能有人会好奇这怎么用双指针啊,其实仔细想想就知道了。

我们可以把数组每一行当做左指针,把每一行数组中的元素下标作为右指针。

  • 首先左指针当然是从 0 开始,右指针(也可从 0 开始)可从每一行数组最后的元素开始;
  • 左右指针有了之后,接下来就开始循环了;
  • 当左指针小于二维数组的长度且右指针大于等于 0 的时候,如果当前元素 == target,就返回true;如果当前元素 < target ,说明这一行数组中最大的值都比target小,那么就直接跳过该行,在下一行中找;如果当前数组的第一个值都比target大,说明该行的数组都比 target 大,并且后面的所有数组都比target大,所以直接跳出循环;

可能这样说的话不是那么的直观,那就看下面的代码。

AC代码

思路一: 两重循环

var findNumberIn2DArray = function(matrix, target) {
   for(let i = 0; i < matrix.length; i++) {
        let arr = matrix[i]
        for(let j = 0; j < arr.length; j++) {
            // if(arr[arr.length - 1] < target || arr[j] > target)
            //     break
            if(arr[j] == target) {
                return true
            }
        }
    }
    return false
}

思路二:数组扁平化

  1. 利用数组自带的方法
var findNumberIn2DArray = function(matrix, target) {
    return matrix.flat(Infinity).includes(target)
}
  1. 利用some实现数组扁平化
var findNumberIn2DArray = function(matrix, target) {
    let arr = flatten(matrix)
    if(arr.some(item => item == target)) {
        return true
    }
    return false
}

function flatten(matrix) {
    while(matrix.some((item) => Array.isArray(item))) {
        matrix = [].concat(...matrix)
    }
    return matrix
}

思路三: 双指针

var findNumberIn2DArray = function(matrix, target) {
    if(matrix.length < 1  || matrix[0].length < 1) return false
    let row = 0;
    let col = matrix[row].length - 1
    while(row < matrix.length && col >= 0) {
        if(matrix[row][col] == target) {
            return true
        } else if(matrix[row][col] < target) { 
        // 如果当前数组最大的都比target小
        // 就直接遍历下一行数组
            row++
        } else if(matrix[row][0] > target){ 
        // 如果当前数组第一个值都比target大,
        // 后面所有的数组都比target大,所以直接结束循环
            break
        } else {
            col--
        }
    }
    return false
};

总结

好难受啊,那种想说又说不出来的感觉。。。如果感兴趣的话,不妨去看看我其他文章,感觉还是有点意思的。

继续努力,hxdm!!!

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情