LeetCode 树

树的代码


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

101. Symmetric Tree

Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).

For example, this binary tree [1,2,2,3,4,4,3] is symmetric:

    1
   / \
  2   2
 / \ / \
3  4 4  3
But the following [1,2,2,null,3,null,3] is not:
    1
   / \
  2   2
   \   \
   3    3

代码一 自己写的 5%

public boolean isSymmetric(TreeNode root) {
    if (root == null) return true;
    TreeNode t1;
    TreeNode t2;
    Stack<TreeNode> s1 = new Stack<TreeNode>();
    Stack<TreeNode> s2 = new Stack<TreeNode>();
    s1.push(root.left);
    s2.push(root.right);

    while (!(s1.isEmpty() || s2.isEmpty())) {
        t1 = s1.pop();
        t2 = s2.pop();
        if (t1 == null && t2 == null) continue;
        if (t1 == null && t2 != null || t1 != null && t2 == null) return false;
        if (t1.val == t2.val) {
            s1.push(t1.left);
            s1.push(t1.right);
            s2.push(t2.right);
            s2.push(t2.left);
        }else return false;
    }
    if (s1.isEmpty() && !s2.isEmpty() || s2.isEmpty() && !s1.isEmpty()) return false;       
    return true;
}

代码二 精简版

public boolean isSymmetric(TreeNode root) {
    Queue<TreeNode> q = new LinkedList<TreeNode>();
    if (root == null) return true;
    q.add(root.left);
    q.add(root.right);
    while (q.size() > 1) {
        TreeNode left = q.poll(), right = q.poll();
        if (left == null && right == null) continue;
        if (left == null ^ right == null) return false;
        if (left.val != right.val) return false;
        q.add(left.left);
        q.add(right.right);
        q.add(left.right);
        q.add(right.left);
    }
    return true;
}

代码三 递归

public boolean isSymmetric(TreeNode root) {
    return root==null || isSymmetricHelp(root.left, root.right);
}

private boolean isSymmetricHelp(TreeNode t1, TreeNode t2) {
    if (t1 == null || t2 == null) return t1 == t2;
    if (t1.val != t2.val) return false;
    return isSymmetricHelp(t1.left, t2.right) && isSymmetricHelp(t1.right, t2.left);
    }

104. Maximum Depth of Binary Tree

Given a binary tree, find its maximum depth.

The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.


代码一 自己写的

public int maxDepth(TreeNode root) {
    return bfs(root, 0);

}

int bfs(TreeNode node, int depth) {
    if (node == null) return depth;
    return Math.max(bfs(node.left, depth + 1), bfs(node.right, depth + 1));
}

代码二 精简版 16%
思维还是跟不上迭代的精髓,根本不需要一个变量去传递depth

public int maxDepth(TreeNode root) {
    if (root == null) {
        return 0;
    }
    return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
}

111. Minimum Depth of Binary Tree

Given a binary tree, find its minimum depth.

The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.


public int minDepth(TreeNode root) {
    if (root == null) return 0;
    int left = minDepth(root.left);
    int right = minDepth(root.right);
    return (left == 0 || right == 0) ? left + right + 1 : Math.min(left, right) + 1;
}

102. Binary Tree Level Order Traversal

Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level).

For example:
Given binary tree [3,9,20,null,null,15,7],
    3
   / \
  9  20
    /  \
   15   7
return its level order traversal as:
[
  [3],
  [9,20],
  [15,7]
]

public List<List<Integer>> levelOrder(TreeNode root) {
    List<List<Integer>> re=new LinkedList<List<Integer>>();
    if(root==null) return re;
    Queue<TreeNode> queue=new ArrayDeque<TreeNode>();
    queue.add(root);
    
    while(!queue.isEmpty()){
        int size=queue.size();
        List<Integer> list=new ArrayList<Integer>();
        for(int i=0;i<size;i++){
            TreeNode node=queue.poll();
            list.add(node.val);
            if(node.left!=null) queue.add(node.left);
            if(node.right!=null) queue.add(node.right);
        }
        re.add(list);
    }
    return re;
}

103. Binary Tree Zigzag Level Order Traversal

Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between).

