LeetCode 剑指 Offer 04. 二维数组中的查找 、 剑指 Offer 07. 重建二叉树

二维数组中的查找

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

限制:

  • 0 <= n <= 1000
  • 0 <= m <= 1000

样例

在这里插入图片描述

题目链接
https://leetcode.cn/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/

解题思路

其实想做出来的话暴力很容易就可以搞定,但是细心的同学肯定会注意到,这是一个横竖都排好序的结构,那我们可以考虑如何进行二分。

经过一波观察,可以发现左下角的这个数,很神奇,只要是往上走,就会变小,只要是往右走,就变变大,其实这就是我们的突破点。具体看代码啦,聪明的你肯定很容易就可以想到🤣🤣。

代码(Java和C++)

Java代码

class Solution {
    public boolean findNumberIn2DArray(int[][] matrix, int target) {
        int n = matrix.length;
        if (n == 0) return false;
        int m = matrix[0].length;
        int i = n - 1, j = 0;
        while (i > -1 && j < m ) {
            if (matrix[i][j] > target) {
                i--;
            } else if (matrix[i][j] < target ) {
                j++;
            } else {
                return true;
            }
        }
        return false;
    }
}

在这里插入图片描述

C++代码

class Solution {
public:
    bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
        int n = matrix.size();
        if (n == 0) return false;
        int m = matrix[0].size();
        int i = n - 1, j = 0;
        while ( i > -1 && j < m) {
            if (matrix[i][j] > target) {
                i--;
            } else if (matrix[i][j] < target) {
                j++;
            } else {
                return true;
            }
        }
        return false;
    }
};

在这里插入图片描述

重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

0 <= 节点个数 <= 5000

样例
在这里插入图片描述

题目链接
https://leetcode.cn/problems/zhong-jian-er-cha-shu-lcof/

前置知识

二叉树前序遍历的顺序为:

  • 先遍历根节点;
  • 随后递归地遍历左子树;
  • 最后递归地遍历右子树。

二叉树中序遍历的顺序为:

  • 先递归地遍历左子树;
  • 随后遍历根节点;
  • 最后递归地遍历右子树。

解题思路

这题我用的是递归的思路,每个节点都有两个孩子节点(有的为NULL),所以我只需要一直去找当前节点的孩子节点就可以了。

步骤:

  1. 构造当前节点
  2. 找到当前节点在中序遍历数组中的位置
  3. 将数组分为两份,以第二步找到的位置为界限,左边这份为左子树的,右边为右子树的
  4. 判断是否有左子树或者右子树,将子树的边界和下标进行递归

代码

class Solution {

    int[] preorder;

    int[] inorder;

    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if (preorder.length == 0) {
            return null;
        }
        this.preorder = preorder;
        this.inorder = inorder;
        return dfs(0, 0, preorder.length);
    }

    // 返回当前字数的根节点
    // index:当前节点所在先序遍历数组中的位置
    // left:所在中序遍历的左边界,right为右边界,这里为左开右闭区间
    public TreeNode dfs(int index, int left, int right) {
		int now = preorder[index];
		TreeNode node = new TreeNode(preorder[index]);
		int inorderIndex = 0;
		// 找到当前节点在中序遍历数组中的位置
		for (int i = left; i < right; i++) {
			if (now == inorder[i]) {
				inorderIndex = i;
				break;
			}
		}
		if (inorderIndex > left) {
			// 左节点在先序遍历一定位于当前节点的下一个,故index + 1即可
			node.left = dfs(index + 1, left, inorderIndex);
		}
		if (inorderIndex < right - 1) {
			// 右节点的偏移位数,要根据左子树中共有多少个节点来判断
			int dev = inorderIndex - left + 1;
			node.right = dfs(index + dev, inorderIndex + 1, right);
		}
		// 返回当前节点
		return node;
    }
}

在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿杆.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值