leetcode题解日练--2016.7.16

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

今日题目:1、顶端迭代器;2、完美平方数;3、根节点到叶节点数字和。

今日摘录:

人生是一场旅程。我们经历了几次轮回,才换来这个旅程。而这个旅程很短,因此不妨大胆一些,不妨大胆一些去爱一个人,去攀一座山,去追一个梦……有很多事我都不明白。但我相信一件事。上天让我们来到这个世上,就是为了让我们创造奇迹 ——-《大鱼海棠》

284. Peeking Iterator | Difficulty: Medium

Given an Iterator class interface with methods: next() and hasNext(), design and implement a PeekingIterator that support the peek()operation – it essentially peek() at the element that will be returned by the next call to next().

Here is an example. Assume that the iterator is initialized to the beginning of the list: [1, 2, 3].

Call next() gets you 1, the first element in the list.

Now you call peek() and it returns 2, the next element. Calling next() after that still return 2.

You call next() the final time and it returns 3, the last element. Calling hasNext() after that should return false.

题意:实现一个类

思路:

1、利用复制构造函数

// Below is the interface for Iterator, which is already defined for you.
// **DO NOT** modify the interface for Iterator.
class Iterator {
    struct Data;
    Data* data;
public:
    Iterator(const vector<int>& nums);
    Iterator(const Iterator& iter);
    virtual ~Iterator();
    // Returns the next element in the iteration.
    int next();
    // Returns true if the iteration has more elements.
    bool hasNext() const;
};

class PeekingIterator : public Iterator {
public:
    PeekingIterator(const vector<int>& nums) : Iterator(nums) {
        // Initialize any member here.
        // **DO NOT** save a copy of nums and manipulate it directly.
        // You should only use the Iterator interface methods.

    }

    // Returns the next element in the iteration without advancing the iterator.
    int peek() {
        return Iterator(*this).next();
    }

    // hasNext() and next() should behave the same as in the Iterator interface.
    // Override them if needed.
    int next() {
        return Iterator::next();
    }

    bool hasNext() const {
        return Iterator::hasNext();
    }
};

结果:4ms

2、

// Below is the interface for Iterator, which is already defined for you.
// **DO NOT** modify the interface for Iterator.
class Iterator {
    struct Data;
    Data* data;
public:
    Iterator(const vector<int>& nums);
    Iterator(const Iterator& iter);
    virtual ~Iterator();
    // Returns the next element in the iteration.
    int next();
    // Returns true if the iteration has more elements.
    bool hasNext() const;
};

class PeekingIterator : public Iterator {
private:
    int m_next;
    bool m_hasnext;
public:
    PeekingIterator(const vector<int>& nums) : Iterator(nums) {
        // Initialize any member here.
        // **DO NOT** save a copy of nums and manipulate it directly.
        // You should only use the Iterator interface methods.
        m_hasnext = Iterator::hasNext();
        if (m_hasnext) m_next = Iterator::next();
    }

    // Returns the next element in the iteration without advancing the iterator.
    int peek() {
        return m_next;
    }

    // hasNext() and next() should behave the same as in the Iterator interface.
    // Override them if needed.
    int next() {
        int res = m_next;
        m_hasnext = Iterator::hasNext();
        if (m_hasnext) m_next = Iterator::next();
        else        m_next=NULL;
        return res;
    }

    bool hasNext() const {
        return m_hasnext;
    }
};

结果:4ms

279. Perfect Squares | Difficulty: Medium

Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, …) which sum to n.

For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13, return 2 because 13 = 4 + 9.

题意:完美平方数,要使用最少的平方数来组成我们的完美平方数,返回这个最小的个数。

思路:

1、这道题很容易看出能用DP解,用DP主要是找到状态之间的关系,先尝试从最低位开始计算。

dp[0]=0,dp[1] = 1,计算dp[2],我们需要考虑哪些情况?2=1*1+1*1,3=1*1+1*1+1*1,4=1*1+1*1+1*1+1*1=2*2

看一个大一点的数字,100=1*1+dp[99]=2*2+dp[96]=3*3+dp[91]+……=10*10+dp[0]。而1*1=2*2=…=10*10=1

这样看来规律就比较明显了,dp[n] = 1+dp[n-i*i],i={1,2,3……floor(sqrt(n))}

照此思路写出代码

class Solution {
public:
    int numSquares(int n) {
        if(n<=0)    return 0;
        vector<int> dp(n+1,INT_MAX);
        dp[0] = 0;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j*j<=i;j++)
            dp[i] = min(dp[i],dp[i-j*j]+1);
        }
        return dp[n];
    }
};

