leetcode

最近稍闲,就刷leetcode玩,说是为了准备找工作,其实就是好玩,因为好水啊哈哈哈哈。

混了个国奖,感觉我干的像样一点的事情都跟我无关,所以还是,努力让自己变成一个更好的人吧。

从今天起就记录一下我没有1A或者有意思的题目吧。

2015.10.16

Contains Duplicate III

Given an array of integers, find out whether there are two distinct indices i and j in the array such that the difference between nums[i] and nums[j] is at most t and the difference between i and j is at most k.

class Solution {
public:
    bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
        multiset<int> m;
        for (int i = 0;i<nums.size();i++)
        {
            if (i>=k+1) m.erase(nums[i-k-1]);
            auto lb = m.lower_bound(nums[i]-t);
            if (lb != m.end() && (*lb)-t<=nums[i]) return true;
            m.insert(nums[i]);
        }
        return false;
    }
};

没有1A的原因:nums[i]+t会超int,好吧,类似还有一个二分题中间,m=(l+r)/2也会超过int。顺便记一下,INT_MAX, INT_MIN, 记得想想就好。

这道题目的想法还是挺直观的,只是发现用stl写,真的好省事。

 Max Points on a Line

Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.

class Solution {
public:
    int maxPoints(vector<Point>& points) {
        int ret = 0;
        for (auto &i : points)
        {
            unordered_map<long double,int> m;
            int dup = 0;
            for (auto& j : points)
            {
                if (i.x == j.x && i.y == j.y) dup++;
                else
                {
                    if (i.x == j.x) m[INFINITY]++;
                    else m[((long double)i.y - j.y)/((long double)i.x - j.x)]++;
                }
            }
            int localMax = 0;
            for (auto &x : m) localMax = max(localMax,x.second);
            localMax += dup;
            ret = max(ret,localMax);
        }
        return ret;
    }
};

也是感叹一下 STL让程序变的更加美观

还有for循环,最近接触了c++11的写法

 

10.23

Best Time to Buy and Sell Stock IV

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete at most k transactions.

Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

这道题目还是有点意思的

比较容易想到动态规划, f[k][n]表示k次交易在前n天的最大收益

f[k][n] = max{f[k-1][n],f[k][n-1],max{f[k-1][p] - a[p+1] + a[n]} }

直接这样是O(k*n^2), 可以后面那一项存下来,理解为持多仓一手的最大收益。

贴个

class Solution {
public:
    int maxProfit(int k, vector<int>& a) {
        int Len = a.size();
        if (!Len || !k) return 0;
        
        //
        if (k >= Len/2)
        {
            int ret = 0;
            for (int i = 0;i<Len-1;i++)
            if (a[i] < a[i+1]) ret+= a[i+1] - a[i];
            return ret;
        }
        //
        
        vector<vector<int>> f = vector<vector<int>>(2,vector<int>(Len,0));
        for (int i = 1;i<=k;i++)
        {
            int maxLong = -a[0];
            for (int j = 1;j<Len;j++)
            {
                int i1 = i & 1;
                f[i1][j] = max(f[1-i1][j],f[i1][j-1]);
                f[i1][j] = max(f[i1][j],maxLong + a[j]);
                maxLong = max(maxLong,f[1-i1][j-1] - a[j]);
            }
        }
        return f[k&1][Len-1];
    }
};

还有O(n)算法

最优的交易策略一定是在极小值点买入,在极大值点卖出的

预处理可以得到所有波谷波峰对$(v_i,p_i)$,注意可以舍去第一个波峰和最后一个波谷

如果不限制交易的次数,那么可以得到每个$(v_i,p_i)$对的收益$\sum(p_i-v_i)$

限制了交易的次数,有些波动是吃不到的,最好能吃到最大的k个向上波动

为了让选取最大的k个波动的算法可行,必须消除两对(v,p)间的相互影响

对于先后出现的两对$(v_i,p_i)$, $(v_j,p_j)$, 如果$v_i >= v_j$ 那么最优的策略不可能$v_i$买入以后到$v_j$还没有卖出, 因为在$v_j$买入不会比$v_i$买入等到$v_j$多花钱,所以这两个对是不相互影响的

精髓:

如果$p_j>p_i$, 那么如果多一次交易机会,可以多吃到$(p_i - v_j)$这个利润

