LeetCode Elementary Algorithm Training-Tree(完了)

前書き

戻る:LeetCodeプライマリアルゴリズムトレーニングにリンクしたリスト

次へ:LeetCode Elementary Algorithm Training-Sorting and Searching

もともとは初心者レベル、中級レベル、企業のインタビューアルゴリズムから始めたかったのですが、質問をブラッシングする目的で質問をブラッシングするのではなく、多くのトレーニングの後、質問をブラッシングするプロセスで一種のアルゴリズム思考を実行するため、基本的には基本から始めることを選択しましたアルゴリズムへの独自の洞察を形成し、アルゴリズムへの感度を養い、問題を確認し、問題を解決するための青写真が脳に現れる可能性があり、最初から徐々に自信を築く。これは、背後にある複雑なアルゴリズムにも当てはまる問題解決のアイデアの基盤を築きます。

LeetCodeプライマリアルゴリズムの概要

独自のアルゴリズム的思考もトレーニングしたい場合は、私に参加して、基本的なアルゴリズムから始めて、アルゴリズムの旅を開始することもできます:基本的なアルゴリズム

あなた自身の考えの一部:質問を読んだ後、答えを見るだけではなく、質問を暗唱して、実装されたアルゴリズムの記憶力が強くないようにしてください。自分の考えを持っている必要があり、最初にIDEAに書かないでください。 leetCodeが提供するホワイトボードにそれを書き、最後にIDEAに置いて問題がないか確認して、基本的なAPIの使用法と習熟度を統合します。もう1つのポイントは、大胆なことで、試行錯誤による面接のコストではありません。低、私たちのアイデアをコードに組み込んでみてください

スペースの問題により、ブログには例とユーザー自身の問題解決の回答のみがリストされています。詳細については、トピックをクリックして直接表示できます。

二分木の最大深度

バイナリツリーを指定して、その最大深度を見つけます。
二分木の深さは、ルートノードから最も遠いリーフノードまでの最長パス上のノード数です。

説明:葉ノードは、子ノードのないノードを指します。

例:
バイナリツリー[3,9,20、null、null、15,7]が与えられた場合、

 	3
   / \
  9  20
    /  \
   15   7

最大深度を返します3。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int maxDepth(TreeNode root) {
        if(root == null) return 0;
        int max = 1;
        int leftMax = maxDepth(root.left);
        int rightMax = maxDepth(root.right);
    
        return max + Math.max(leftMax,rightMax);
    }
}

39/39テストケースに
合格ステータス:合格
実行時間:0ミリ秒
メモリ消費量:40 MB

この再帰は、ノードがnullの場合は0を返し、ノードがnullでない場合のデフォルト値は1です。次に、左と右の子ノードのどちらか大きい方の方に戻り、max +(leftMaxとrightMaxの最大値)などを繰り返します。

バイナリ検索ツリーを確認する

バイナリツリーを指定して、それが有効なバイナリ検索ツリーであるかどうかを判断します。
二分探索木が次の特性を持っていると仮定し
ます。ノードの左側のサブツリーには、現在のノードより小さい数値のみが含まれます。
ノードの右側のサブツリーには、現在のノードより大きい数値のみが含まれています。
すべての左と右のサブツリーは、それ自体がバイナリ検索ツリーでなければなりません。

例1:
入力:

    2
   / \
  1   3

出力:true

例2:
入力:

    5
   / \
  1   4
     / \
    3   6

出力:false
説明:入力は[5,1,4、null、null、3,6]です。
ルートノードの値は5ですが、その右側の子ノードの値は4です。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
   public boolean help(TreeNode root,Integer min,Integer max){
      if(root == null) return true;
        int val = root.val;
        
        //保证了root的左子树的最大值小于root的值并且root的右子树的最小值大于root的值;
        if(min != null && min >= val) return false;//只要root的左子树中有值大于root,就不是BFT;
        if(max != null && max <= val) return false;//只要root的右子树中有值小于root,就不是BFT;
        
        //保证了root的所有左子树和右子树都是BFT;
        if(!help(root.left,min,val)) return false;//在遍历左子树的时候只关心最大值,所以将val赋给max;
        if(!help(root.right,val,max)) return false;//在遍历右子树的时候只关心最小值,所以将val赋给min;
    
        return true;
    }
    public boolean isValidBST(TreeNode root) {
        if(root == null ) return true;
        return help(root,null,null);
    }
 
}

75/75のテストケースに
合格ステータス:合格
実行時間:0ミリ秒
メモリ消費量:39.7 MB

対称二分木

バイナリツリーを指定して、それがミラー対称であるかどうかを確認します。
たとえば、バイナリツリー[1,2,2,3,4,4,3]は対称です。

    1
   / \
  2   2
 / \ / \
3  4 4  3

ただし、次の[1,2,2、null、3、null、3]はミラー対称ではありません。

    1
   / \
  2   2
   \   \
   3    3

上級:
再帰と反復を使用してこの問題を解決できますか?

