美文网首页
刷题简报-2019-12-24

刷题简报-2019-12-24

作者: 三分归元币 | 来源:发表于2019-12-24 18:14 被阅读0次

本周已经进入倦怠期,题目完成总量120,需要温故知新了。

通过先序遍历和后序遍历构造二叉树

889. Construct Binary Tree from Preorder and Postorder Traversal
这道题的核心思路,是找到根节点,然后根据根节点将数组分成左子树与右子树。
拿官方的例子来解释,pre = [1,2,4,5,3,6,7], post = [4,5,2,6,7,3,1]
先序遍历的顺序:根节点-左子节点-右子节点
后续遍历的顺序:左子节点-右子节点-根节点
第一步,拿到先序遍历的第一个元素1,为根节点,随后它的左子节点应为是第二个元素2;通过左子节点将后续遍历的数组分割为[4,5,2],[6,7,3];因为1已经被使用了,所以应该剔除。
第二步,pre=[2,4,5],post=[4,5,2],进一步拿出根节点2,然后分为[4,5],[4,5];
第三步,分割为单个元素,创建节点并返回;这样就构造了一颗子树了。

t1.png
/**
 * 889. Construct Binary Tree from Preorder and Postorder Traversal
 *
 * Return any binary tree that matches the given preorder and postorder traversals.
 *
 * Values in the traversals pre and post are distinct positive integers.
 *
 * Input: pre = [1,2,4,5,3,6,7], post = [4,5,2,6,7,3,1]
 * Output: [1,2,3,4,5,6,7]
 *
 * pre:root-left-right
 * post:left-right-root
 */
public class ConstructBinaryTreefromPreorderandPostorderTraversal {
    public void test(){
        int[] pre1 = {1,2,4,5,3,6,7};
        int[] post1 = {4,5,2,6,7,3,1};
        TreeNode.preorderTraversal(constructFromPrePost(pre1,post1));
    }
    public TreeNode constructFromPrePost(int[] pre, int[] post) {
        return buildTree(pre,0,pre.length-1,post,0,post.length-1);
    }
    TreeNode buildTree(int[] pre,int pStart,int pEnd,int[] post,int poStart,int poEnd){
        if(pStart > pEnd || poStart > poEnd){
            return null;
        }
        TreeNode node = new TreeNode(pre[pStart]);
        if(pStart == pEnd){
            return node;
        }
        int nextIndex = poStart;
        for(;nextIndex<=poEnd;nextIndex++){
            if(pre[pStart+1] == post[nextIndex]){
                break;
            }
        }

        node.left = buildTree(pre,pStart+1,pStart+1+nextIndex-poStart,post,poStart,nextIndex);
        node.right = buildTree(pre,pStart+1+nextIndex-poStart +1,pEnd,post,nextIndex+1,poEnd-1);
        return node;
    }
}

通过中序遍历以及后序遍历生成树

106. Construct Binary Tree from Inorder and Postorder Traversal
这个题的思路也是如上题,计算左子树与右子树的区间
中序:左-根-右
后序:左-右-根
in = {9,3,15,20,7};post = {9,15,7,20,3};
后序遍历最后一个元素必然是树的根节点,找到3,并在中序遍历中将数组分为[9],[15,20,7]两部分,进而再对两部分进行递归。

/**
 * 106. Construct Binary Tree from Inorder and Postorder Traversal
 *
 * Given inorder and postorder traversal of a tree, construct the binary tree.
 *
 * Note:
 * You may assume that duplicates do not exist in the tree.
 * @author ctk
 */
public class ConstructBinaryTreefromInorderandPostorderTraversal {
    public void test(){
        //   3
        //   / \
        //  9  20
        //    /  \
        //   15   7
        int[] inorder1 = {9,3,15,20,7};
        int[] postorder1 = {9,15,7,20,3};
        traversal(buildTree(inorder1,postorder1));
    }
    private void traversal(TreeNode tree){
        if(tree == null){
            return;
        }
        System.out.println(tree.val);
        traversal(tree.left);
        traversal(tree.right);
    }
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        Map<Integer,Integer> valueIndex = new HashMap<>();
        for(int i=0;i<inorder.length;i++){
            valueIndex.put(inorder[i],i);
        }
        return buildTree(inorder,0,inorder.length-1,postorder,0,postorder.length-1,valueIndex);
    }
    private TreeNode buildTree(int[] inorder, int inStart, int inEnd, int[] postorder, int postStart, int postEnd,Map<Integer,Integer> valueIndex){
        if(inStart > inEnd || postStart > postEnd){
            return null;
        }
        TreeNode root = new TreeNode(postorder[postEnd]);
        int rootIndex = valueIndex.get(postorder[postEnd]);
        root.left = buildTree(inorder,inStart,rootIndex-1,postorder,postStart,postStart+(rootIndex-inStart-1),valueIndex);
        root.right = buildTree(inorder,rootIndex+1,inEnd,postorder,postStart+rootIndex-inStart,postEnd-1,valueIndex);
        return root;
    }
}

通过中序遍历以及前序遍历生成树

105. Construct Binary Tree from Preorder and Inorder Traversal

中序:左-根-右
前序:根-左-右
通过根节点,将数组分割进而递归

/**
 * 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.
 * Created by MacBook on 2019/12/1.
 */
