Leecode: 352, 449, 714

352. Data Stream as Disjoint Intervals

题目

Given a data stream input of non-negative integers a1, a2, …, an, …, summarize the numbers seen so far as a list of disjoint intervals.

For example, suppose the integers from the data stream are 1, 3, 7, 2, 6, …, then the summary will be:

[1, 1]
[1, 1], [3, 3]
[1, 1], [3, 3], [7, 7]
[1, 3], [7, 7]
[1, 3], [6, 7]

Follow up:
What if there are lots of merges and the number of disjoint intervals are small compared to the data stream’s size?

解决思路

这道题解到一般的时候, 在 arr.push_back(Interval) 的时候, 突然想起了浅拷贝,深拷贝的问题.这里再来复习一遍.

简单的来说,【浅拷贝】是增加了一个指针,指向原来已经存在的内存。而【深拷贝】是增加了一个指针,并新开辟了一块空间让指针指向这块新开辟的空间。

【浅拷贝】在多个对象指向一块空间的时候,释放一个空间会导致其他对象所使用的空间也被释放了,再次释放便会出现错误.

当一个类里面只有基本类型的时候(不带指针的时候),就无所谓浅拷贝深拷贝了,因为都是值的复制,但是如果一个类里面有类似于 char *s 的变量的时候, 浅拷贝和深拷贝的区别就区分出来了.

vector.push_back(const _Ty& _Val) 是调用了对象的拷贝复制函数,所以push_back的拷贝方式是由你自己对象的拷贝方式决定的.

参考链接: stl中push_back的拷贝方式
c++浅拷贝和深拷贝

回到题目本身,思路很简单,就是维护一个排序好的interval,然后再二分查找

代码

int binarySearch(vector<Interval>& arr, int begin, int end, int val){
    // 找出第一个arr[index].begin >= val的index, 没有返回-1
    if (arr[end].start < val) return -1;
    while(begin < end){
        int mid = (begin+end) >> 1;
        if(val >= arr[mid].start)
            begin = mid +1;
        else if(val < arr[mid].start)
            end = mid;
    }
    if(arr[begin].start > val)
        return begin;
    else return -1;
}


class SummaryRanges {
public:
    /** Initialize your data structure here. */

    vector<Interval> arr;
    SummaryRanges() {

    }

    void addNum(int val) {
        if( arr.empty() ){
            arr.push_back(Interval(val, val));
            return ;
        }
        int index = binarySearch(arr, 0, arr.size()-1, val);
        if(index == -1){
            if( arr[arr.size() - 1].end >= val) return;
            else if(arr[arr.size() - 1].end + 1 == val ){
                arr[arr.size() - 1].end = val;
            }
            else
                arr.push_back(Interval(val, val));
        }
        else if (index == 0){
            if( arr[0].start == val + 1) arr[0].start = val;
            else arr.insert(arr.begin(), Interval(val, val));
        }
        else{
            if( val + 1 == arr[index].start && val == arr[index - 1].end + 1){
                arr[index].start = arr[index-1].start;
                arr.erase(arr.begin() + index - 1);
            }
            else if( val + 1 == arr[index].start ){
                arr[index].start = val;
            }

            else if( val == arr[index - 1].end + 1) {
                arr[index - 1].end = val;
            }
            else if( val <= arr[index - 1].end ){
                return;
            }
            else {
                arr.insert(arr.begin() + index, Interval(val, val));
            }
        }
    }

    vector<Interval> getIntervals() {
        return arr;
    }
};

449. Serialize and Deserialize BST

问题

Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment.

Design an algorithm to serialize and deserialize a binary search tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary search tree can be serialized to a string and this string can be deserialized to the original tree structure.

The encoded string should be as compact as possible.

Note: Do not use class member/global/static variables to store states. Your serialize and deserialize algorithms should be stateless.

分析

一开始以为是普通的树进行序列化,那这样的话考虑的是通过记录 length, pre_order, in_order来达到目的,然后反序列化的时候根据这三个字段来生成一个树。
但是因为这棵树是BST, 本身就有一定的规则限制,所以直接通过pre_order就可以实现了。在反序列化的时候,较为巧妙地用到了栈这个数据结构。考虑到了FIFO这个特性。

代码

