一道二维数组的面试题

题目:给一个M*N的二维数组,数组元素的值为0或者1,要求转换数组,将含有1的行和列全部置1.

 比如原数组:

0 1 0 0

0 0 0 0

0 0 1 0

0 0 0 0

需要转换成:

1 1 1 1

0 1 1 0

1 1 1 1

0 1 1 0


这个题目看起来很简单,可是我在面试过程的40分钟硬是没写出个满意的答案。

首先想到的就是遍历数组,然后遇到1,就设置对应的行和列;但是这样会有问题,因为前面的设置的值会影响后续元素的判断。我的应对方案是将数组复制一份b[m,n],然后遍历第二个数组,如果b[i,j]==1,则设置a数组对应的行和列为1。

这样导致空间复杂度也为m*n了,面试官提醒我有什么办法不用复制数组,我当时脑袋已经一团浆糊了(不巧正好重感冒,本来就不清醒),结果没有回答出来,时间到了。

第二天早上灵光一现,思路突然清晰,花了五分钟完成了下面这个答案:

其实思想就是使用两个一维数组分别记录行和列的状况,数组b[m] , c[n] 用来映射有1的列和行;这样不用复制整个二维数组了,不过还是需要小号点额外空间。于是我就想办法在原有数组a上作文章。

是将1映射到首行首列I相应的位置(不过第一行的1先不映射,因为那样的话a[0,0]会出错),第一步完成为:

0 1 1 0

0

1

0

然后分别根据第一行处理其他行,根据第一列处理其他列;

最后再来处理第一行,第一列;


void convert(int a[][], m, n)
{
   
    int i,j = 0;
    int x, y = 0;
    /*首先在数组未做任何改变之前确认第一行和第一列应该如何处理*/
    for(j=0;j<n;j++)
    {
        if (a[0,j]==1)
        {
            x=1; /*第一行含有1,应该全部置1*/
            break;
        }            
    }
    
    for(i=0;i<m;i++)
    {
        if (a[i,0]==1)
        {
            y=1;/*第一列含有1,应该全部置1*/
            break;
        }            
    }
    
    /*映射除了第一行和第一列的所有的1到第一行第一列的相应位置*/
    for(i=1;i<m;i++)
        for(j=1;j<n;j++)
            if(a[i,j] == 1)
            {
                a[i,0] = a[j,0] = 1;
            }
    
    /*处理行元素置1*/
    for(i=0;i<m; i++)
    {
        if (a[i,0] == 1)
        {
            for(j=1;j<n;j++)
                a[i,j]=1;
        }
    }
    /*处理列元素置1*/
    for(j=0;j <n; j++)
    {
        if (a[0,j] == 1)
        {
            for(i=1;i<n;i++)
                a[i,j]=1;
        }
    }
    /*处理第一行*/
    if(x)
        for(j=0; j<n; j++)
            a[0,j] = 1;
    if(y)
        for(i=0;i<m;i++)
            a[i,0] = 1;
    
    return;    
}


猜你喜欢

转载自blog.csdn.net/bear110/article/details/50487012