leetcode——樹

114. 二叉樹展開爲鏈表

題目

例如,給定二叉樹

    1
   / \
  2   5
 / \   \
3   4   6
將其展開爲:

1
 \
  2
   \
    3
     \
      4
       \
        5
         \
          6

--------------------------------------------------------------------------------------------------

思路:此題形成的鏈表實際上二叉樹的先序遍歷,因此我們可以將先序遍歷倒過來(右左中),通過一個變量pre來記錄之前遍歷的節點,將當前節點的右指針指向pre,並把當前節點的左指針置爲空。

    TreeNode pre = null;
    public void flatten(TreeNode root) {
        if(root == null)    return;
        flatten(root.right);
        flatten(root.left);
        root.right = pre;
        root.left = null;
        pre = root;
    }

 


208. 實現 Trie (前綴樹)

題目:實現一個 Trie (前綴樹),包含 insertsearch, 和 startsWith 這三個操作。所有輸入的字符串都是非空且小寫

示例:

Trie trie = new Trie();

trie.insert("apple");
trie.search("apple");   // 返回 true
trie.search("app");     // 返回 false
trie.startsWith("app"); // 返回 true
trie.insert("app");   
trie.search("app");     // 返回 true

--------------------------------------------------------------------------------------------------

思路:前綴樹又稱字典樹,它的節點值通常是字符,其中的根節點是空字符。下圖中的數保存了8個鍵。

(1)定義節點結構

每個節點都有一個節點數組,用於存儲子節點。數組長度爲26,即所有小寫字母的總數。此外isEnd變量用於標記是否已到頭。

containsChar() 方法判斷字典樹中是否有字符ch,判斷標準是當前節點的數組是否有該字符。getNode()方法用於得到當前節點的對應字符參數的下一節點。put()方法用於將參數字符加入當前節點的數組中。

 class TrieNode {
      private TrieNode[] treePath;
      private final int len = 26;
      private boolean isEnd;
      
      public TrieNode() {
        treePath = new TrieNode[len];
      }
      public boolean containsChar(char ch) {
        return treePath[ch - 'a'] != null;
      }

      public TrieNode getNode(char ch) {
        return treePath[ch - 'a'];
      }

      public void put(char ch, TrieNode node) {
        treePath[ch - 'a'] = node;
      }
      public void setEnd() {
        isEnd = true;
      }
      public boolean isEnd() {
          return isEnd;
      }
    }

(2)添加字符串

假設加入字符串leet,則其字段數大致結構爲:

    public void insert(String word) {
        TrieNode node = root;
        char[] words = word.toCharArray();
        for(char ch : words) {
          if(!node.containsChar(ch)) {
            node.put(ch, new TrieNode());
          }
            node = node.getNode(ch);
        }
        node.setEnd();
    }

(3)查找字符串

通過字符串的一個個字符來向下遍歷字典樹,若有遇到某一節點的節點數組中不存在該字符,則返回錯誤;若遍歷到樹的根節點則返回正確,

    public TrieNode searchNode(String word) {
          TrieNode node = root;
          char[] words = word.toCharArray();
          for(char ch : words) {
            if(node.containsChar(ch)) {
              node = node.getNode(ch);
            }else {
              return null;
            }
          }
          return node;
      }

    /** Returns if the word is in the trie. */
    public boolean search(String word) {
      TrieNode node = searchNode(word);
      return node != null && node.isEnd();
    }

(4)以某一字符串爲開頭

    public boolean startsWith(String prefix) {
      TrieNode node = searchNode(prefix);
      return node != null;
    }

 


236. 二叉樹的最近公共祖先

題目:給定一個二叉樹, 找到該樹中兩個指定節點的最近公共祖先(一個節點也可以是它自己的祖先)。

例如,給定如下二叉樹:  root = [3,5,1,6,2,0,8,null,null,7,4]

示例 1:

輸入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
輸出: 3
解釋: 節點 5 和節點 1 的最近公共祖先是節點 3。
示例 2:

輸入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
輸出: 5
解釋: 節點 5 和節點 4 的最近公共祖先是節點 5。

--------------------------------------------------------------------------------------------------

思路:遞歸判斷:

  1. 若遍歷到的節點root爲空,則返回空;若root是p, q節點中的一個,則root就是它們的最近公共祖先。
  2. 若以上情況都不滿足,則跑到root的左右子節點判斷:若左右節點都返回空,則說明不存在p, q節點;若兩者都非空,則root是它們的最近公共祖先。若有一個非空,一個爲空,則那個非空的就是最近公共祖先。
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
      if(root == null || p == root || q == root) {
        return root;
      }
      TreeNode leftRes = lowestCommonAncestor(root.left, p, q);
      TreeNode rightRes = lowestCommonAncestor(root.right, p, q);
      if(leftRes == null && rightRes == null) {
        return null;
      }else if(leftRes != null && rightRes != null) {
        return root;
      }else {
        return leftRes == null ? rightRes : leftRes;
      }
      
    }

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章