《每周一道算法题》(四)验证二叉搜索树

题目

https://leetcode-cn.com/problems/validate-binary-search-tree/

给定一个二叉树,判断其是否是一个有效的二叉搜索树。

假设一个二叉搜索树具有如下特征:

  • 节点的左子树只包含小于当前节点的数。
  • 节点的右子树只包含大于当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。
  • 如果是一棵空树,也算是有效的二叉搜索树
示例 1:
输入:
    2
   / \
  1   3
输出: true
示例 2:
输入:
    5
   / \
  1   4
     / \
    3   6
输出: false
解释: 输入为: [5,1,4,null,null,3,6]。
根节点的值为 5 ,但是其右子节点值为 4 。
一 错误的思路

遍历二叉树的所有节点,看看所有的节点是否满足

node.left.val < node.val < node.right.val ? 该判断方法存在漏洞

注:这种思路是存在漏洞的

  • 下面是两个反例,虽然每个节点都符合,但是不是一棵二叉搜索树
image.png
二 思路1 - 中序遍历
  • 2.1 二叉搜索树的一个特性:中序遍历(左-root-右),结果必然是升序的。

  • 2.2 2.2利用上述特性就可以判断是否为一棵二叉搜索树了

  • 核心代码 - 迭代调用

/// 思路一 中序遍历 迭代
- (BOOL)isValidBST:(TreeNode *)root {
    if (root == nil) {
        return true;
    }
    
    Stack *stack = [[Stack alloc] init];
    while (true) {
        while (root != nil) {
            [stack push:root];
            root = root.left;
        }
        if ([stack isEmpty]) {
            break;
        }
        root = [stack pop];
        
        if (self.last != NSNotFound && root.value <= self.last) {
            return false;
        }
        self.last = root.value;
        root = root.right;
    }
    return true;
}

时间复杂度:O(n),空间复杂度(n)

  • 核心代码 - 递归调用
/// 递归调用
- (BOOL)isValidBST2:(TreeNode *)root {
    if (root == nil) {
        return true;
    }
    
    if (![self isValidBST:root.left]) {
        return false;
    }
    
    if (self.last != NSNotFound && root.value <= self.last) {
        return false;
    }
    self.last = root.value;
    
    if (![self isValidBST:root.right]) {
        return false;
    }
    
    return true;
}

时间复杂度:O(n),空间复杂度O(n)

三 思路2 - 遍历的同时指定范围
  • 3.1 在遍历每一个节点的时候,都指定它的上界和下界,节点的取值范围是(下界到上界)

  • 3.2 这种思想适合所有的遍历方式(前序,中序,后序,层序)

3.1 遍历的同时指定范围 - 前序遍历
// 思路2 - 遍历的同时指定范围 - 前序遍历
- (BOOL)isValidBST3:(TreeNode *)root {
    return [self isValidBST3:root min:NSNotFound max:NSNotFound];
}

- (BOOL)isValidBST3:(TreeNode *)node min:(NSInteger)min max:(NSInteger)max {
    if (node == nil) {
        return true;
    }
    if (min != NSNotFound && node.value <= min) {
        return false;
    }
    if (max != NSNotFound && node.value >= max ) {
        return false;
    }
    // 遍历左边节点
    if (![self isValidBST3:node.left min:min max:node.value]) {
        return false;
    }
    
    // 遍历右边节点
    if (![self isValidBST3:node.right min:node.value max:max]) {
        return false;
    }
    
    return true;
}

时间复杂度:O(n),空间复杂度O(n)

3.2 遍历的同时指定范围 - 层序遍历
  • 核心代码
/// 思路2 - 遍历的同时指定范围 - 层序遍历
- (BOOL)isValidBST4:(TreeNode *)root {
    if (root == nil) {
        return true;
    }
    [self offer:root min:NSNotFound max:NSNotFound];
    
    // 循环遍历
    while (!self.nodes.isEmpty) {
        TreeNode *node = [self.nodes deQueue];
        NSInteger min = [[self.mins objectAtIndex:0] integerValue];
        
        if (min != NSNotFound && node.value <= min) {
            return false;
        }
        
        NSInteger max = [[self.maxs objectAtIndex:0] integerValue];
        if (max != NSNotFound && node.value >= max) {
            return false;
        }
        
        // 遍历左右子树
        [self offer:node.left min:min max:node.value];
        [self offer:node.right min:node.value max:max];
    }
    return true;
}

- (void)offer:(TreeNode *)node min:(NSInteger)min max:(NSInteger)max {
    if (node == nil) {
        return;
    }
    [self.nodes enQueue:node];
    [self.mins addObject:@(min)];
    [self.maxs addObject:@(max)];
}
  • 运行结果
2019-11-20 23:14:34.143954+0800 03_CheckIsValidBSTTree[2364:98870] result4 = 1

本文参考MJ老师的每周一道算法题,非常感谢


项目链接地址 - 04_CheckIsValidBSTTree


每周一道算法题 - 笔记


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,919评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,567评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,316评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,294评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,318评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,245评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,120评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,964评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,376评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,592评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,764评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,460评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,070评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,697评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,846评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,819评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,665评论 2 354

推荐阅读更多精彩内容