public class ConstructBinaryTreefromPreorderandInorder {
    public void test(){
        /*
                3
               / \
              9  20
                /  \
               15   7
        */
        int[] pre1 = {3,9,20,15,7};
        int[] in1 = {9,3,15,20,7};
        TreeNode.preorderTraversal(buildTree(pre1,in1));
    }
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        return buildTree(preorder,0,preorder.length-1,inorder,0,inorder.length-1);
    }
    public TreeNode buildTree(int[] preorder,int preStart,int preEnd,int[] inorder,int inStart,int inEnd){

        if(inStart > inEnd || preStart > preEnd){
            return null;
        }
        int rootVal = preorder[preStart];
        int rootIndex = inStart;
        while (rootIndex < inEnd){
            if(inorder[rootIndex] == rootVal) {
                break;
            }
            rootIndex ++;
        }
        TreeNode root = new TreeNode(rootVal);
        root.left = buildTree(preorder,preStart+1,preStart+rootIndex-inStart,inorder,inStart,rootIndex-1);
        root.right = buildTree(preorder,preStart+rootIndex-inStart+1,preEnd,inorder,rootIndex+1,inEnd);
        return root;
    }
}


计算元素之后小于它的总数

315. Count of Smaller Numbers After Self
题目主旨是给定一个数组a[],计算出每一个元素之后出现的小于它的元素的个数。
使用树状数组统计,首先对原数组拷贝一份并排序,然后用BIT记录它对应位置的个数,每次遍历到的元素就能统计到小于它的元素的个数。

image.png image.png

因此,我们使用从后往前遍历的方式,每次访问元素先获取BIT中比它还小的个数统计,然后再讲其更新到BIT中。

/**
 * 315. Count of Smaller Numbers After Self
 *
 * You are given an integer array nums and you have to return a new counts array.
 * The counts array has the property where counts[i] is the number of smaller elements to the right of nums[i].
 */
public class CountofSmallerNumbersAfterSelf {
    public void test(){
        int[] nums1 = {5,2,6,1};
        System.out.println(countSmaller(nums1));
        int[] nums2 = {-1,-1};
        System.out.println(countSmaller(nums2));
    }

    /**
     * Binary Indeed Tree
     */
    public List<Integer> countSmaller(int[] nums) {
        List<Integer> result = new ArrayList<>(nums.length);
        int[] copy = new int[nums.length];
        for(int i=0;i<nums.length;i++){
            copy[i] = nums[i];
        }

        int[] bit = new int[nums.length + 1];

        Arrays.sort(copy);

        for(int i=nums.length-1;i>=0;i--){
            result.add(query(bit,binarySearch(copy,nums[i])-1));
            update(bit,binarySearch(copy,nums[i]),1);
        }
        Collections.reverse(result);
        return result;
    }
    int lowBit(int i){
        return i & (-i);
    }
    int query(int[] bit,int x){
        int res = 0;
        int i = x + 1;
        while (i>0){
            res += bit[i];
            i -= lowBit(i);
        }
        return res;
    }
    void update(int[] bit,int x,int value){
        int i = x + 1;
        while (i<bit.length){
            bit[i] += value;
            i += lowBit(i);
        }
    }
    int binarySearch(int[] sortArray,int value){
        int n = sortArray.length;
        int l = 0;
        int r = n - 1;
        while (l < r){
            int mid = l + (r - l) / 2;
            if(sortArray[mid] > value){
                r = mid - 1;
            }else if(sortArray[mid] < value){
                l = mid + 1;
            }else {
                return mid;
            }
        }
        return sortArray[l] == value ? l : -1;
    }
}


相关文章

  • 刷题简报-2019-12-24

    本周已经进入倦怠期,题目完成总量120,需要温故知新了。 通过先序遍历和后序遍历构造二叉树 889. Constr...

  • 刷题简报-2019-12-15

    本周稍有懈怠,未能做到日均一题,日后可能更为严峻,不过精选几题作为总结。 编辑距离 坐标 72. Edit Dis...

  • 刷题刷题

    时间紧迫,任务繁重,又有疫情影响,搞的人心惶惶,一时间复习得不安宁,又舍不得摆烂。 在焦灼、惶恐的情绪中,紧张急迫...

  • 2022-09-16

    刷题,刷题还是刷题

  • 2018-07-16

    刷题,祸害的何止是教育? 报班,刷题;买练习册,刷题;家教,刷题;跟不上,刷题;学得好,刷题;为了抢跑,刷题;为了...

  • 刷题啊刷题

    因为月底又要考试,所以最近几天一直在刷题。按说是看了书再看视频再刷题效果比较好才是。可是来不及了啊。 上次考试,就...

  • 刷题啊刷题

    刷题啊刷题 因为11月中旬要举行期中考试,所以最近几天,学校精心组织,一直在刷题。按说是看了书再看PPT课件或教师...

  • 2020-02-01关于刷题的几个建议

    算法刷题 针对性刷题,刻意练习。刻意刷题!不是麻木刷题!刷题前一定要先看书,清楚明白为什么要刷这些题,这些题刷完能...

  • 刷题

    清早起来刷题 吃饭也在刷题 上厕所也在刷题 中午也在刷题 下午也在刷题 晚上也在刷题 一天到晚都在刷题 考试马上到...

  • 程序猿刷题网站你知道吗?

    Coderbyte 刷题网LeetCode 刷题网Stack Overflow 刷题网

网友评论

      本文标题:刷题简报-2019-12-24

      本文链接:https://www.haomeiwen.com/subject/doufoctx.html