LeetCode 975. Odd Even Jump

对于每一个位置,无论是odd还是even jump,jump后的位置要么不存在,要么就是符合要求的唯一位置。因此最关键的问题是解决:

给定一个index i,找出jump后的位置

如果对每个index都能找到jump后的位置,那么利用递归 (DP) 很容易就能判断能否jump到最后一个位置。

由于数组是无序的,因此也没法直接用二分有效搜索。

 

方法一:Ordered Map + DP

可以利用一个map,key是数组的元素,value是index,根据key排序,利用map有序的特性二分来做。

可以先把所有元素放到map里,然后遍历数组里元素后从map里erase掉。

也可以从后往前遍历,这样就只需往map里添加元素即可,就不用先插入后删除了。

DP部分可以和前面一个for循环写在一起更加美观,分开写思路更加清楚。

时间复杂度 O(nlogn),C++ map是RBT,插入删除搜索都是O(logn),对每个数组元素都要操作。

class Solution {
public:
    int oddEvenJumps(vector<int>& A) {
        int n=A.size();
        vector<int> oddnext(n,-1), evennext(n,-1);
        
        map<int,int> m; // value->index
        for (int i=n-1;i>=0;--i){
            auto it_lb=m.lower_bound(A[i]);
            if (it_lb!=m.end()) 
                oddnext[i] = it_lb->second;
            
            auto it_up=m.upper_bound(A[i]);
            if (it_up!=m.begin()) 
                evennext[i] = (--it_up)->second;
            
            m[A[i]] = i;
        }
        
        // oddjump[i] - if now it odd jumps from index i, whether it could reach the end.
        vector<bool> oddjump(A.size(),false), evenjump(A.size(),false);
        oddjump[A.size()-1] = evenjump[A.size()-1] = true;
        for (int i=A.size()-2;i>=0;--i){
            if (oddnext[i]!=-1)
                oddjump[i] = evenjump[oddnext[i]];
            if (evennext[i]!=-1)
                evenjump[i] = oddjump[evennext[i]];
        }
        
        int count=0;
        for (int x:oddjump){
            if (x) ++count;
        }
        
        return count;
    }
};

 

方法二:Monotonic Stack + DP

这里也可以利用单调栈来做。

对于odd jump,我们要找到之后的第一个>= 的数。先建立一个index数组,将index数组根据对应 A[i] 的值从小到大排序,依次放入一个index单调递减的stack内。

while 循环,如果新入栈的index比栈顶元素大 (这里就可以保证当前index i>s.top() && A[i]>=A[s.top()]),那么 oddnext[s.top()] = i.

时间复杂度 O(nlogn),因为排序 O(nlogn),后面单调栈只要 O(n)。

注意:排序时一定要加上 if (A[a]==A[b]) return a<b; 因为快排是无序的,如果A[i]相等,我们必须让index小的排在前面,这样在单调栈时才会更新较小元素位置的oddnext/evennext.

C++ 用lambda function时,如果要用到function外的变量,需要用 [&] 去 capture. 

Lambda of a lambda : the function is not captured

class Solution {
public:
    int oddEvenJumps(vector<int>& A) {
        vector<int> index;
        for (int i=0;i<A.size();++i) index.push_back(i);
        
        // sort index the value in the given index 
        sort(index.begin(),index.end(),[&A](const int &a, const int &b){
            if (A[a]==A[b]) return a<b;
            return A[a]<A[b];
        });
        vector<int> oddnext=make(index);
        
        sort(index.begin(),index.end(),[&A](const int &a, const int &b){
            if (A[a]==A[b]) return a<b;
            return A[a]>A[b];
        });
        vector<int> evennext=make(index);         
        
        // oddjump[i] - if now it odd jumps from index i, whether it could reach the end.
        vector<bool> oddjump(A.size(),false), evenjump(A.size(),false);
        oddjump[A.size()-1] = evenjump[A.size()-1] = true;
        for (int i=A.size()-2;i>=0;--i){
            if (oddnext[i]!=-1)
                oddjump[i] = evenjump[oddnext[i]];
            if (evennext[i]!=-1)
                evenjump[i] = oddjump[evennext[i]];
        }
        
        int count=0;
        for (int x:oddjump){
            if (x) ++count;
        }
        
        return count;
    }
    
    vector<int> make(vector<int> &index){
        vector<int> res(index.size(),-1);
        stack<int> s; // 维护下标减小的单调栈
        for (int i:index){
            while(!s.empty() && s.top()<i){
                res[s.top()] = i; s.pop();
            }
            s.push(i);
        }
        return res;
    }
};

 

posted @ 2019-05-31 13:52  約束の空  阅读(583)  评论(0编辑  收藏  举报