好!recover-binary-search-tree(难)& 两种好的空间O(n)解法 & 空间O解法

Posted 笨鸟居士的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了好!recover-binary-search-tree(难)& 两种好的空间O(n)解法 & 空间O解法相关的知识,希望对你有一定的参考价值。


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\\n", 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\\n", 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\\n", tmp.count, count, tmp.tn.val);
            if (tmp.count == 1) {
                count++;
                if (count == index[k]) {
                    //System.out.printf("here: %d\\n", 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: \\n");
        System.out.printf("Get ret1: %d\\n", root.left.val);
        System.out.printf("Get ret2: %d\\n", root.val);
        System.out.printf("Get ret3: %d\\n", 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;
                
    }

};

 

以上是关于好!recover-binary-search-tree(难)& 两种好的空间O(n)解法 & 空间O解法的主要内容,如果未能解决你的问题,请参考以下文章

线路板要镀金好还是镀镍好呢???大家给点意见得无,紧急求助..

学习ui设计是自学好?还是参加培训好?

RPC好,还是RESTful好?

怎样才算是好程序员?关于好程序员与好代码的杂谈

jQuery 根据日期的不同时间段,做问候语:中午好,下午好,早上好

在Linux操作系统下用Shell编写一时钟提示程序,要求能显示出上午好、中午好、下午好!!急待高手解决