再帰:2つのポインタがそれぞれ左側と右側に移動します。左側のポインタと右側のポインタが比較され、実際には、右側のサブツリーの左側のノードと右側のノードと左側のサブツリーが比較されます。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    
    public boolean isSymmetric(TreeNode root) {
        if(root == null) return true;
        return check(root.left,root.right);
    }
    
    private boolean check(TreeNode p,TreeNode q) {
        if(p == null && q == null) return true;
         if(p == null || q == null) return false;
        return p.val == q.val && check(p.left,q.right) && check(p.right,q.left);
    }
}

195/195テストケースに
合格ステータス:合格
実行時間:0ミリ秒
メモリ消費量:37.7 MB

反復:1対1で継続的にキューに追加し、比較を取り出します。これは、左側と右側のサブツリーの比較でもあります。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    
    public boolean isSymmetric(TreeNode root) {
        if(root == null) return true;
    
        return check(root.left,root.right);
    }
    
    public boolean check(TreeNode u, TreeNode v) {
        Queue<TreeNode> q = new LinkedList<TreeNode>();
        q.offer(u);
        q.offer(v);
        while (!q.isEmpty()) {
            u = q.poll();
            v = q.poll();
            if (u == null && v == null) {
                continue;
            }
            if ((u == null || v == null) || (u.val != v.val)) {
                return false;
            }

            q.offer(u.left);
            q.offer(v.right);

            q.offer(u.right);
            q.offer(v.left);
        }
        return true;
    }
}

195/195テストケースに
合格ステータス:合格
実行時間:1 ms
メモリ消費:39.3 MB

バイナリツリーのシーケンストラバーサル

バイナリツリーを取得し、それを順番にたどって得られたノード値を返してください。(つまり、左から右に、レイヤーごとにすべてのノードにアクセスします)。

例:
二分木:[3,9,20、null、null、15,7]、

    3
   / \
  9  20
    /  \
   15   7

レベルトラバーサルの結果を返します。

[
  [3],
  [9,20],
  [15,7]
]

深さ優先

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {

    List<List<Integer>> lists = new ArrayList<>();

    public List<List<Integer>> levelOrder(TreeNode root) {
        if(root == null) return lists;
        help(root,0);
        return lists;
    }

    private void help(TreeNode node,int level){
   		//只有列表大小为当前level时新创建一个数组塞进去,这样其他的相同层级就避免多创建
        if(lists.size() == level) {
            lists.add(new ArrayList<Integer>());
        }
        //把node值添加到当前层级数组中
        lists.get(level).add(node.val);
        
		//递归root左侧下一个层级
        if(node.left != null){
            help(node.left,level + 1);
        }
        //递归root右侧侧下一个层级
         if(node.right != null){
             help(node.right,level + 1);
         }
    }
}

34/34のテストケースに
合格ステータス:合格
実行時間:1 ms
メモリ消費量:40.3 MB

この深さ優先戦略と幅優先アプローチは、理解するのが少し複雑です。

幅が最初

public List<List<Integer>> levelOrder(TreeNode root) {
           //思路 二叉树的层序遍历 通用思路为使用 队列,利用队列先进先出特点保存每一行的结点,遍历之后出队
           //时间复杂度 空间复杂度 O(n)
           List<List<Integer>> res = new ArrayList<>();

           if(root == null){
              return res;
           }
           //存储没层结点队列
           Queue<TreeNode> queueNodes = new LinkedList<>();
           //把当前根节点加入队列
           queueNodes.add(root);

           //遍历队列节点
           while(!queueNodes.isEmpty()){
               //获取当前层级有多少个节点
               int count = queueNodes.size();
               //保存当前遍历节点值得 list
               List<Integer> temp = new ArrayList<>();
               //根据队列中的数据 遍历获取节点值
               for (int i = 0; i < count; i++) {
                   //当前节点是否有左右子节点
                   if(queueNodes.peek().left !=null){
                     queueNodes.offer(queueNodes.peek().left);
                   }
                   if(queueNodes.peek().right !=null){
                    queueNodes.offer(queueNodes.peek().right);
                  }
                  //保存当前节点行元素值数组 并从队列中删除
                  temp.add(queueNodes.poll().val);
               }
               //保存每一层节点数组
               res.add(temp);
           }

            return res;
    }
}
順序付けられた配列を二分探索木に変換する

昇順の順序付けられた配列を、高度にバランスのとれた二分探索木に変換します。

この質問では、高度にバランスのとれた二分木は、二分木の各ノードの左右のサブツリー間の高さの差の絶対値が1を超えないことを意味します。

例:

順序付けられた配列がある場合:[-10、-3,0,5,9]、

考えられる答えの1つは、[0、-3,9、-10、null、5]です。これは、次の高度にバランスのとれた二分探索木を表すことができます。

      0
     / \
   -3   9
   /   /
 -10  5

アイデアは最初は正しかったが、場所と境界を見つけるのは正しくなかった。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        return  help(nums,0,nums.length - 1);
    }

    private TreeNode help(int[] nums,int left,int right){
        
        if(left > right) return null;

        int mid = (left + right)/2;

        TreeNode root = new TreeNode(nums[mid]);

        root.left = help(nums,left,mid - 1);
        root.right = help(nums,mid + 1, right);
        return root;
    }
}

32/32のテストケースに
合格ステータス:合格
実行時間:0ミリ秒
メモリ消費量:39.6 MB

おすすめ

転載: blog.csdn.net/u011148116/article/details/107212165