结果:440ms

2、显然还能提高,但是我不知道怎么去做了,以下三种方法参考自:

https://discuss.leetcode.com/topic/24255/summary-of-4-different-solutions-bfs-dp-static-dp-and-mathematics

静态DP,和DP思想一样,只不过初始化的时候只初始化一个dp[0],然后后面逐个向里面加。

class Solution {
public:
    int numSquares(int n) {
        if(n<=0)    return 0;
        static vector<int> dp{0};
        while(dp.size()<=n)
        {
            int num = INT_MAX;
            for(int i=1;i*i<=dp.size();i++)
                num = min(num,dp[dp.size()-i*i]+1);
            dp.push_back(num);
        }
        return dp[n];
    }
};

结果:16ms

3、数学思路

首先我们尝试枚举一些数字

1 1

10 2

11 3

100 1

101 2

110 3

111 4

1000 2

1001 1

1010 2

1011 3

1100 3

1101 2

1110 3

1111 4

10000 1

10001 2

10010 2

10011 3

10100 2

……

先就这些数字,观察下规律,貌似结果永远是1-4?这个猜想暂时还不能确定。那么先就这么假设。

首先如果一个数是4的倍数,就一直右移两位,直到这个数的低4位至少有一个1存在。现在我们现在看看

1的情况有哪些,完全平方数,

2的情况是偶数位有一个1或者奇数位有两个1

3的情况是奇数位1个1,偶数位1个1

4的情况呢,最低三位都是1

开始想从位运算上面去找规律,但是找了好久规律,还是没找到。

1和4还是很好写出来,1就是完全平方,4就是如果一个数是4的倍数,就除以4,然后剩下的数中低三位都是1.

2呢?也很好理解,从1到sqrt(n)中,只要能找到一个数X,将n-x之后的数是完全平方数即可。

剩下就是3.

class Solution {
public:
    bool is_square(int n)
    {
        int square_n = (int)sqrt(n);
        return(square_n*square_n==n);
    }
    int numSquares(int n) {
        if(n<=0)    return 0;
        if(is_square(n)) return 1;
        while((n&3)==0)   n >>=2;
        if((n &7)==7) return 4;
        int sqrt_n = (int)(sqrt(n));
        for(int i = 1; i <= sqrt_n; i++)
        {
            if (is_square(n - i*i))
            {
                return 2;
            }
        }
        return 3;
    }
};

结果:4ms

4、BFS的思想,首先标记所有的完全平方数,然后标记所有两个完全平方数能够组成的数,然后三个,最后4个,直到标记完所有数为止,本题最多只到4个完全平方数。

class Solution {
public:
    int numSquares(int n) {
        if(n<=0)    return 0;
        vector<int>cntPerfectNum(n,0);
        vector<int>perfectNums;
        for(int i=1;i*i<=n;i++)
        {
            cntPerfectNum[i*i-1] = 1;
            perfectNums.push_back(i*i);
        }
        if(perfectNums.back()==n)   return 1;
        queue<int> search;
        for(auto num:perfectNums)
        {
            search.push(num);
        }
        int Cnt = 1;
        while(!search.empty())
        {
            Cnt++;
            int size = search.size();
            for(int i=0;i<size;i++)
        {
            int tmp = search.front();
            for(auto num : perfectNums)
            {
                if(tmp+num==n)  return Cnt;
                else if(tmp+num<n && cntPerfectNum[tmp+num-1]==0)
                {
                    cntPerfectNum[tmp+num-1] = Cnt;
                    search.push(tmp+num);
                }
                else if(tmp+num>n)  break;
            }
            search.pop();
        }
        }
    return 0;
    }
};

结果:85ms

  1. Sum Root to Leaf Numbers | Difficulty: Medium

Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number.

An example is the root-to-leaf path 1->2->3 which represents the number 123.

Find the total sum of all root-to-leaf numbers.

For example,

1

/ \

2 3

The root-to-leaf path 1->2 represents the number 12.

The root-to-leaf path 1->3 represents the number 13.

Return the sum = 12 + 13 = 25.

题意:找到二叉树所有根节点到叶节点的路径和。

相关题目:path sum

思路:

1、DFS思想,每次都到最深,和path sum一题非常类似。

