Maximum Subarray & Climbing Stairs & Remove Element

简单题三连发!!!

(1) Maximum Subarray

题目很简单,但是非常经典,求最大子序列和问题,很多问题可以转化成这个问题来解决(比如Best Time to Buy and Sell Stock这道题就可以转化成这种问题求解)。根据[1]“根据Wikipedia,这是Brown大学某教授给学生的一道练习题。之后被CMU某教授找到O(n)的解法。”

这个题的解法思路很简单。[2]当我们加上一个正数时,和会增加;当我们加上一个负数时,和会减少。如果当前得到的和是个负数,那么这个和在接下来的累加中应该抛弃并重新清零,不然的话这个负数将会减少接下来的和。于是设两个变量,一个是如果以当前元素为最长子数组的最后一个元素,目前所能达到的最大值curSum。另一个是已知的最大值maxSum。需要注意的是遍历完数组如果最后maxSum==0,则表示数组的数里全部都是小于等于0,然后只需要再重新遍历一次数组选出最大的一个数即可。时间复杂度O(n)。

其实是一个动态规划问题。

class Solution {
public:
    int maxSubArray(int A[], int n) {
        
        if(n==0)  
            return 0;  
          
        int curSum=0, maxSum=0;  
               
        for(int i=0;i<n;i++){  
            curSum+=A[i];  
              
            if(curSum<0)  
                curSum=0;  
              
            if(curSum>maxSum)  
                maxSum=curSum;  
        }  
          
         if(maxSum==0)
         {
             maxSum=A[0];
             
             for(int i=0;i<n;i++)
             {
                 if(A[i]>maxSum)
                    maxSum=A[i];
             }
             return maxSum;
         }
         else return maxSum;  
    }
};


(2) Climbing Stairs

这道题本质是求fibonacci数列。

新手(比如说我)一看到就觉得太简单了,直接一个递归三行代码搞定:

class Solution {
public:
    int climbStairs(int n) {
        if(n==1) return 1;
        if(n==2) return 2;
        return climbStairs(n-1)+climbStairs(n-2);
    }
};
结果 Time Limit Exceeded (Last executed input:44)。根据[3],递归程序一般都是太慢了,因为像Fibonacci问题一样,重复计算了很多分支,因此我们用动态规划填表的方法:

class Solution {
public:
    int climbStairs(int n) {
        
        int *a=new int[n+1];
        
        a[1]=1;a[2]=2;
        
        for(int i=3;i<=n;i++)
        {
            a[i]=a[i-1]+a[i-2];
        }
        return a[n];
    }
};
果断秒过 Accepted (4ms)。然后看了[3],其实用不着一个数组来储存(浪费空间),只用三个变量就可以了:

class Solution {
public:
    int climbStairs(int n) {
        
        int a=1,b=2,c=2;
        
        for(int i=3;i<=n;i++)
        {
            c=a+b;
            a=b;
            b=c;
        }
        return n>1 ? c :a;
    }
};
小结:这道题虽然简单,但是很经典,而且从第一个没通过的版本到最后只用三个int额外空间的过程体现了对一个问题优化到极致的一种渴望,也提醒自己以后写程序都要注意时间空间的开销问题。


(3) Remove Element 

这道题感觉有点简单的无聊了。。。从后往前扫描一遍数组就可以了

class Solution {
public:
    int removeElement(int A[], int n, int elem) {
        
        int end=A[n-1],len=n;
        
        for(int i=n-1;i>=0;i--)
        {
            if(A[i]==elem)
            {
                A[i]=end;
                len--;
                end=A[len-1];
            }
        }
        return len;
    }
};




参考:

[1] http://blog.csdn.net/magisu/article/details/14515209

[2] http://blog.csdn.net/ithomer/article/details/7096252

[3] http://blog.csdn.net/kenden23/article/details/17377869

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值