1. 连续子数组的最大和
思路一:从头开始遍历,设置两个数,一个记录当前序列和,一个记录最大序列和。如果当前序列和小于等于0,说明前面的序列没有用,令当前序列和为下一个数字,如果大于0,就继续往上加,再与最大序列和做对比。

class Solution {
public:
    int FindGreatestSumOfSubArray(vector<int> array) {
        int len=array.size();
        if(len<=0) return 0;
        int cur=0;
        int res=0x80000000;//最小负数
        for(int i=0;i<len;i++)
        {
            if(cur<=0)
                cur=array[i];//小于等于0,舍去记录的序列
            else
            {
                cur+=array[i];//否则序列加一个数
            }
            res=max(res,cur);//比较
        }
        return res;  
    }
};

思路二:动态规划。当i=0或f(i-1)<=0时,f(i)=pData[i];当i≠0且f(i-1)>0时,f(i)=f(i-1)+pData[i],我们要求的就是max(f[i]) 0<=i<=n;其实动态规划与思路一思想是一样的。

2. 1-n整数中出现1的次数
思路一:暴力,另写一个函数计算每个数字出现1的次数,然后遍历1-n。

class Solution {
public:
    int NumberOf1Between1AndN_Solution(int n)
    {
        if(n<1) return 0;
        int count=0;
        for(int i=1;i<=n;i++)
        {
            int temp=i;//借助一个temp,直接用i的话i会一直为0
            while(temp)
            {
                if(temp%10==1)
                    count++;
                temp=temp/10;
            }
        }
        return count;     
    }
};

思路二:以21345为例子,将其分为1-1345和1346-21345两个部分。先看1346-21345中出现的次数,分两种情况:第一种情况,计算万位的1,出现了10000次,注意次数如果21345是小于19999的数字,那么就不会出现10000次,而是x-10000+1次;第二种情况,分析1除了最高位之外的其他四位数中的情况,由于最高位是2,我们可以再分为,1346-11345与11345-21345两段。每一段剩下的四位数字中,选择其中一位是1,其余三位可以从0-9这十个数字中任意选择。根据排列组合,次数是2×4×10^3.再看1-1345,递归即可。

class Solution {
public:
    int NumberOf1Between1AndN_Solution(int n)
    {
        if(n<=0)
            return 0;
        char strN[50];
        sprintf(strN,"%d",n);//转换成字符串
        return NumberOf1(strN);    
    }
    int NumberOf1(const char* strN)
    {
        if(!strN||*strN<'0'||*strN>'9'||*strN=='\0')
            return 0;//结束条件
        int first=*strN-'0';//最高位
        unsigned int length=static_cast<unsigned int>(strlen(strN));
        if(length==1&&first==0)
            return 0;
        if(length==1&&first>0)
            return 1;//0-9
        int numFirstDigit=0;//最高位
        if(first>1)
            numFirstDigit=pow(10,length-1);
        else if(first==1)
            numFirstDigit=atoi(strN+1)+1;//10000-12345
        int numOtherDigits=first*(length-1)*pow(10,length-2);//剩余位数排列组合
        int numRecursive=NumberOf1(strN+1);//递归
        return numFirstDigit+numOtherDigits+numRecursive;       
    }
};

3.数字序列中某一位的数字
思路:以第1001为为例子,序列前十位是0-9这十个数字,1001>10,从991开始找两位数,两位数一共180,991>180,所以第991位在所有的两位数之后,991-190=881;三位数一共2700位,由于881<2700,所以第881位是某三位数中的一位。由于811=270×3+1,可得811位是100+270这个数的中间一位,也就是7.

 int digitAtIndex(int index)
 {
     if(index==0)
     return -1;
     int digits=1;
     while(true)
     {
         int numbers=countOfIntegers(digits);//计算m位的数字有多少个
         if(index<numbers*digits)
         {
             return digitAtIndex(index,digits);
         }
         index-=digits*numbers;//减去前面的位数
         digits++;
     }
     return -1;
 }
 int countOfIntegers(int digits)//计算m位的数字个数
 {
     if(digits==1)
     return 10;
     int count=(int)pow(10,digits-1);
     return 9*count;
 }
 int digitAtIndex(int index,int digits)
 {
     int number=beginNumber(digits)+index/digits;
     int indexFromRight=digits-index%digits;
     for(int i=1;i<indexFromRight;i++)
     {
         number/=10;
     }
     return number%10;
 }
 int beginNumber(int digits)
 {
     if(digits==1)
     return 0;
     return (int)pow(10,digits-1);
 }