leetcode题解日练--2016.7.26

日练三题,冰冻三尺非一日之寒。

今日题目:

1、用先序遍历和中序遍历去建立树; | tag:树|数组|DFS

2、用中序遍历和后序遍历去建立树; |tag:树|数组|DFS

3、丑数II。 |tag:DP|堆|数学

今日摘录:

如果有天我们湮没在人潮之中,
庸碌一生,
那是因为我们没有努力要活得丰盛。
——黄碧云

105. Construct Binary Tree from Preorder and Inorder Traversal | Difficulty: Medium

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

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

tag:树|数组|DFS
题意:给一棵二叉树的前序和中序遍历,构建这课二叉树
思路:
1、递归去求解,首先,根据前序遍历能够找到树的根节点就是前序遍历的第一个元素。这个时候怎么找根节点的左节点和右节点呢?我们用根节点将这棵树划为左子树和右子树,我们需要递归去求解左子树的前序遍历,因为根据前序遍历能找到根节点,那么如果确定一棵树哪些部分是左子树,哪些部分是右子树呢?这就需要利用中序遍历了。中序遍历当前根节点,根节点的index左边是左子树,右边是右子树。看栗子:
原树:[1,2,3,4,5,6,7]
先序:[1,2,4,5,3,6,7]
中序:[4,2,5,1,6,3,7]
后序:[4,5,2,6,7,3,1]
首先找到根节点4,然后根节点的index=3,这个时候划分为左子树和右子树,左子树的先序遍历下标是[1,3],中序遍历下标是[0,2],右子树的先序遍历下标是[4,6],中序遍历下标是[4,6]。
自己去递归写几步就能看出规律来,
左子树先序遍历下标=[原来先序起始+1,index]
左子树中序遍历下标=[原来中序起始位置,index-1]
右子树先序遍历下标=[原来先序起始+(index-原来中序起始,这个值也就是index的相对偏移量)+1,原来先序终止位置]
右子树中序遍历下标=[index+1,原来中序终止位置]

/**
 * 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 dfs(0,0,preorder.size()-1,inorder.size()-1,preorder,inorder);
    }
    TreeNode* dfs(int preStart,int inStart,int preEnd,int inEnd,vector<int>&preorder,vector<int>&inorder)
    {
        if(preStart>preorder.size()-1 || inStart>inEnd)
        {
            return NULL;
        }
        TreeNode*root = new TreeNode (preorder[preStart]);
        int index=0;
        for(int i=inStart;i<=inEnd;i++)
        {
            if(inorder[i]==root->val)  {index = i;break;}
        }
        root->left = dfs(preStart+1,inStart,index,index-1,preorder,inorder);
        root->right = dfs(preStart+index-inStart+1,index+1,preEnd,inEnd,preorder,inorder);
        return root;
    }
};

结果:36ms
update:2016.9.16,第二次刷代码,将代码形式写成与中序后序相同的形式

/**
 * 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 dfs(0,0,preorder.size()-1,inorder.size()-1,preorder,inorder);
    }
        TreeNode* dfs(int preStart,int inStart,int preEnd,int inEnd,vector<int>&preorder,vector<int>&inorder)
    {
        if(preStart>preEnd||inStart>inEnd)
            return NULL;
        TreeNode* root = new TreeNode (preorder[preStart]);
        int index = 0;
        for(int i=inStart;i<=inEnd;i++)
        {
            if(inorder[i]==root->val) {index = i;break;}
        }
        root->left = dfs(preStart+1,inStart,preStart+index-inStart,index-1,preorder,inorder);
        root->right = dfs(preStart+index-inStart+1,index+1,preEnd,inEnd,preorder,inorder);
        return root;
    }
};

结果:39ms

106. Construct Binary Tree from Inorder and Postorder Traversal | Difficulty: Medium

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

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

tag:树|数组|DFS
题意:给定一个中序遍历一个后序遍历,去建造原来的树。
思路:
1、递归,与上题类似

/**
 * 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>& inorder, vector<int>& postorder) {
        return dfs(0,0,postorder.size()-1,inorder.size()-1,postorder,inorder);
    }
    TreeNode* dfs(int postStart,int inStart,int postEnd,int inEnd,vector<int>&postorder,vector<int>&inorder)
    {
        if(postStart>postEnd||inStart>inEnd)
            return NULL;
        TreeNode* root = new TreeNode (postorder[postEnd]);
        int index = 0;
        for(int i=inStart;i<=inEnd;i++)
        {
            if(inorder[i]==root->val) {index = i;break;}
        }
        root->left = dfs(postStart,inStart,postStart+index-inStart-1,index-1,postorder,inorder);
        root->right = dfs(postStart+index-inStart,index+1,postEnd-1,inEnd,postorder,inorder);
        return root;
    }
};

结果:40ms

264. Ugly Number II |Difficulty: Medium

Write a program to find the n-th ugly number.

Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. For example, 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 is the sequence of the first 10 ugly numbers.

Note that 1 is typically treated as an ugly number.

tag:DP|堆|数学
相关题目:丑数 超级丑数
题意:找到第n个丑数,丑数的定义是
思路:
1、超级丑数的一种特例

class Solution {
public:
    int nthUglyNumber(int n) {
        vector<int> uglies(n,INT_MAX);
        vector<int> idx(3,0);
        int primers[]={2,3,5};
        uglies[0] = 1;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<3;j++)   uglies[i] = min(uglies[i],uglies[idx[j]]*primers[j]);
            for(int j=0;j<3;j++)   idx[j]+=(uglies[i]==uglies[idx[j]]*primers[j]);
        }
        return uglies[n-1];
    }
};

结果:28ms

2、一种更易读的方法,时间也更快,思路是一样的,只是写得形式不同而已。
代码地址:https://discuss.leetcode.com/topic/21882/my-16ms-c-dp-solution-with-short-explanation/2

class Solution {
public:
    int nthUglyNumber(int n) {
        if(n <= 0) return false; // get rid of corner cases 
        if(n == 1) return true; // base case
        int t2 = 0, t3 = 0, t5 = 0; //pointers for 2, 3, 5
        vector<int> k(n);
        k[0] = 1;
        for(int i  = 1; i < n ; i ++)
        {
            k[i] = min(k[t2]*2,min(k[t3]*3,k[t5]*5));
            if(k[i] == k[t2]*2) t2++; 
            if(k[i] == k[t3]*3) t3++;
            if(k[i] == k[t5]*5) t5++;
        }
        return k[n-1];
    }
};

结果:16ms

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值