For example:
Given binary tree [3,9,20,null,null,15,7],
    3
   / \
  9  20
    /  \
   15   7
return its zigzag level order traversal as:
[
  [3],
  [20,9],
  [15,7]
]

代码一 3%

public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
    List<List<Integer>> re = new LinkedList<List<Integer>>();
    if (root == null) return re;
    Stack<TreeNode> stack= new Stack<TreeNode>();
    Stack<TreeNode> next= new Stack<TreeNode>();
    stack.push(root);
    boolean flag = true;

    while (!stack.isEmpty()) {
        int size = stack.size();
        List<Integer> list = new ArrayList<Integer>();
        for (int i = 0; i < size; i++) {
            TreeNode node = stack.pop();
            list.add(node.val);
            if (flag) {
                if (node.left != null) next.push(node.left);
                if (node.right != null) next.push(node.right);
            } else {
                if (node.right != null) next.push(node.right);
                if (node.left != null) next.push(node.left);
            }
        }
        stack=next;
        next= new Stack<TreeNode>();
        flag = !flag;
        re.add(list);
    }
    return re;
}

代码二 40%
从左到右遍历就可以了,只是在做list的时候反向插入即可。

public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
    List<List<Integer>> re=new LinkedList<List<Integer>>();
    if(root==null) return re;
    Queue<TreeNode> queue=new ArrayDeque<TreeNode>();
    queue.add(root);
    boolean flag = true;
    
    while(!queue.isEmpty()){
        int size=queue.size();
        List<Integer> list=new ArrayList<Integer>();
        for(int i=0;i<size;i++){
            TreeNode node=queue.poll();
            if(flag) list.add(node.val);
            else list.add(0, node.val);
            if(node.left!=null) queue.add(node.left);
            if(node.right!=null) queue.add(node.right);
        }
        flag!=flag;
        re.add(list);
    }
    return re;
}

105. Construct Binary Tree from Preorder and Inorder Traversal

Given preorder and inorder traversal of a tree, construct the binary tree.

Note:
You may assume that duplicates do not exist in the tree.


代码一 75%
http://blog.csdn.net/crazy1235/article/details/51559645

public TreeNode buildTree(int[] preorder, int[] inorder) {
    return build(preorder, inorder, 0, 0, inorder.length - 1);
}

public TreeNode build(int[] preorder, int[] inorder, int preIndex, int startInIndex, int endInIndex) {
    if (startInIndex > endInIndex) return null;
    int index = getIndexInInorder(inorder, preorder[preIndex]);
    int LenL = index - startInIndex;
    int LenR = endInIndex - index;
    TreeNode node = new TreeNode(preorder[preIndex]);
    if (LenL > 0) node.left = build(preorder, inorder, preIndex + 1, startInIndex, index - 1);
    if (LenR > 0) node.right = build(preorder, inorder, preIndex + LenL + 1, index + 1, endInIndex);
    return node;

}

public int getIndexInInorder(int[] inorder, int val) {
    for (int i = 0; i < inorder.length; i++) {
        if (val == inorder[i]) {
            return i;
        }
    }
    return -1;
}

108. Convert Sorted Array to Binary Search Tree

Given an array where elements are sorted in ascending order, convert it to a height balanced BST.


代码一:递归

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

TreeNode build(int[] nums, int lo, int hi){
    if( lo > hi ) return null;
    int mid = ( lo + hi ) / 2;
    TreeNode node = new TreeNode( nums[mid] );
    node.left = build( nums, lo, mid-1 );
    node.right = build( nums, mid + 1, hi );
    return node;
}

