剑指offer——Day20 分治算法(中等)

Day20 2023.2.2 分治算法(中等)

剑指offer 07. 重建二叉树

自己实现

之前FDS做过这个题目,现在有一点忘了,就在网上找了资料来看。

正确的思路是前序遍历的第一个数字就是树的根,然后在中序遍历去找这个根,然后把左子树和右子树分开(得到左子树的节点数L),然后再找前序遍历除了根以外的前L个数就对应左子树;右子树同理。然后递归去构建即可。

代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        return recur(preorder,inorder);
    }
    TreeNode* recur(vector<int>& pre, vector<int> in){
        if(in.size()==0)return NULL;
        vector<int> pre_l,in_l;
        vector<int> pre_r,in_r;
        int j=0;
        while(in[j]!=pre[0]){
            in_l.push_back(in[j]);
            j++;
            pre_l.push_back(pre[j]);
        }
        j++;
        while(j<in.size()){
            pre_r.push_back(pre[j]);
            in_r.push_back(in[j]);
            j++;
        }
        TreeNode* root=new TreeNode(pre[0]);
        root->left=recur(pre_l,in_l);
        root->right=recur(pre_r,in_r);
        return root;
    }
};

代码表现

太慢了 看看题解

题解

自己实现的时候是直接传入了遍历序列的数组,这个可能会造成很大的开销。

题解使用了传入每个部分的下标的方法,类似双指针。

有空的时候可以试着实现一下

代码表现

hint

  • 利用分治的思想,先找到根节点,然后对中序进行划分左右部分,再根据左右部分的节点数找前序遍历的左右部分,然后就进行构建

剑指offer 16.数值的整数次方

自己实现

自己实现就是一直用乘法乘以本身来实现分治思想,然后用一个整型变量来统计目前的次方数,但是这样做超出了时间限制,无法通过,因此查看题解。

题解

题解比较有特点的一种理解方法是用二进制来理解,将n转化为二进制展开,可以发现当n的某一bit为1时就需要乘,并且在乘完之后n向右移位一位,就代表做了一半。这个思路挺不错的。

代码如下:

class Solution {
    public double myPow(double x, int n) {
        if(x == 0) return 0;
        long b = n;
        double res = 1.0;
        if(b < 0) {
            x = 1 / x;
            b = -b;
        }
        while(b > 0) {
            if((b & 1) == 1) res *= x;
            x *= x;
            b >>= 1;
        }
        return res;
    }
}

代码表现

hint

  • 二进制也能用来体现分治思想,好思路

剑指offer33. 二叉搜索树的后序遍历序列

自己实现

云里雾里呀……不知道怎么判断一个后序遍历序列是不是某棵二叉树的后序遍历结构。直接看题解了

题解

哦没有认真审题,题目说了这是一棵二叉搜索树

就是把后序遍历的左右部分分出来,因为这是一棵二叉搜索、树,所以左子树部分肯定都比右子树部分的值要小。

理解的不是很透彻,可以后面再来复习一下。当然还有另外一种单调栈的解法

详见K神题解

代码如下:

class Solution {
public:
    bool verifyPostorder(vector<int>& postorder) {
        return recur(postorder, 0, postorder.size() - 1);
    }
    bool recur(vector<int>& postorder, int i, int j) {
        if(i >= j) return true;
        int p = i;
        while(postorder[p] < postorder[j]) p++;
        int m = p;
        while(postorder[p] > postorder[j]) p++;
        return p == j && recur(postorder, i, m - 1) && recur(postorder, m, j - 1);
    }
};

代码表现

hint

  • 认真审题,然后想条件所给的意味着什么
  • 这个题值得再来复习一下
posted @ 2023-02-02 14:55  神鹏佐佑  阅读(17)  评论(0)    收藏  举报