阿里笔试——我果然是菜鸟

306 阅读2分钟

题目大意是给定一串0,1数列,允许删除一个0,求数列的1的最长子序列长度。

心路历程:

乍一看感觉这题目不难,毕竟也曾经做过几道子序列问题。但写起代码来却是这里一个坑,那里一个坑。

  • 一开始的想法是尝试把删除每个0的情况考虑一遍,计算对应的子序列长度就可以得出答案。这种方法当然不是不可以,实现起来其实。。也有点困难,因为数列没有删除功能(我不确定c++的模版有没有哇,默认没有),所以每次删除都是一个大工程,就算实现了时间复杂度也是O(n^2),所以直接排除。既然看0不行,

  • 那看1总可以吧。从头遍历数组,对遇到的第一个1子序列进行计数,到达末端后尝试删除0并接着往后数1。这个办法有几个难点:

  1. 如果单纯的用遍历来实现的话,第一次删除0并接着往后计数的时候需要知道删除的机会已经被用掉
  2. 删除完0接着往后走,虽然得到了当前最大子序列,但却有可能丢失后面的1与更后面的子序列组合而成的更长的子序列。

解决办法其实也不难,遍历数组中,在一串1后遇到0,且判断0的后面紧接着1,就嵌套一个循环,循环从该1子序列后的1开始接着数1,直到下一个0,出循环,获得当前最长序列长度。也算是变相的尝试所有组合了。下面是代码:

int maxOnes(int* a, int size)
{
    int MaxNums = 0;
    int tmpMaxNums = 0;

    int i = 0;
    while(a[i]==0) i++;
    
    for(; i < size;)
    {
        if(a[i] == 1)
            tmpMaxNums++;
        else if(a[i] == 0 && i+1 < size && a[i+1] == 1)
        {
            for (int j = i+1; a[j] != 0 && j < size; j++) {
                tmpMaxNums++;
            }
            if(tmpMaxNums > MaxNums)
            {
                MaxNums = tmpMaxNums;
            }
            tmpMaxNums = 0;
        }
        else {
            if(tmpMaxNums > MaxNums)
            {
                MaxNums = tmpMaxNums;
            }
            tmpMaxNums = 0;
            while(a[i]==0) i++;
            continue;
        }
        ++i;
    }
    
    if(tmpMaxNums > MaxNums)
    {
        MaxNums = tmpMaxNums;
    }
     
    return MaxNums;
}

我也不知道为什么一开始的我一直执着于用递归实现,导致代码的bug很多,真的服了自己,下面是递归的代码,又丑又长:


int maxOnes(int* a, int index, int size, bool chance)
{
    int MaxNums = 0;
    int tmpMaxNums = 0;
    
    int i = index;
    while(a[i]==0) i++;
    for(; i < size;)
    {
        if(a[i] == 1)
            tmpMaxNums++;
        else if(a[i] == 0 && i+1 < size && a[i+1] == 1 && chance)
        {
            tmpMaxNums += maxOnes(a, i+1, size, false);
            if(tmpMaxNums > MaxNums)
            {
                MaxNums = tmpMaxNums;
            }
            tmpMaxNums = 0;
                
        }
        else if(a[i] == 0 && !chance)
        {
            break;
        }
        else {
            if(tmpMaxNums > MaxNums)
            {
                MaxNums = tmpMaxNums;
            }
            tmpMaxNums = 0;
            while(a[i]==0) i++;
            continue;
        }
        ++i;
    }
    
    if(tmpMaxNums > MaxNums)
    {
        MaxNums = tmpMaxNums;
    }
     
    return MaxNums;
}

就是因为一开始一直想写成递归才害我这题没写出来的。。气死了

之前没怎么刷过算法题,但个人总感觉这题可以用动态规划解决,毕竟我这个方案复杂度其实也近O(n^2)了(毕竟暴力解法),但实在没想到什么办法可以优化,想用空间换时间,却并想不出什么好办法。。有懂的小伙伴一起探讨呀,不得不说做题还是蛮快乐的。