leetcode题解日练--2016.7.12

来源:互联网 发布:手机上传淘宝主图视频 编辑:程序博客网 时间:2024/05/22 12:19

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

今日题目:1、二叉树每层最右节点;2、实现BST迭代器;3、最小路径和;❤4、超级丑数。

今日摘录:

我们要轻轻的走路、用心的过活;我们要温和的呼吸、柔软的关怀;我们要深刻的思想、广大的慈悲:我们要爱惜一株青草、践地唯恐地痛。这些,都是修行。
——林清玄 《情深,万象皆深》

199. Binary Tree Right Side View | Difficulty: Medium

Given a binary tree, imagine yourself standing on the right side of it, return the values of the nodes you can see ordered from top to bottom.

For example:
Given the following binary tree,
1 <—
/ \
2 3 <—
\ \
5 4 <—
You should return [1, 3, 4].

题意:从上至下输出从右往左看能看到的那些节点。
思路:
1、BFS
突然想到之前一道类似的题目,用两个队列实现如下,权当练手。

/** * 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:    vector<int> rightSideView(TreeNode* root) {        queue <TreeNode*>  q[2];        TreeNode *tmp;        vector<int> res;        if(!root)   return res;        int cur=0,next=1;        q[cur].push(root);        while(!q[cur].empty()||!q[next].empty())        {            tmp = q[cur].front();            q[cur].pop();            if(tmp->left) q[next].push(tmp->left);            if(tmp->right) q[next].push(tmp->right);            if(q[cur].size()==0)                {                    res.push_back(tmp->val);                    swap(cur,next);                }        }        return res;    }};

结果:4ms

其实一个队列就能搞定了,上述代码纯属搞笑。

/** * 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:    vector<int> rightSideView(TreeNode* root) {        queue <TreeNode*> q;        TreeNode *tmp;        vector<int> res;        if(!root)   return res;        q.push(root);        while(!q.empty())        {            int end = q.size()-1;            for(int i=0;i<=end;i++)            {            tmp = q.front();            q.pop();            if(tmp->left)       q.push(tmp->left);            if(tmp->right)      q.push(tmp->right);            if(i==end)   res.push_back(tmp->val);            }        }        return res;    }};

结果:4ms

2、DFS

/** * 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:    vector<int> rightSideView(TreeNode* root) {        vector<int>res;        recursion(res,1,root);        return res;    }    void recursion(vector<int>&res,int level,TreeNode* root)    {        if(!root)   return;        if(res.size()<level)    res.push_back(root->val);        recursion(res,level+1,root->right);        recursion(res,level+1,root->left);    }};

结果:4ms

173. Binary Search Tree Iterator | Difficulty: Medium

Implement an iterator over a binary search tree (BST). Your iterator will be initialized with the root node of a BST.

Calling next() will return the next smallest number in the BST.

Note: next() and hasNext() should run in average O(1) time and uses O(h) memory, where h is the height of the tree.

题意:实现一个BST的迭代器,使得能够在O(1)时间O(h)空间内调用是否有下一个最小数和下一个最小数是什么的功能。

思路:如果没有O(h)空间限制,我们完全可以在先中序遍历一次BST存入队列中,然后这个时候就已经排序好了,之后就很好办了。既然不能采用这种方法,那还有什么方法呢?不难想到,中序遍历的迭代实现是怎样呢?先将最左路径的元素存入栈中,然后从底开始访问,每次访问节点如果有右子树就将右子树的最左路加进来。照着这个思路就很好写代码了,我们需要一个将最左路加入到栈中的代码。

/** * Definition for binary tree * struct TreeNode { *     int val; *     TreeNode *left; *     TreeNode *right; *     TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */class BSTIterator {public:    stack<TreeNode*> nodes;    BSTIterator(TreeNode *root) {        pushLeftPath(root,nodes);    }    /** @return whether we have a next smallest number */    bool hasNext() {        return !nodes.empty();    }    /** @return the next smallest number */    int next() {        TreeNode *tmp = nodes.top();        nodes.pop();        if(tmp->right)    pushLeftPath(tmp->right,nodes);        return tmp->val;    }private:    void pushLeftPath(TreeNode *root,stack<TreeNode*>&nodes)    {        while(root)        {        nodes.push(root);        root = root->left;        }    }};/** * Your BSTIterator will be called like this: * BSTIterator i = BSTIterator(root); * while (i.hasNext()) cout << i.next(); */