代码二:非递归
public TreeNode sortedArrayToBST(int[] nums) {

        int len = nums.length;
        if ( len == 0 ) { return null; }
        
        // 0 as a placeholder
        TreeNode head = new TreeNode(0); 
        
        Deque<TreeNode> nodeStack       = new LinkedList<TreeNode>() {{ push(head);  }};
        Deque<Integer>  leftIndexStack  = new LinkedList<Integer>()  {{ push(0);     }};
        Deque<Integer>  rightIndexStack = new LinkedList<Integer>()  {{ push(len-1); }};
        
        while ( !nodeStack.isEmpty() ) {
            TreeNode currNode = nodeStack.pop();
            int left  = leftIndexStack.pop();
            int right = rightIndexStack.pop();
            int mid   = left + (right-left)/2; // avoid overflow
            currNode.val = nums[mid];
            if ( left <= mid-1 ) {
                currNode.left = new TreeNode(0);  
                nodeStack.push(currNode.left);
                leftIndexStack.push(left);
                rightIndexStack.push(mid-1);
            }
            if ( mid+1 <= right ) {
                currNode.right = new TreeNode(0);
                nodeStack.push(currNode.right);
                leftIndexStack.push(mid+1);
                rightIndexStack.push(right);
            }
        }
        return head;
    }

109. 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.
造树,和上面的区别是没办法通过索引直接获得了。


代码一 递归
自顶向上

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode sortedListToBST(ListNode head) {
        if (head==null) return null;
        ListNode slow=head;
        ListNode fast=head;
        ListNode prev=null;
        while(fast!=null && fast.next!=null){
            prev=slow;
            slow=slow.next;
            fast=fast.next.next;
        }
        
        TreeNode root=new TreeNode(slow.val);
        
        if(prev!=null){
            prev.next=null;
        }else
            head=null;
            
        root.left=sortedListToBST(head);
        root.right=sortedListToBST(slow.next);
        return root;
    }
}

代码二 递归
中序遍历(待探究) 自底向上
左结点,根,右结点

private ListNode node;

public TreeNode sortedListToBST(ListNode head) {
    if(head == null){
        return null;
    }
    
    int size = 0;
    ListNode runner = head;
    node = head;
    
    while(runner != null){
        runner = runner.next;
        size ++;
    }
    
    return inorderHelper(0, size - 1);
}

public TreeNode inorderHelper(int start, int end){
    if(start > end){
        return null;
    }
    int mid = start + (end - start) / 2;
    
    TreeNode left = inorderHelper(start, mid - 1);
    treenode.left = left;
    
    TreeNode treenode = new TreeNode(node.val);
    node = node.next;

    TreeNode right = inorderHelper(mid + 1, end);
    treenode.right = right;
    
    return treenode;
}

114. Flatten Binary Tree to Linked List

Given a binary tree, flatten it to a linked list in-place.

For example,
Given

         1
        / \
       2   5
      / \   \
     3   4   6
The flattened tree should look like:
   1
    \
     2
      \
       3
        \
         4
          \
           5
            \
             6

代码一 从左向右

  1. 如果当前结点为叶结点,则返回该结点
  2. 如果左子树不为空,给左子树排序,找到左子树的最右下点node,node.right=右子树,继续给右子树排序。
  3. 如果左子树为空。(有可能它是整个左子树的一部分),返回该左子树的最右下端。
public void flatten(TreeNode root) {
    if(root ==null) return;
    dfs(root);
}

TreeNode dfs(TreeNode root){
    if(root.left==null && root.right==null) return root;
    if(root.left==null) {
        return dfs(root.right);
    }
    
    TreeNode node=dfs(root.left);
    node.right=root.right;
    root.right=root.left;
    root.left=null;
    return dfs(root.right);
}

代码二 精简版
从右到左,从下到上

private TreeNode prev = null;

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

129. Sum Root to Leaf Numbers

Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number.

An example is the root-to-leaf path 1->2->3 which represents the number 123.

Find the total sum of all root-to-leaf numbers.

For example,

    1
   / \
  2   3
The root-to-leaf path 1->2 represents the number 12.
The root-to-leaf path 1->3 represents the number 13.

Return the sum = 12 + 13 = 25.

public int sumNumbers(TreeNode root) {
    return dfs(root,0);
}

int dfs(TreeNode node, int val){
    if(node==null) return 0;
    int sum=10*val+node.val;
    if(node.left==null && node.right==null) return sum;
    return dfs(node.left,sum)+dfs(node.right,sum);
    
}

112. Path Sum

Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum.

