zoukankan      html  css  js  c++  java
  • 好!recover-binary-search-tree(难)& 两种好的空间O(n)解法 & 空间O(1)解法


    https://leetcode.com/mockinterview/session/result/xyc51it/

    https://leetcode.com/problems/recover-binary-search-tree/

    // 想到了Space O(N)的解法:方法是直接将BST放平,然后重新排序,然后比较一下就可以。
    // 原题中提到说,有 Space O(Constant)的方法,还要研究一下

    看了Discuss,也上网搜了一下,发现空间O(1)可以用 Morris遍历的方法。单独写了一篇博客,方法介绍如下:
    http://www.cnblogs.com/charlesblc/p/6013506.html

    下面是leetcode这道题目我的解答。没有使用O(1)空间复杂度,使用了O(n)空间复杂度。 还用到了Java里面 Arrays.sort方法,也需要注意toArray函数的参数。

    除了这种解法,还有一种,是我之前做的方法,也很好,通过两个数字记录可能出错的位置,很巧妙,在这个后面给出。

    package com.company;import java.util.*;
    
    class TreeNode {
            int val;
            TreeNode left;
            TreeNode right;
            TreeNode(int x) { val = x; }
    }
    
    class StkNode {
        TreeNode tn;
        int count;
        StkNode(TreeNode tn) {
            this.tn = tn;
            count = 0;
        }
    }
    
    class Solution {
    
        List<Integer> getArray(TreeNode root) {
    
            List<Integer> ret = new ArrayList<>();
            if (root.left != null) {
                ret.addAll(getArray(root.left));
            }
            ret.add(root.val);
            if (root.right != null) {
                ret.addAll(getArray(root.right));
            }
            return ret;
        }
    
        public void recoverTree(TreeNode root) {
    
            // Space O(N)的解法,想到了是直接将BST放平,然后重新排序,然后比较一下就可以。
    
            // 分情况, 左ok, 右ok, 1. 上ok, 2. 上不ok
            // 左不ok, 或者右不ok, 1. 上ok,
            // 想不清楚,先用直接的方法:
            if (root == null) {
                return;
            }
            List<Integer> ret = getArray(root);
            Integer[] sortRet= ret.toArray(new Integer[0]);
            Arrays.sort(sortRet);
    
            int[] change = new int[2];
            int[] index = new int[2];
            int ii = 0;
            for (int i=0; i<sortRet.length; i++) {
                //System.out.printf("old: %d, new: %d
    ", ret.get(i), sortRet[i]);
                if (ret.get(i) != sortRet[i]) {
                    index[ii] = i+1;
                    change[ii] = sortRet[i];
                    ii++;
                    if (ii >= 2) {
                        break;
                    }
                }
            }
            //System.out.printf("ii:%d
    ", ii);
    
            Stack<StkNode> stk = new Stack<>();
            int count = 0;
            int k = 0;
            StkNode stkRoot = new StkNode(root);
            stk.push(stkRoot);
            while (!stk.isEmpty()) {
                StkNode tmp = stk.pop();
                //System.out.printf("here: %d, %d, %d
    ", tmp.count, count, tmp.tn.val);
                if (tmp.count == 1) {
                    count++;
                    if (count == index[k]) {
                        //System.out.printf("here: %d
    ", count);
                        tmp.tn.val = change[k];
                        k++;
                        if (k>=2) {
                            return;
                        }
                    }
                    if (tmp.tn.right != null) {
                        StkNode newTmp = new StkNode(tmp.tn.right);
                        stk.push(newTmp);
                    }
                }
                else {
                    tmp.count++;
                    stk.push(tmp);
                    if (tmp.tn.left != null) {
                        StkNode newTmp = new StkNode(tmp.tn.left);
                        stk.push(newTmp);
                    }
                }
            }
    
        }
    }
    
    public class Main {
    
        public static void main(String[] args) {
            System.out.println("Hello!");
            Solution solution = new Solution();
    
            TreeNode root = new TreeNode(2);
            TreeNode root2 = new TreeNode(3);
            TreeNode root3 = new TreeNode(1);
            root.left = root2;
            root.right = root3;
            solution.recoverTree(root);
            System.out.printf("Get ret: 
    ");
            System.out.printf("Get ret1: %d
    ", root.left.val);
            System.out.printf("Get ret2: %d
    ", root.val);
            System.out.printf("Get ret3: %d
    ", root.right.val);
            System.out.println();
    
            /*Iterator<List<Integer>> iterator = ret.iterator();
            while (iterator.hasNext()) {
                Iterator iter = iterator.next().iterator();
                while (iter.hasNext()) {
                    System.out.printf("%d,", iter.next());
                }
                System.out.println();
            }*/
    
            System.out.println();
    
        }
    }

    下面我之前的解法,也很好,通过两个数字来记录可能的出错位置,并且在遍历的同时,更新这个位置。需要对出错的规律有深刻了解,比如在解法中,first_result位置就始终没有变过,因为一旦找到就可以不变,通过second_result位置的改变,就能满足条件:

    https://leetcode.com/problems/recover-binary-search-tree/
    
    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     * };
     */
    class Solution {
        stack < pair <TreeNode*, int> > stk;
    public:
        void recoverTree(TreeNode* root) {
            if (root == NULL) {
                return;
            }
            pair<TreeNode*, int> pr(root, 0);
            stk.push(pr);
            
            TreeNode * first_result = NULL;
            TreeNode * last_result = NULL;
            TreeNode* last = NULL;
            
            pair<TreeNode*, int> tmp;
            TreeNode* tn_tmp;
    
            while ( !stk.empty() ) {
                tmp = stk.top();
                stk.pop();
                
                if (tmp.second == 0) {
                    // left
                    tn_tmp = tmp.first;
                    pair<TreeNode*, int> tmp_cur(tn_tmp, 1);
                    stk.push(tmp_cur);
                        
                    if (tn_tmp->left != NULL) {
                        pair<TreeNode*, int> tmp_left(tn_tmp->left, 0);
                        stk.push(tmp_left);
                    }
                    
                }
                else {
                    // right
                    tn_tmp = tmp.first;
                    if (last != NULL && last->val > tn_tmp->val) {
                        // Found
                        if (first_result == NULL ) {
                            first_result = last;
                            last_result = tn_tmp;
                        }
                        else {
                            last_result = tn_tmp;
                            break;
                        }
                    }
                    last = tn_tmp;
                    
                    if (tn_tmp->right != NULL) {
                        pair<TreeNode*, int> tmp_pr(tn_tmp->right, 0);
                        stk.push(tmp_pr);
                    }
                    
                }
                
            }
            
            if (first_result != NULL && last_result != NULL) {
                int swap = first_result->val;
                first_result->val = last_result->val;
                last_result->val = swap;
            }
            return;
                    
        }
    
    };
  • 相关阅读:
    【Linux系列汇总】小白博主的嵌入式Linux实战快速进阶之路(持续更新)
    【matlab系列汇总】小白博主的matlab学习实战快速进阶之路(持续更新)
    【FreeRTOS学习01】CubeIDE快速整合FreeRTOS创建第一个任务
    STM32F767ZI NUCLEO144 基于CubeIDE快速开发入门指南
    【matlab 基础篇 01】快速开始第一个程序(详细图文+文末资源)
    Linux 通过终端命令行切换系统语言
    ubuntu 1604升级到ubuntu 1804无法忽视的细节问题(亲测有效)
    假如用王者荣耀的方式学习webpack
    小程序第三方框架对比 ( wepy / mpvue / taro )
    我所理解的前端
  • 原文地址:https://www.cnblogs.com/charlesblc/p/6013413.html
Copyright © 2011-2022 走看看