LeetCode解题报告——Convert Sorted List to Binary Search Tree & Populating Next Right Pointers in Each Node & Word Ladder

1. Convert Sorted List to Binary Search Tree

Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.

For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1.

Example:

Given the sorted linked list: [-10,-3,0,5,9],

One possible answer is: [0,-3,9,-10,null,5], which represents the following height balanced BST:

      0
     / \
   -3   9
   /   /
 -10  5

Idea: For tree-related problems, we should first think of using recursion to solve it. If we find the middle, then the left subtree is the left subtree, and the right subtree is the right subtree, so we can recurse. The difficulty of this process is to find the middle linked list node, and to determine the starting range of the left and right subtrees each time the recursion occurs.

public class Solution {
    
    public TreeNode sortedListToBST(ListNode head) {
        if(head==null) return null;
        return toBST(head,null);
    }
    
    public TreeNode toBST(ListNode head, ListNode tail) { //The start of the left and right subtrees at each recursion, that is, the head and tail to be taken in the linked list 
        ListNode slow = head;
        ListNode fast = head;
        if(head==tail) return null;

        while (fast!=tail&&fast.next!= tail) {  //This is very interesting, fast moves two steps back each time, slow moves one step back each time, when fast reaches the penultimate node, slow just goes to the linked list middle part 
            fast = fast.next.next;
            slow = slow.next;
        }
        TreeNode thead = new TreeNode(slow.val); //Take the current intermediate node as the root node 
        thead.left = toBST(head,slow);  //Make a left subtree recursion 
        thead.right for the left linked list part of the current root node = toBST(slow.next,tail);   //Recursive return thead for the right subtree of the right linked list part of the current root node
         ;
    }
}

 

2. Populating Next Right Pointers in Each Node

Given a binary tree

    struct TreeLinkNode {
      TreeLinkNode *left;
      TreeLinkNode *right;
      TreeLinkNode *next;
    }

Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL.

Initially, all next pointers are set to NULL.

Note:

  • You may only use constant extra space.
  • You may assume that it is a perfect binary tree (ie, all leaves are at the same level, and every parent has two children).

For example,
Given the following perfect binary tree,

         1
       /  \
      2    3
     / \  / \
    4  5  6  7

After calling your function, the tree should look like:

         1 -> NULL
       /  \
      2 -> 3 -> NULL
     / \  / \
    4->5->6->7 -> NULL

Idea: I originally wanted to solve the problem through the convenience of layers, because I haven't done the algorithm problem for a long time, and suddenly I am still a little handicapped. I still read the discussion. There is a relatively simple solution, which is from top to bottom. For the current node cur, if it has a left child node, then according to the meaning of the title, it must have a right child node, then The next of the left child node points to the right child of the parent node. For this right child, if the next of its parent is not null, then the next of the right child should point to the next of its parent. The left child of the node. This will cycle from top to bottom.

public class Solution {
    public void connect(TreeLinkNode root) {
        TreeLinkNode level_start=root;
        while(level_start!=null){
            TreeLinkNode cur=level_start;
            while(cur!=null){
                if(cur.left!=null) cur.left.next=cur.right;
                if(cur.right!=null && cur.next!=null) cur.right.next=cur.next.left;
                
                cur=cur.next;
            }
            level_start=level_start.left;
        }
    }
}

The above algorithm is only valid when the binary tree is full, so how to solve the problem if the binary tree is any binary tree? for example

Given the following binary tree,

         1
       /  \
      2    3
     / \    \
    4   5    7

After calling your function, the tree should look like:

         1 -> NULL
       /  \
      2 -> 3 -> NULL
     / \    \
    4-> 5 -> 7 -> NULL

The solution is similar to the above problem, but it is still traversed layer by layer from left to right. For the node cur on the current level, considering the situation of its left and right child nodes, this process requires a prev to record what the previous node in the previous link is. , and the first node of the next layer for subsequent convenience.

public class Solution {
    
    //based on level order traversal
    public void connect(TreeLinkNode root) {

        TreeLinkNode head = null; //head of the next level
        TreeLinkNode prev = null; //the leading node on the next level
        TreeLinkNode cur = root;  //current node of current level

        while (cur != null) {
            
            while (cur != null) { //iterate on the current level
                //left child
                if (cur.left != null) {
                    if (prev != null) {
                        prev.next = cur.left; // If the left child node is not empty and the previous node is not empty, link directly, if the previous node is empty, since cur is convenient from left to right, the first one in the lower layer is not empty The child node is the first node of the lower layer 
                    } else {
                        head = cur.left;
                    }
                    prev = cur.left;   // Set the linked node as the prev node
                }
                //right child
                if (cur.right != null) {
                    if (prev != null) {
                        prev.next = cur.right;
                    } else {
                        head = cur.right;
                    }
                    prev = cur.right;
                }
                //move to next node
                cur = cur.next;
            }
            
            //move to next level
            cur = head;
            head = null;
            prev = null;
        }
        
    }
}

 

3. Word Ladder

Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord, such that:

  1. Only one letter can be changed at a time.
  2. Each transformed word must exist in the word list. Note that beginWord is not a transformed word.

Note:

  • Return 0 if there is no such transformation sequence.
  • All words have the same length.
  • All words contain only lowercase alphabetic characters.
  • You may assume no duplicates in the word list.
  • You may assume beginWord and endWord are non-empty and are not the same.

Example 1:

Input:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]

Output: 5

Explanation: As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.

Example 2:

Input:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]

Output: 0

Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.

思路:可以使用BFS来解决这题,对于beginWord,和它临接的边是它在wordList中所能transform到的单词,这是第一层,那么第二层就是第一层所能transform到的所有单词,所以是个典型的BFS问题。试了下一般的BFS,如果从开始单词一层层的往外找,结果会超时,所以采取两端同时BFS,即从beginWord和endWord两端开始BFS。

public class Solution {

    public int ladderLength(String beginWord, String endWord, Set<String> wordList) {
        if(!wordList.contains(endWord)) return 0;
        Set<String> beginSet = new HashSet<String>(), endSet = new HashSet<String>();

        int len = 1;
        HashSet<String> visited = new HashSet<String>();

        beginSet.add(beginWord);
        endSet.add(endWord);
    //    如果从beginWord到endWord的BFS或者从endWord到beginWord的BFS过程中有哪一层是空的话,则表明beginWord到endWord走不通
        while (!beginSet.isEmpty() && !endSet.isEmpty()) {
            if (beginSet.size() > endSet.size()) {    // BFS从beginWord到endWord,交换BFS方向是为了减少计算次数
                Set<String> set = beginSet;
                beginSet = endSet;
                endSet = set;    // 这里交换beginSet和endSet来实现BFS方向的改变
            }

            Set<String> temp = new HashSet<String>();
            for (String word : beginSet) {
                char[] chs = word.toCharArray();

                for (int i = 0; i < chs.length; i++) {
                    for (char c = 'a'; c <= 'z'; c++) {
                        char old = chs[i];
                        chs[i] = c;
                        String target = String.valueOf(chs);

                        if (endSet.contains(target)) {     //     两端BFS过程中,如果相遇则直接返回BFS深度,还要加1才是题目要求的
                            return len + 1;
                        }

                        if (!visited.contains(target) && wordList.contains(target)) {  
                            temp.add(target);
                            visited.add(target);
                        }
                        chs[i] = old;
                    }
                }
            }

            beginSet = temp;
            len++;
        }

        return 0;
    }
}

 

这里的 two-end BFS,以及BFS中改变遍历的方向以减少计算量还是很有意思的。 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324692524&siteId=291194637