力扣数据结构14天学习计划—day5

力扣36—有效的数独

力扣36—有效的数独

相关标签:数组、哈希表、矩阵

题意

请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。

  1. 数字 1-9 在每一行只能出现一次。
  2. 数字 1-9 在每一列只能出现一次。
  3. 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)

注意:

  • 一个有效的数独(部分已被填充)不一定是可解的
  • 只需要根据以上规则,验证已经填入的数字是否有效即可。
  • 空白格用 '.' 表示。

解法1—哈希表

        按照从左往右,从上到下的顺序遍历board,判断数字是否在对应的行、列和 3x3的box 里出现过。

        假设数字的下标为 (i,j),那么该数字出现在第  j/3+(i/3)*3 个box

C++实现

class Solution 
{
public:
    bool isValidSudoku(vector<vector<char>>& board) 
    {
        //存储数字在对应的行上是否出现过,默认都是0,代表没有出现过
        //第二维度是10,代表下标范围可以出现9
        int rows[9][10]={0};
        int cols[9][10]={0};
        int box[9][10]={0}; //一共有9个box

        for(int i=0;i<9;++i)
        {
            for(int j=0;j<9;++j)
            {
                if(board[i][j]=='.')
                    continue;
                int num = board[i][j]-'0';  // 字符型数字转化为整形数字
                if(rows[i][num]==1) //如果该数字在对应的行上出现过就直接返回false
                    return false;
                if(cols[j][num]==1)
                    return false;
                if(box[j/3+(i/3)*3][num]==1)
                    return false;
                rows[i][num]=1;
                cols[j][num]=1;
                box[j/3+(i/3)*3][num]=1;
            }
        } 
        return true; 
    }
};

解法2—位运算

二进制 用某一位的1代表这个数字出现过,因为题目存储的数字范围是1~9,所以我们需要9个位来标记数字,而int 的 二进制 是32位,所以足以存储。

初始化时 我们可以用0代表没出现,1代表出现过。

class Solution 
{
public:
    bool isValidSudoku(vector<vector<char>>& board) 
    {
        /*
        //存储数字在对应的行上是否出现过,默认都是0,代表没有出现过
        //第二维度是10,代表下标范围可以出现9
        int rows[9][10]={0};
        int cols[9][10]={0};
        int box[9][10]={0}; //一共有9个box

        for(int i=0;i<9;++i)
        {
            for(int j=0;j<9;++j)
            {
                if(board[i][j]=='.')
                    continue;
                int num = board[i][j]-'0';  // 字符型数字转化为整形数字
                if(rows[i][num]==1) //如果该数字在对应的行上出现过就直接返回false
                    return false;
                if(cols[j][num]==1)
                    return false;
                if(box[j/3+(i/3)*3][num]==1)
                    return false;
                rows[i][num]=1;
                cols[j][num]=1;
                box[j/3+(i/3)*3][num]=1;
            }
        } 
        return true; 
        */
        
        int rows[9]={0};    //表示每一行中数字是否出现过
        int cols[9]={0};
        int box[9]={0};
        for(int i=0;i<9;++i)
        {
            for(int j=0;j<9;++j)
            {
                if(board[i][j]=='.')
                    continue;
                int box_index = j/3+(i/3)*3;    //表示当前数字是位于第几个box里面
                int num = 1<<(board[i][j]-'0'); //当前数字存储在第几位上
                if(rows[i]&num || cols[j]&num || box[box_index]&num)
                {
                    //如果当前数字在对应的行、列、box里出现过,就返回false
                    return false;
                }
                rows[i]|=num;
                cols[j]|=num;
                box[box_index]|=num;
            }
        }
        return true;
    }
};

 力扣73—矩阵置零

力扣73

相关标签:数组、哈希表、矩阵

题意 

给定一个 m x n 的矩阵,如果一个元素为 ,则将其所在行和列的所有元素都设为 0 。请使用 原地算法

解法1—使用标记数组

