861. 翻转矩阵后的得分

本文介绍了一种解决LeetCode题目《矩阵翻转后的二进制得分》的方法,通过行、列变换策略,最大化矩阵中二进制数的高位计数,从而求得最高分数。详细步骤包括初始化计数数组、行列翻转判断及其实现。

地址:

力扣icon-default.png?t=M0H8https://leetcode-cn.com/problems/score-after-flipping-matrix/

题目:

有一个二维矩阵 A 其中每个元素的值为 0 或 1 。

移动是指选择任一行或列,并转换该行或列中的每一个值:将所有 0 都更改为 1,将所有 1 都更改为 0。

在做出任意次数的移动后,将该矩阵的每一行都按照二进制数来解释,矩阵的得分就是这些数字的总和。

返回尽可能高的分数。

示例:

输入:[[0,0,1,1],[1,0,1,0],[1,1,0,0]]
输出:39
解释:
转换为 [[1,1,1,1],[1,0,0,1],[1,1,1,1]]
0b1111 + 0b1001 + 0b1111 = 15 + 9 + 15 = 39

提示:

1 <= A.length <= 20
1 <= A[0].length <= 20
A[i][j] 是 0 或 1

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/score-after-flipping-matrix
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路:

一个二进制的表示,要想数目大,那么高位尽量等于 1

比如:

那么对于一个这样表达二进制数的矩阵来讲

每一行都是一个二进制数,第一个目标就是把最高位全部置 1

第一阶段:

所以我们扫描每一行的第 0 列,如果值不是 0,就进行行翻转

        第一行:

        

        第二行:

        

        第三行不是 0,不做行变换

第二阶段:

        我们不能再做行变换了,如果再做那么最高位可能就会变,我们这个阶段是处理列变换

       起始列从第 1 列开始,比较的是该列 0 元素的个数,1 元素的个数

        只有 1 元素个数更多的时候,相加的和才更大

        第一列:全部是 1 不做变换

        第二列:0:2个,1:1个,列变换

                

        第三列:0:2个,1:1个,列变换

                 

第三阶段:

        经过前面两个阶段,我们都得到了最终的矩阵,剩下的就是对矩阵行遍历

        转变二进制数为十进制数

        比如:1 1 0 1

                1*2^3 + 1*2^2 + 0*2^1 + 1*2^0

实现部分,需要额外的创建两个二维数组

还是以原始矩阵说明:

行数组元素 0 的个数元素 1 的个数

countRowArr

[0][0] = 3[0][1] = 1
[1][0] = 3[1][1] = 1
[2][0] = 2[2][1] = 2

列数组元素 0 的个数元素 1 的个数

countColArr

[0][0] = 2[0][1] = 1
[1][0] = 2[1][1] = 1
[2][0] = 2[2][1] = 1
[3][0] = 2[3][1] = 1

 

再判定需要进行 行变换 或 列变换 时,要顺带更新上面这两个二维数组的值

方法一、动态更新值

 代码稍微有点多,主要逻辑先上:

1. 创建两个二维数组

2. 行变换

3. 列变换

4. 变换完成,计算二进制的十进制值

    int **countRowArr = createCountGrid(grid, row, col, "row");
    int **countColArr = createCountGrid(grid, row, col, "col");
   

    /* reverse */
    for(i=0; i<row; i++)
    {
        if(grid[i][0] == 0)
        {
            doReverse(grid, row, col, i, -1, countRowArr, countColArr, "row");
        }
    }


    for(i=1; i<col; i++)
    {
        if( needReverse(countColArr, i) )
            doReverse(grid, row, col, -1, i, countRowArr, countColArr, "col");
    }


    /* caculate */
    for(i=0; i<row; i++)
    {
        ret += cacul(grid[i], col);
    }


 剩余代码为具体实现上面的功能,下面是全代码:

int ** createCountGrid(int **grid, int row, int col, char *content)
{
    int i,j;

    if(strcmp(content, "row") == 0)
    {
        /* store numbers of 0 1 in each row */
        int **countRowArr = (int **)malloc(sizeof(int *) * row);
        for(i=0; i<row; i++)
        {
            countRowArr[i] = (int *)malloc(sizeof(int) * 2);
        }

        /* init countRowArr */
        for(i=0; i<row; i++)
        {
            int zero = 0, one = 0;
            for(j=0; j<col; j++)
            {
                if(grid[i][j] == 0)
                    zero++;
                else
                    one++;
            }
            countRowArr[i][0] = zero;
            countRowArr[i][1] = one;
        }

        return countRowArr;
    }
    else
    {
        /* store numbers of 0 1 in each col */
        int **countColArr = (int **)malloc(sizeof(int *) * col);
        for(i=0; i<col; i++)
        {
            countColArr[i] = (int *)malloc(sizeof(int) * 2);
        }

        /* init countColArr */
        for(j=0; j<col; j++)
        {
            int zero = 0, one = 0;
            for(i=0; i<row; i++)
            {
                if(grid[i][j] == 0)
                    zero++;
                else
                    one++;
            }
            countColArr[j][0] = zero;
            countColArr[j][1] = one;
        }

        return countColArr;
    }

    return NULL;
}