For example:
Given the below binary tree and sum = 22,
              5
             / \
            4   8
           /   / \
          11  13  4
         /  \      \
        7    2      1
return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22.    

代码一 自己写的
左右枝一片混乱
一直在犯同一个错误,如果左枝为空,并不能通过左枝来判断,因为左枝根本不是叶结点!!!,应该只看右枝; 同样地,如果右枝为空,只看左枝

public boolean dfs(TreeNode root, int sum) {
    if(root==null) return sum==0;
    if(root.left!=null ) {//如果左枝不为空
        boolean flag=dfs(root.left, sum-root.val); //看一眼
        if(flag) return true; //如果找到了直接返回
        else if (root.right!=null){//如果右枝不为空
            return dfs(root.right,sum-root.val); //返回右枝
        }else return false;//如果右枝为空,则根本不用看右枝了
            
    }
    return dfs(root.right, sum-root.val); //如果左枝为空,则看右枝
}


代码二 人家写的,如此简洁
我是到空了,再判断。
人家是在父结点判断即可。如果左右枝都为空,直接判断,不再往下走。
想法和Q129一样的,我自己傻掉了。再巩固,学习。

public boolean hasPathSum(TreeNode root, int sum) {
    if(root == null) return false;

    if(root.left == null && root.right == null && sum - root.val == 0) return true;

    return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val);
}


113. Path Sum II

Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum.

For example:
Given the below binary tree and sum = 22,
              5
             / \
            4   8
           /   / \
          11  13  4
         /  \    / \
        7    2  5   1
return
[
   [5,4,11,2],
   [5,8,4,5]
]

代码一 15%

public List<List<Integer>> pathSum(TreeNode root, int sum) {
    List<List<Integer>> re = new LinkedList<List<Integer>>();
    dfs(re,new ArrayList<Integer>(),root,sum);
    return re;
}

void dfs(List<List<Integer>> re,List<Integer> list, TreeNode node, int sum){
    if(node==null) return;
    int n=node.val;
    List<Integer> newList=new ArrayList<Integer>(list);
    newList.add(n);
    if(node.left==null && node.right==null){
        if(sum==n){
            re.add(newList);
        }
        else return;
    }
    
    dfs(re, newList,node.left,sum-n);
    dfs(re, newList,node.right,sum-n);
}

代码二 48%
微调整,不是每次重新创立新的list,而是在最后的时候remove就可以了

public List<List<Integer>> pathSum(TreeNode root, int sum) {
    List<List<Integer>> re = new LinkedList<List<Integer>>();
    dfs(re, new ArrayList<Integer>(), root, sum);
    return re;
}

void dfs(List<List<Integer>> re, List<Integer> list, TreeNode node, int sum) {
    if (node == null) return;
    int n = node.val;
    list.add(n);
    if (node.left == null && node.right == null && sum == n) {
        List<Integer> newList = new ArrayList<Integer>(list);
        re.add(newList);

    } else {
        dfs(re, list, node.left, sum - n);
        dfs(re, list, node.right, sum - n);
    }
    list.remove(list.size() - 1);
}

437. Path Sum III

You are given a binary tree in which each node contains an integer value.

Find the number of paths that sum to a given value.

The path does not need to start or end at the root or a leaf, but it must go downwards (traveling only from parent nodes to child nodes).

The tree has no more than 1,000 nodes and the values are in the range -1,000,000 to 1,000,000.

Example:

root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8

      10
     /  \
    5   -3
   / \    \
  3   2   11
 / \   \
3  -2   1

Return 3. The paths that sum to 8 are:

1.  5 -> 3
2.  5 -> 2 -> 1
3. -3 -> 11

代码一 3% 自己写的bullshit。 新建map太花时间了。我记录的是减法,实际记录加法就可以了。这样就不用每次新建map了。

int count=0;
public int pathSum(TreeNode root, int sum) {
    Map<Integer, Integer> map = new HashMap<Integer, Integer>();
    map.put(sum, 1);//这个写在哪里一开始没有想清楚
    dfs(root, map, sum);
    return count;
}