class Solution 
{
public:
    void setZeroes(vector<vector<int>>& matrix) 
    {
        int m = matrix.size();  //原矩阵行数
        int n = matrix[0].size();   //原矩阵列数
        vector<bool> rows(m,false);   
        vector<bool> cols(n,false);   
        for(int i=0;i<m;++i)
        {
            for(int j=0;j<n;++j)
            {
                if(!matrix[i][j])
                {
                    rows[i]=cols[j]=true;
                }
            }
        }
        for(int i=0;i<m;++i)
        {
            for(int j=0;j<n;++j)
            {
                if(rows[i]||cols[j])
                {
                    matrix[i][j]=0;
                }
            }
        }
        

    }
};

 法2—使用两个标记变量

        我们可以用矩阵的第一行和第一列代替方法一中的两个标记数组,以达到 O(1) 的额外空间。但这样会导致原数组的第一行和第一列被修改,无法记录它们是否原本包含 0。因此我们需要额外使用两个标记变量分别记录第一行和第一列是否原本包含 0。

class Solution 
{
public:
    void setZeroes(vector<vector<int>>& matrix) 
    {
        int m = matrix.size();  //原矩阵行数
        int n = matrix[0].size();   //原矩阵列数
        bool rows0_flag=false;  //标记第一行是否有0
        bool cols0_flag=false;  //标记第一列是否有0
        
        //扫描第一行看有没有0
        for(int j=0;j<n;++j)
        {
            if(matrix[0][j]==0)
            {
                rows0_flag=true;
                break;
            }
        }
        //扫描第一列看有没有0
        for(int i=0;i<m;++i)
        {
            if(matrix[i][0]==0)
            {
                cols0_flag=true;
                break;
            }
        }
        //用第一行、第一列记录,非第一行第一列元素为0的情况
        for(int i=1;i<m;++i)
        {
            for(int j=1;j<n;++j)
            {
                if(0==matrix[i][j])
                {
                    matrix[i][0]=0;//用第一列记录
                    matrix[0][j]=0;//用第一行记录
                }
            }
        }
        //更改非第一行第一列的元素
        for(int i=1;i<m;++i)
        {
            for(int j=1;j<n;++j)
            {
                if(matrix[i][0]==0 || matrix[0][j]==0)
                {
                   matrix[i][j]=0;
                }
            }
        }
        //判断第一行、第一列是否需要改0
        if(rows0_flag)
        {
            for(int j=0;j<n;++j)
                matrix[0][j]=0;
        }
        if(cols0_flag)
        {
            for(int i=0;i<m;++i)
                matrix[i][0]=0;
        }


        /*
        vector<bool> rows(m,false);   
        vector<bool> cols(n,false);   
        for(int i=0;i<m;++i)
        {
            for(int j=0;j<n;++j)
            {
                if(!matrix[i][j])
                {
                    rows[i]=cols[j]=true;
                }
            }
        }
        for(int i=0;i<m;++i)
        {
            for(int j=0;j<n;++j)
            {
                if(rows[i]||cols[j])
                {
                    matrix[i][j]=0;
                }
            }
        }
        */
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
力扣(LeetCode)中,数据结构的调用细则如下: 1. 导入库:首先,你需要导入相应的库来使用数据结构。例如,在使用数组时,你可以导入`<vector>`头文件,而在使用链表时,可以导入`<list>`头文件。 2. 创建数据结构对象:接下来,你需要创建数据结构的对象。具体的创建方式取决于不同的数据结构。例如,在创建一个数组对象时,你可以使用`vector<int> arr`来声明一个整型数组对象。 3. 插入元素:一旦创建了数据结构对象,你可以使用相应的方法向其中插入元素。不同的数据结构有不同的插入方法。例如,在向数组中插入元素时,你可以使用`arr.push_back(element)`将元素添加到数组的末尾。 4. 访问元素:要访问数据结构中的元素,你可以使用相应的索引或迭代器。例如,对于数组,你可以使用`arr[index]`来访问特定位置的元素。 5. 修改元素:如果需要修改数据结构中的元素,你可以直接对元素进行赋值操作。例如,对于数组,你可以使用`arr[index] = newValue`来修改特定位置的元素。 6. 删除元素:如果需要删除数据结构中的元素,你可以使用相应的方法进行删除。例如,在删除数组中的元素时,你可以使用`arr.erase(iterator)`将迭代器指向的元素从数组中删除。 需要注意的是,不同的数据结构具有不同的特性和操作方法。在使用数据结构时,你需要了解其特点,并根据具体情况选择合适的方法进行操作。此外,力扣上还提供了许多常见数据结构的问题和练习题,供你练习和深入理解数据结构的应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心之所向便是光v

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值