可以等价成$(v_j,p_i)$ ,$(v_i ,p_j)$两个对,如果只有一次机会, 就做进大的这一对, 如果多一次交易机会, 就把小的利润也做进去.

具体实现用到了栈

贴:

class Solution {
public:

    stack<pair<int,int>> st;

    int maxProfit(int k, vector<int>& a) {
        int v = 0;
        int p = 0;
        int Len = a.size();
        vector<int> pro;
        
        while (v < Len)
        {
            while (v+1 < Len && a[v+1]<=a[v]) v++;
            p = v+1;
            if (p == Len) break;
            while (p+1 < Len && a[p+1]>=a[p]) p++;
            int av = a[v];
            int ap = a[p];
            v = p+1;
            
            while (!st.empty() && av <= st.top().first)
            {
                pro.push_back(st.top().second - st.top().first);
                st.pop();
            }
            while (!st.empty() && ap > st.top().second)
            {
                pro.push_back(st.top().second - av);
                av = st.top().first;
                st.pop();
            }
            st.push({av,ap});
        }
        
        while (!st.empty())
        {
            pro.push_back(st.top().second - st.top().first);
            st.pop();
        }
        
        sort(pro.begin(),pro.end(),[](int a,int b){return a>b;});
        int ret = 0;
        if (k>pro.size()) k = pro.size();
        for (int i = 0;i<k;i++)
        ret+=pro[i];
        return ret;
    }
};

Linked List Cycle II

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

Note: Do not modify the linked list.

Follow up:
Can you solve it without using extra space?

贴个代码吧,记住就好,挺有意思的算法

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        if (!head) return NULL;
        auto p = head;
        auto q = head;
        int cnt = 0;
        for (;;)
        {
            cnt++;
            
            p = p->next;
            
            q = q->next;
            if (!q) return NULL;
            q = q->next;
            if (!q) return NULL;
            if (p == q) break;
        }
        p = head;
        while (p!=q)
        {
            p = p->next;
            q = q->next;
        }
        return p;
    }
};

10.24

Word Break II

Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each word is a valid dictionary word.

Return all such possible sentences.

For example, given
s = "catsanddog",
dict = ["cat", "cats", "and", "sand", "dog"].

A solution is ["cats and dog", "cat sand dog"].

class Solution {
public:
    map<string,vector<string>> m;

    vector<string> combine(const string& s,vector<string> vs)
    {
        if (vs.size()==1 && vs[0] == ""){return vector<string>{s};}
        vector<string> ret;
        for (auto& x : vs)
        ret.push_back(s + " " + x);
        return ret;
    }
    
    vector<string> wordBreak(string s, unordered_set<string>& Dict) {
        vector<string> ret;
        if (s == "")
        {
            ret.push_back(s);
            return ret;
        }
        if (m.find(s)!=m.end()) return m[s];
        for (int i = 1;i<=s.length();i++)
        if (Dict.count(s.substr(0,i)))
        {
            auto tmp =combine(s.substr(0,i),wordBreak(s.substr(i,s.length()-i),Dict));
            ret.insert(ret.end(),tmp.begin(),tmp.end());
        }
        m[s] = ret;
        return ret;
    }
};

再次感叹一下STL的强大,感觉STL让程序更加简洁,易懂。这个程序不用STL的话,是非常冗长的。

Clone Graph

Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors.


OJ's undirected graph serialization:
Nodes are labeled uniquely.

We use # as a separator for each node, and , as a separator for node label and each neighbor of the node.
As an example, consider the serialized graph {0,1,2#1,2#2,2}.

The graph has a total of three nodes, and therefore contains three parts as separated by #.

First node is labeled as 0. Connect node 0 to both nodes 1 and 2.
Second node is labeled as 1. Connect node 1 to node 2.
Third node is labeled as 2. Connect node 2 to node 2 (itself), thus forming a self-cycle.
贴:

class Solution {
public:
   unordered_map<UndirectedGraphNode*,UndirectedGraphNode*> m;
    
    UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
        if (!node) return node;
        if (m.find(node) != m.end()) return m[node];
        auto ret = new UndirectedGraphNode(node->label);
        m[node] = ret;
        for (auto& x : node->neighbors)
        ret->neighbors.push_back(cloneGraph(x));
        return ret;
    }
};

STL+递归,不谈了。

转载于:https://www.cnblogs.com/soya/p/4886400.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值