/**
 * 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:
    int sumNumbers(TreeNode* root) {
        if(!root)   return 0;
        stack<TreeNode*> nodes;
        TreeNode *pre=NULL,*cur=root;
        int sum=0;
        int res = 0;
        while(cur||!nodes.empty())
        {
            while(cur)
            {
                nodes.push(cur);
                sum=sum*10+cur->val;
                cur = cur->left;
            }
            cur=nodes.top();
            if(cur->right==NULL && cur->left==NULL) res+=sum;
            if(cur->right&&pre!=cur->right)
            {
                cur = cur->right;
            }
            else
            {
             pre=cur;
             sum/=10;
             nodes.pop();
             cur=NULL;
            }
        }
        return res;
    }
};

结果:5ms

2、该写成递归版本

递归基:叶子节点,返回路径和sum

递归调用:每个节点不是递归基的情况下路径和等于左边路径和加上右边路径和

/**
 * 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:
    int sumNumbers(TreeNode* root) {
        if(!root)   return 0;
        return recursion(root,0);
    }
    int recursion(TreeNode*root,int val)
    {
        if(root->left==NULL && root->right==NULL)   return val*10+root->val;
        int newVal=0;
        if(root->left!=NULL)    newVal+=recursion(root->left,val*10+root->val);
        if(root->right!=NULL)   newVal+=recursion(root->right,val*10+root->val);
        return newVal;
    }
};

结果:4ms

时间: 2024-11-05 02:23:55

leetcode题解日练--2016.7.16的相关文章

leetcode题解日练--2016.7.7

日练三题,冰冻三尺非一日之寒. 今日题目:1.出现一次的数II:2.房子小偷III:3.生成括号. 今日摘录:有些事,只能一个人做.有些关,只能一个人过.有些路啊,只能一个人走.–龙应台<目送> 137. Single Number II | Difficulty: Medium Given an array of integers, every element appears three times except for one. Find that single one. Note: Yo

leetcode题解日练--2016.7.17

日练三题,冰冻三尺非一日之寒. 今日题目:1.找到顶点元素:2.去除排序数组中的重复元素:3.H指数 ; 4.H指数II:5.判断一棵二叉树是否合法. 今日摘录: 你站在桥上看风景, 看风景的人在楼上看你. 明月装饰了你的窗子, 你装饰了别人的梦. --卞之琳<断章> 162. Find Peak Element | Difficulty: Medium A peak element is an element that is greater than its neighbors. Given

leetcode题解日练--2016.7.11

日练三题,冰冻三尺非一日之寒. 今日题目:1.每个节点加上next right指针:2.完全平方数:3.旋转矩阵:4.旋转矩阵II. 今日摘录: 也许每一个男子全都有过这样的两个女人,至少两个. 娶了红玫瑰,久而久之,红的变了墙上的一抹蚊子血,白的还是"床前明月光": 娶了白玫瑰,白的便是衣服上的一粒饭粘子,红的却是心口上的一颗朱砂痣. --<红玫瑰与白玫瑰> 116. Populating Next Right Pointers in Each Node | Diffic

[LeetCode]题解(python):031-Next Permutation

题目来源 https://leetcode.com/problems/next-permutation/ Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers. If such arrangement is not possible, it must rearrange it as the lowest possible

leetcode 题解:Search in Rotated Sorted Array II (旋转已排序数组查找2)

题目: Follow up for "Search in Rotated Sorted Array":What if duplicates are allowed? Would this affect the run-time complexity? How and why? Write a function to determine if a given target is in the array. 说明: 1)和1比只是有重复的数字,整体仍采用二分查找 2)方法二 : 实现:  

leetcode题解:Search in Rotated Sorted Array(旋转排序数组查找)

题目: Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). You are given a target value to search. If found in the array return its index, otherwise return -1. You may assume no du

[LeetCode 题解]:Candy

There are N children standing in a line. Each child is assigned a rating value. You are giving candies to these children subjected to the following requirements: Each child must have at least one candy. Children with a higher rating get more candies

leetcode题解:Binary Tree Postorder Traversal (二叉树的后序遍历)

题目: Given a binary tree, return the postorder traversal of its nodes' values. For example:Given binary tree {1,#,2,3}, 1 2 / 3 return [3,2,1]. Note: Recursive solution is trivial, could you do it iteratively? 说明: 1) 两种实现,递归与非递归 , 其中非递归有两种方法 2)复杂度分析:时

leetcode题解: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. 说明: 1)二叉树可空 2)思路:a.根据前序遍历的特点, 知前序序列(PreSequence)的首个元素(PreSequence[0])为二叉树的根(root),  然后在中序序列(InSequence)中查找此根(