class Codec {
public:

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        if( root == nullptr )  return "";
        string tmp = to_string(root->val);
        if(root->left)
            tmp += "/" + serialize(root->left);
        if(root->right)
            tmp += "/" + serialize(root->right);
        return tmp;
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        stack<TreeNode*> nodeStack;
        if(data == "")  return nullptr;
        // 获得第一个数字。 作为root节点。
        // 放入stack中,获得下一个数字,如果小,插入左节点, 如果大,则弹出stack
        int index = 0;
        TreeNode* root = nullptr, *newNode, *topNode;
        while(index < data.size()){
            int num = 0;
            // acquire first digit
            while(index < data.size() && data[index] != '/'){
                num *= 10;
                num += data[index] - '0';
                ++index;
            }
            // skip "/"
            ++index;
            if(nodeStack.empty()){
                root = new TreeNode(num);
                nodeStack.push(root);
            }
            else if(!nodeStack.empty()){
                newNode = new TreeNode(num);
                topNode = nodeStack.top();
                if( num < topNode->val ){
                    topNode->left = newNode;
                    nodeStack.push(newNode);
                }
                else{ 
                    while( !nodeStack.empty() && num >= nodeStack.top()->val ){
                        topNode = nodeStack.top();
                        nodeStack.pop();
                    }
                    topNode->right = newNode;
                    nodeStack.push(newNode);
                }
            }
        }
        return root;
    }
};

714. Best Time to Buy and Sell Stock with Transaction Fee

题目

Your are given an array of integers prices, for which the i-th element is the price of a given stock on day i; and a non-negative integer fee representing a transaction fee.

You may complete as many transactions as you like, but you need to pay the transaction fee for each transaction. You may not buy more than 1 share of a stock at a time (ie. you must sell the stock share before you buy again.)

Return the maximum profit you can make.

Example 1:

Input: prices = [1, 3, 2, 8, 4, 9], fee = 2
Output: 8
Explanation: The maximum profit can be achieved by:
  • Buying at prices[0] = 1
  • Selling at prices[3] = 8
  • Buying at prices[4] = 4
  • Selling at prices[5] = 9
  • The total profit is ((8 - 1) - 2) + ((9 - 4) - 2) = 8.

Note:

  • 0 < prices.length <= 50000.
  • 0 < prices[i] < 50000.
  • 0 <= fee < 50000.

分析

无意中刷到了 Morgan Stanly 终面 on-site 的一道面试题。当时面试的时候没考虑到手续费的问题(也算是没弄清楚问题)

这题最重要的就是弄清楚每个点只有两种状态:买入和售出
刚开始想这道题的时候,一直想着要通过一个变量来保存之前买的股票的价格 p1 ,然后卖出的时候再通过做差 p2 - p1 来计算利润。

但是换种思路会简单很多,炒股的时候可能也应该有这种心态,叫沉没成本:就是你当初购买股票的钱已经花出去了,是已经固定的成本,接下来的决策就应该针对当前市面价格,做出决策,在价格最高的时刻卖出去,即便可能这个价格比当初买的价格还低。

如果这么来想的话,就应该通过 balance 来记录自己现有的钱。 买入就是 balance - p1, 卖出就是 balance + p2 。然后又因为购买的规则,一天只能进行一个操作。那么可以想到用 DP 来解决这个问题:
sold[i]hold[i]分别代表第i天进行卖出,买入操作的最大获益,那么状态转移方程是:

sold[i] = max(sold[i-1], hold[i-1] + p[i] - fee)
hold[i] = max(hold[i-1], sold[i-1] - p[i])

代码

typedef long long LL;
class Solution {
public:
    int maxProfit(vector<int>& prices, int fee) {
    // init sold[0], hold[0]
    // sold[i] = max(sold[i-1], hold[i-1] + p[i] - fee)
    // hold[i] = max(hold[i-1], sold[i-1] - p[i])
        LL sold[prices.size()], hold[prices.size()];
        sold[0] = 0;
        hold[0] = 0 - prices[0];
        LL ans = 0;
        for (int i = 1 ; i < prices.size() ; ++i){
            sold[i] = max(sold[i-1], hold[i-1] + prices[i] - fee);
            hold[i] = max(hold[i-1], sold[i-1] - prices[i]);
            if ( sold[i] > ans )    ans = sold[i];
        }
        return ans;
    }
};
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、 4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值