TLE opimization

几道题目很悲剧

Longest Parenthese 不是一次遍历+stack, 而是DP,但是DP TLE了。这道题目一开始以为是普通的stack括号匹配,一次扫描,后面逻辑改了半天还没过所有的case,然后看了才知道DP,感觉
最什么的问题都不是朴素算法,一般考虑DP 贪心啥的。这里的DP方程一开始以为是dp[i][j]表示整数啥的,递推写起来很别扭,后来想起曹博PPT提过bool的状态,所以改成bool值了,然后
括号字串类似矩阵链从短到长,遍历结束就是最后赋dp[i][j]=true的就是maxlen了,都不用打擂台。

#include <iostream>
using namespace std;
//#define MAXNUM 10000
//bool dp[MAXNUM][MAXNUM];
int longestValidParentheses(string str)
{
    int n=str.size();
    if(n==0) return 0;

    bool** dp=new bool*[n];
    for(int i=0;i<n;i++)
        dp[i]=new bool[n],memset(dp[i],0,n*sizeof(bool));
    /*
        for(int i=0;i<str.size();i++)
        {
            for(int j=0;j<str.size();j++)
            {
                cout<<dp[i][j]<<" ";
            }
            cout<<endl;
        }
    */
    //for(int i=0;i<=n-1;i++)
    //    dp[i][i]=false;
    int maxlen=0;
    for(int i=0;i<=n-2;i++)
    {
        if(str[i]=='(' && str[i+1]==')')
            dp[i][i+1]=true,maxlen=2;
        //else 
        //    dp[i][i+1]=false;
    }
    for(int length=3;length<=n;length++)
    {
        for(int i=0;i<=n-3;i++)
        {
            int j=i+length-1;
            if(j>=n)
                break;
            //dp[i][j]=false;
            if(dp[i+1][j-1]==true && str[i]=='(' && str[j]==')')
            {    dp[i][j]=true; maxlen=length;continue;}
            for(int k=i;k<j;k++)
            {
                if(dp[i][k] && dp[k+1][j])
                {    dp[i][j]=true;maxlen=length;break;}
            }
        }
    }

    for(int i=0;i<n;i++)
        delete[] dp[i];
    delete[] dp;

    return maxlen;
}


int main()
{
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    string str;
    while(getline(cin,str))
    {
        time_t start=clock();
        cout<<longestValidParentheses(str)<<endl;
        time_t end=clock();
        cout<<"time: "<<end-start<<endl;
        /*
        for(int i=0;i<str.size();i++)
        {
            for(int j=0;j<str.size();j++)
            {
                cout<<dp[i][j]<<" ";
            }
            cout<<endl;
        }*/
    }
    return 0;
}

认识已经如此的艰难,为何还要这样对我。后来leetcode版主回我说是有一个one pass的用栈的算法。。。我欲哭无泪了。。。。

这个是看的别人的代码,就像一道题目想不出最后看答案一个道理,和自己想出来对于自己的印象和理解是不可同日而语的。只能暂时解释下代码了。算法是被人的。

This algorithm seems a brainstorm method. stack stores position, which I have not thought before, it is so hard to think. Maxlen records current longest string length, last records last unmatched ),

int longestValidParentheses(string s) {
if (s.empty()) return 0;
stack<int> ms;
int maxlen = 0;
int last = -1;  // Position of the last unmatched ')'
for (int i = 0; i < s.size(); i ++)
{
    if (s[i] == '(') ms.push(i); // 
    else if (ms.empty()) last = i; // == ')' and the stack is empty, it means this is a non-matching ')'
    else
    {
        ms.pop();           // pops the matching '('.
        if (ms.empty()) // If there is nothing left in the stack, it means this ')' matches a '(' after the last unmatched ')'
            maxlen = max(maxlen, i-last);
        else    // otherwise, 
            maxlen = max(maxlen, i-ms.top());
    }
}
return maxlen;
}

Merged K linklist,优化了一次,去掉while 条件的 一次N重循环,还是不行,已经想到解决方案了,可以用heap,里面用pair,key是结点值,value是链表索引号,便于后面找到链表后移。
用了堆之后,我就在想,以后要有意识,找元素,能二分先考虑二分,找K个最大或者最小,能堆先堆,虽然建堆要O(n),但是当查找最大最小频繁的时候,例如在一个loop里面,那么loop里O(n)
就变为O(logn)了,如果n次loop,那么总复杂度从O(n^2)降到O(n+nlogn)=O(nlogn)了,所以堆的确是很强的DS。

另外需要注意的是,默认的make_heap一般都是 less compare函数,那么这个是产生大顶堆,这个不知道为什么,就理解成反的吧,例如父亲要小于孩子的(less than),产生小顶堆,但是这里却是
大顶堆。默认less函数都知道的,就像排序默认less函数,然后递增。

Insert intervals 也要第二次搞定。。。。

另外今天看到一个语法问题,拷贝构造函数参数必须是引用传递,而不可以是值传递,因为本身参数传递如果是值,就要对象赋值,再次调用拷贝构造函数本身,造成自身递归调用,无穷递归。所以
一定是const T& a这种类型的 参数。

数组inta, a+1 相当于地址a+14了

Posted by richard爱闹 - 7月 30 2014
如需转载,请注明: 本文来自 Richard