void freeCountGrid(int **grid, int row, int col, char *content)
{
    int i;
    int drow, dcol;

    if(strcmp(content, "row") == 0)
        drow = row;
    else
        drow = col;

    for(i=0; i<drow; i++)
    {
        free(grid[i]);
    }
    free(grid);
}

void dispGrid(int **grid, int row, int col, char *content)
{
    int i, j;
    int drow, dcol;

    if(strcmp(content, "row") == 0)
    {
        drow = row;
        dcol = 2;
    }
    else if(strcmp(content, "col") == 0)
    {
        drow = col;
        dcol = 2;
    }
    else
    {
        drow = row;
        dcol = col;
    }

    for(i=0; i<drow; i++)
    {
        for(j=0; j<dcol; j++)
        {
            printf("disp...%s, grid[%d][%d]=%d\n", content, i, j, grid[i][j]);
        }
    }
}

bool needReverse(int **countArr, int idx)
{
    if(countArr[idx][0] >= countArr[idx][1])
        return true;
    else
        return false;

    return false;
}

void doReverse(int **grid, int row, int col, int revRowIdx, int revColIdx, int **countRowArr, int **countColArr, char *content)
{
    int i;

    if(strcmp(content, "row") == 0) // reverse row
    {
        for(i=0; i<col; i++)
        {
            if(grid[revRowIdx][i] == 0)
            {
                grid[revRowIdx][i] = 1;
                countRowArr[revRowIdx][0] --;
                countRowArr[revRowIdx][1] ++;
                countColArr[i][0] --;
                countColArr[i][1] ++;    
            }
            else
            {
                grid[revRowIdx][i] = 0;
                countRowArr[revRowIdx][0] ++;
                countRowArr[revRowIdx][1] --;
                countColArr[i][0] ++;
                countColArr[i][1] --;
            }
        }
    }
    else
    {
        for(i=0; i<row; i++)
        {
            if(grid[i][revColIdx] == 0)
            {
                grid[i][revColIdx] = 1;

                countColArr[revColIdx][0] --;
                countColArr[revColIdx][1] ++;
                countRowArr[i][0] --;
                countRowArr[i][1] ++;
            }
            else
            {
                grid[i][revColIdx] = 0;

                countColArr[revColIdx][0] ++;
                countColArr[revColIdx][1] --;
                countRowArr[i][0] ++;
                countRowArr[i][1] --;
            }
        }
    }
}

int cacul(int *arr, int len)
{
    int num = 0;
    int k = 0;

    for(int i=len-1; i>=0; i--)
    {
        if(arr[k++] == 0)
            continue;

        int j = i;
        int tmp = 1;
        while(j)
        {
            tmp *= 2;
            j--;
        }
        num += tmp;
    }

    return num;
}

int matrixScore(int** grid, int gridSize, int* gridColSize){
    int i, j;
    int ret = 0;
    int row = gridSize;
    int col = gridColSize[0];

    int **countRowArr = createCountGrid(grid, row, col, "row");
    int **countColArr = createCountGrid(grid, row, col, "col");
    
    // dispGrid(grid, row, col, "all");
    // dispGrid(countRowArr, row, col, "row");
    // dispGrid(countColArr, row, col, "col");

    /* reverse */
    for(i=0; i<row; i++)
    {
        if(grid[i][0] == 0)
        {
            doReverse(grid, row, col, i, -1, countRowArr, countColArr, "row");
        }
    }

    // dispGrid(grid, row, col, "all");
    // dispGrid(countRowArr, row, col, "row");
    // dispGrid(countColArr, row, col, "col");

    for(i=1; i<col; i++)
    {
        if( needReverse(countColArr, i) )
            doReverse(grid, row, col, -1, i, countRowArr, countColArr, "col");
    }

    //dispGrid(grid, row, col, "all");
    // dispGrid(countRowArr, row, col, "row");
    // dispGrid(countColArr, row, col, "col");

    /* caculate */
    for(i=0; i<row; i++)
    {
        ret += cacul(grid[i], col);
    }

    /* free */
    freeCountGrid(countRowArr, row, col, "row");
    freeCountGrid(countColArr, row, col, "col");

    return ret;
}

 

查看更多刷题笔记

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值