void dfs(TreeNode node, Map<Integer, Integer> map, int sum) {
    if (node == null) return;

    int cur = node.val;
    //不要在这里加,因为不好减
    if (map.containsKey(cur)) {
        count += map.get(cur);
    }

    if (node.left == null && node.right == null) return;
    Map<Integer, Integer> curMap = new HashMap<Integer, Integer>();

    for (int target : map.keySet()) {
        curMap.put(target - cur, map.get(target));
    }
    curMap.put(sum, curMap.getOrDefault(sum, 0)+1);//在这里加
    dfs(node.left,curMap,sum);
    dfs(node.right,curMap,sum);
    curMap.put(sum, curMap.get(sum)-1);//在这里减
}

代码二 68% 记录加法

public int pathSum(TreeNode root, int sum) {
    HashMap<Integer, Integer> preSum = new HashMap();
    preSum.put(0, 1);
    return helper(root, 0, sum, preSum);
}

public int helper(TreeNode root, int currSum, int target, HashMap<Integer, Integer> preSum) {
    if (root == null) return 0;

    currSum += root.val;
    int res = preSum.getOrDefault(currSum - target, 0);
    preSum.put(currSum, preSum.getOrDefault(currSum, 0) + 1);
    
    res += helper(root.left, currSum, target, preSum) + helper(root.right, currSum, target, preSum);
    preSum.put(currSum, preSum.get(currSum) - 1);
    return res;
}

代码三 46% 真正的迭代

public int pathSum(TreeNode root, int sum) {
    if (root == null) return 0;
    return pathSumFrom(root, sum) + pathSum(root.left, sum) + pathSum(root.right, sum);
    }
    
private int pathSumFrom(TreeNode node, int sum) {
    if (node == null) return 0;
    return (node.val == sum ? 1 : 0) 
        + pathSumFrom(node.left, sum - node.val) + pathSumFrom(node.right, sum - node.val);
    }

257. Binary Tree Paths

Given a binary tree, return all root-to-leaf paths.

For example, given the following binary tree:

   1
 /   \
2     3
 \
  5
All root-to-leaf paths are:

["1->2->5", "1->3"]

代码一 15%

public List<String> binaryTreePaths(TreeNode root) {
    List<String> re = new LinkedList<String>();
    if (root == null) return re;
    if (root.left == null & root.right == null) {
        re.add(String.valueOf(root.val));
        return re;
    }
    bfs(root.left, re, String.valueOf(root.val));
    bfs(root.right, re, String.valueOf(root.val));
    return re;
}

void bfs(TreeNode node, List<String> list, String s) {
    if (node == null) {
        return;
    }
    s += "->" + node.val;
    if (node.left == null && node.right == null) {
        list.add(s);
        return;
    }

    bfs(node.left, list, s);
    bfs(node.right, list, s);

}

代码二 3%

public List<String> binaryTreePaths(TreeNode root) {
    List<String> answer = new ArrayList<String>();
    if (root != null) searchBT(root, "", answer);
    return answer;
}
private void searchBT(TreeNode root, String path, List<String> answer) {
    if (root.left == null && root.right == null) answer.add(path + root.val);
    if (root.left != null) searchBT(root.left, path + root.val + "->", answer);
    if (root.right != null) searchBT(root.right, path + root.val + "->", answer);
}

116. Populating Next Right Pointers in Each Node

Given a binary tree

class 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

代码一 16% 不符合要求

public void connect(TreeLinkNode root) {
    if (root == null) return;
    Queue<TreeLinkNode> q = new LinkedList<TreeLinkNode>();
    q.offer(root);
    while (!q.isEmpty()) {
        Queue<TreeLinkNode> next = new LinkedList<TreeLinkNode>();
        int size = q.size();
        for (int i = 0; i < size; i++) {
            TreeLinkNode node = q.poll();
            node.next = q.peek();
            if (node.left != null) next.offer(node.left);
            if (node.right != null) next.offer(node.right);
        }
        q = next;
    }
}

代码二 29%