结果:28ms

64. Minimum Path Sum | Difficulty: Medium

Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.

题意:m×n的方格,每个方格都放了非负整数,找到一条从左上到右下的路径使得和最小。
相似题目:
思路:
1、很明显的DP思路。用了两个额外的向量。

class Solution {public:    int minPathSum(vector<vector<int>>& grid) {        int res=0;        if(grid.size()==1)        {            for(int i=0;i<grid[0].size();i++)                res+=grid[0][i];            return res;        }        else if(grid[0].size()==1)        {            for(int i=0;i<grid.size();i++)                res+=grid[i][0];            return res;        }        int m=grid.size();        int n=grid[0].size();        vector<int> pre(m,INT_MAX);        vector<int> cur(m,0);        for(int i=0;i<n;i++)        {            if(i==0)    cur[0] = grid[i][0];            else    cur[0] = pre[0]+grid[0][i];            for(int j=1;j<m;j++)                cur[j] =grid[j][i]+ min(pre[j],cur[j-1]);            swap(pre,cur);        }        return pre[m-1];    }};

结果:12ms

上述代码写得太复杂了,每次都是一列一列进行计算,并且空间上还可以优化一下,下面简化一下代码:

class Solution {public:    int minPathSum(vector<vector<int>>& grid) {        int m=grid.size();        int n=grid[0].size();        vector<int> cur(m,grid[0][0]);        for(int i=1;i<m;i++)        {            cur[i]=cur[i-1]+grid[i][0];        }        for(int i=1;i<n;i++)        {            cur[0] +=grid[0][i];            for(int j=1;j<m;j++)                cur[j] =grid[j][i]+min(cur[j-1],cur[j]);        }        return cur[m-1];    }};

结果:12ms

313. Super Ugly Number | Difficulty: Medium

Write a program to find the nth super ugly number.

Super ugly numbers are positive numbers whose all prime factors are in the given prime list primes of size k. For example, [1, 2, 4, 7, 8, 13, 14, 16, 19, 26, 28, 32] is the sequence of the first 12 super ugly numbers given primes = [2, 7, 13, 19] of size 4.

Note:
(1) 1 is a super ugly number for any given primes.
(2) The given numbers in primes are in ascending order.
(3) 0 < k ≤ 100, 0 < n ≤ 106, 0 < primes[i] < 1000.

题意:找到第n个超级丑数,超级丑数的定义是给了一个数组,超级丑数的所有因数只能是这个数组中的元素。
思路:
primes = [2,7,13,19] ,我们怎么样去找丑数?
首先可以肯定所有丑数肯定是2、7、13、19的倍数中产生,但是这里面是有重复元素的,我们需要做的事情就是将这些所有primes元素倍数的数按照从小到大拍个序
为了方便计数,我们创建一个与primes相同大小的idx数组[0,0,0,0],这个数组的含义是prime出现的次数。我们找第1个数(从0开始计数)的时候是怎么找的?这个时候遍历4个idx的值,代表primes中的元素出现的次数,这个时候全部都没有出现过,所以只需要拿1去与它们相乘然后找出最小的那个因子更新uglies[1] = min(primes[j]*uglies[idx[j]])遍历j。这个时候uglies[1] = 2,此时我们就用了一次2这个因子了,就应该将相应的idx加1,变成idx=[1,0,0,0],在下次遍历j的时候,uglies[idx[i]]就便成了[2,1,1,1]。
感觉好像没说清楚,其实就是[1,1,1,1]然后每个数乘上自己对应的因子,变成[2,7,13,19],挑出最小的作为丑数的下一个元素并且更新,其他均不更新。此时就变成[2,1,1,1],直到找够n个数字循环结束。

class Solution {public:    int nthSuperUglyNumber(int n, vector<int>& primes) {         vector<int> idx(primes.size(),0);         vector<int> uglies(n,INT_MAX);         uglies[0] = 1;         for(int i=1;i<n;i++)         {             for(int j=0;j<primes.size();j++)   uglies[i] = min(uglies[i],uglies[idx[j]]*primes[j]);             for(int j=0;j<primes.size();j++)   idx[j] +=(uglies[i]==uglies[idx[j]]*primes[j]);         }         return uglies[n-1];    }};

结果:168ms

0 0
原创粉丝点击