leetcode题解日练--2016.7.12

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

今日题目: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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值