public void connect(TreeLinkNode root) {
    if (root == null) return;
    TreeLinkNode cur = root;
    TreeLinkNode nextLeftmost = null;

    while (cur.left != null) {//往下走
        nextLeftmost = cur.left; // save the start of next level
        while (cur != null) {//往右走
            cur.left.next = cur.right;
            cur.right.next = cur.next == null ? null : cur.next.left;
            cur = cur.next;
        }
        cur = nextLeftmost; // point to next level
    }
}

代码三 75%

public void connect(TreeLinkNode root) {
    if(root==null) return;    
    if(root.left!=null) {
        root.left.next=root.right;
        connect(root.left);
    }
    if(root.next!=null && root.right!=null){
        root.right.next=root.next.left;
    }  
    connect(root.right);
}

117. Populating Next Right Pointers in Each Node II

Follow up for problem "Populating Next Right Pointers in Each Node".

What if the given tree could be any binary tree? Would your previous solution still work?

Note:

You may only use constant extra space.

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

代码 50%

public void connect(TreeLinkNode root) {
    if (root == null) return;
    TreeLinkNode head = new TreeLinkNode(0);
    TreeLinkNode cur = head;

    while (root != null) {// 这个循环既是往右走,又是往下走
        if (root.left != null) {
            cur.next = root.left;// 神来之笔
            cur = cur.next;
        }
        if (root.right != null) {
            cur.next = root.right;
            cur = cur.next;
        }
        root = root.next;
        if (root == null) {
            root = head.next;
            cur = head;
            head.next = null;
        }
    }
}

129. Sum Root to Leaf Numbers

Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number.

An example is the root-to-leaf path 1->2->3 which represents the number 123.

Find the total sum of all root-to-leaf numbers.

For example,

    1
   / \
  2   3
The root-to-leaf path 1->2 represents the number 12.
The root-to-leaf path 1->3 represents the number 13.

Return the sum = 12 + 13 = 25.

代码一 递归59%

public int sumNumbers(TreeNode root) {
    return dfs(root,0);
}

int dfs(TreeNode node, int val){
    if(node==null) return 0;
    int sum=10*val+node.val;
    if(node.left==null && node.right==null) return sum;
    return dfs(node.left,sum)+dfs(node.right,sum);
    
}

440. K-th Smallest in Lexicographical Order

Given integers n and k, find the lexicographically k-th smallest integer in the range from 1 to n.

Note: 1 ≤ k ≤ n ≤ 109.

Example:

Input:
n: 13   k: 2

Output:
10

Explanation:
The lexicographical order is [1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9], so the second smallest number is 10.

分析
依次逐渐确定前缀,每次计算当前前缀下不超过n的个数,若个数超过k,则说明第k个数在当前前缀下,反之,则说明在当前前缀加1以后的前缀;

以first为前缀的数
[first, first+1]
[first10, (first+1)10]
[first100, (first+1)100]

另一种分析方法,这是一颗十叉树,前序遍历(然而不用真的遍历,只需要计算子树的大小即可)

public int findKthNumber(int n, int k) {  
    int ans=1;  
    for(k--;k>0;){  
        int count=0;  
        for(long first=ans,second=first+1;first<=n;first*=10,second*=10){  
            count+=Math.min(n+1,second)-first;  
        }  
        if(count<=k){  
            k-=count;  
            ans++;  
        }else{  
            k--;//减掉的是当前为前缀的那个数  
            ans*=10;//元素个数太多,需要减小,因此前缀变大  
        }  
    }  
    return ans;  
}  

自己更习惯用gap,其实是一样的,不过上面写的更精简一点
每次的形式都为[first, first+gap],每次循环跟新first和gap
[4, 4+1] ----> gap=1,first=4
[410, 410+10]----> gap=10, first=40
[4100, 4100+100]----> gap=100, first=400

public int findKthNumber(int n, int k) {
    long size = 1;
    int cur = 1;
    k--;

    while (k != 0) {
        size = getSize(cur, n);
        if (size > k) {
            cur = cur * 10;
            k--;
        } else {
            cur++;
            k -= size;
        }
    }
    return cur;
}

long getSize(long cur, long n){
    long count=0;
    long gap=1;
    while(cur<=n){
        count+=Math.min(gap, n-cur+1);
        gap*=10;
        cur*=10;
    }
    return count;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容