矩阵以及搜索


cpp

#include<vector>
#include<iostream>
using namespace std;


int infection(vector<vector<int>> & vec,int x,int y,int T,int target)
{
    int m=vec.size();
    int n=vec[0].size();
    if(x<0|| x>=m || y<0 || y>=n ||vec[x][y]==-1)
    {
        return 0;
    }
    if(abs(vec[x][y]-target)>T)
        return 0;
    vec[x][y]=-1;
    int a=infection(vec,x+1,y,T,target);
    int b=infection(vec,x-1,y,T,target);
    int c=infection(vec,x,y+1,T,target);
    int d=infection(vec,x,y-1,T,target);

    return a+b+c+d+1;
}

int func(vector<vector<int>> & vec,int x,int y,int T)
{
  int a=vec[x][y];
    return infection(vec,x,y,T,a);
}

int main()
{
    int m;
    cin>>m;
    int n;
    cin>>n;
    vector<vector<int>> vec(m,vector<int>(n,0));
    int y;
    cin>>y;
    int x;
    cin>>x;

    int T;
    cin>>T;
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<n;j++)
        {
            cin>>vec[i][j];
        }
    }
    
  cout<<func(vec,x,y,T)<<endl;
    return 0;
    

}
36.
#include<vector>
#include<string.h>
using namespace std;

class Solution {
public:
    bool isValidSudoku(vector<vector<char>>& board) 
    {
        int row[9][9];//rwo【i】【k】代表第i行的数字k-1出现的次数
        int colmn[9][9];
        int mrt[3][3][9];//mrt[i][j][k]代表的是,第i+1,j+1个框中,数字k-1出现的次数

        memset(row,0,sizeof(row));
        memset(colmn,0,sizeof(colmn));
        memset(mrt,0,sizeof(mrt));

        for(int i=0;i<9;i++)
        {
            for(int j=0;j<9;j++)
            {
                if(board[i][j]!='.')
                {
                    int n=board[i][j]-'0'-1;
                    row[i][n]++;
                    colmn[j][n]++;
                    mrt[i/3][j/3][n]++;
                    if(row[i][n]>1 || colmn[j][n]>1|| mrt[i/3][j/3][n]>1)
                    {
                        return false;
                    }
                }
                
            }
        }
        return true;
    }
};


48.
#include <iostream>
#include "vector"
#include <algorithm>
using namespace std;

//法一:使用额外的矩阵记录
//按行遍历,写入temp对应的列中
//第i行的第j个元素,就是temp里面的倒数第i列的第j个元素
class Solution {
public:
    void rotate(vector<vector<int>>& matrix) 
    {
       int m=matrix.size();
       int n=matrix[0].size();
       vector<vector<int>> temp(m,vector<int>(n,0));
        for(int i=0;i<m;i++)
        {
            for(int  j=0;j<n;j++)
            {
                temp[j][n-i-1]=matrix[i][j];
            }
        }
        matrix=temp;

    }
        
};

// 法二:原地旋转--不使用额外空间
// 这里的方法比较巧妙:以反转代替旋转。先上下反转,然后焱对角线反转
// 问:为什么可以这样反转? 答:上下反转是旋转-180后镜像,对角线反转是旋转270加一次镜像
class Solution {
public:
    void rotate(vector<vector<int>>& matrix) 
    {
        int m=matrix.size();
        int n=matrix[0].size();
        
        //先上下反转
        for(int i=0;i<m/2;i++)
        {
            for(int j=0;j<n;j++)
            {
                swap(matrix[i][j],matrix[m-i-1][j]);
            }
        }

        //再沿对角线反转
        for(int i=0;i<m;i++)
        {
            for(int j=i+1;j<n;j++)
            {
                swap(matrix[i][j],matrix[j][i]);
            }
        }
        return;

    }
        
};

//翻转代替旋转
class Solution {
public:
    void rotate(vector<vector<int>>& matrix) 
    {
        int m=matrix.size();
        int n=matrix[0].size();
        //1 先上下反转
        for(int i=0;i<m/2;i++)
        {
            for(int j=0;j<n;j++)
            {
                swap(matrix[i][j],matrix[m-i-1][j]);
            }
        }

        //2 沿对角线反转
        for(int i=0;i<m;i++)
        {
            for(int j=i+1;j<n;j++)
            {
                swap(matrix[i][j],matrix[j][i]);
            }
        }
        return;
    }
};


54.
#include<vector>

using namespace std;

//法一:在原矩阵上将遍历过的元素置空,来记录已经遍历过的元素
class Solution {
public:
    int directions[4][2]={{0,1},{1,0},{0,-1},{-1,0}};//每一个{}代表的是方向。{}中第一个是行,第二个是列
    vector<int> spiralOrder(vector<vector<int>>& matrix) 
    {
       if(matrix.size()==0 || matrix[0].size()==0) return {};
       int m=matrix.size();
       int n=matrix[0].size(); 
       vector<int > res;
       int row=0;
       int colmn=0;
       int directionIndex=0;//记录的是当前遍历的方向。
       for(int i=0;i<m*n;i++)
       {
           res.push_back(matrix[row][colmn]);
           matrix[row][colmn]=101;
           
           int nextrow=row+directions[directionIndex][0];
           int nextcolmn=colmn+directions[directionIndex][1];

           if(nextrow<0|| nextrow>=m || nextcolmn<0 || nextcolmn>=n || matrix[nextrow][nextcolmn]==101)
           {
               directionIndex=(directionIndex+1)%4;
           }
           
           //处理row和colmn
           row=row+directions[directionIndex][0];
           colmn=colmn+directions[directionIndex][1];
           
       }
       return res;
    }
};

//法二:使用一个额外的数组来记录遍历过的元素
class Solution {
public:
    int directions[4][2]={{0,1},{1,0},{0,-1},{-1,0}};//每一个{}代表的是方向。{}中第一个是行,第二个是列
    vector<int> spiralOrder(vector<vector<int>>& matrix) 
    {
        if(matrix.size()==0 || matrix[0].size()==0) 
            return {};
       int m=matrix.size();
       int n=matrix[0].size();
       vector<int> res;
       vector<vector<int>> mark(m,vector<int>(n,0));

       int row=0;//当前遍历到的行
       int colmn=0;//当前遍历到的列

       int direction=0;//当前遍历的方向
       for(int i=0;i<m*n;i++)
       {
           res.push_back(matrix[row][colmn]);
            mark[row][colmn]=1;

            int nextrow=row+directions[direction][0];
            int nextcolmn=colmn+directions[direction][1];

            if(nextrow<0 || nextrow>=m || nextcolmn<0 || nextcolmn>=n || mark[nextrow][nextcolmn]==1)
            {
                direction=(direction+1)%4;
            }

            row=row+directions[direction][0];
            colmn=colmn+directions[direction][1];

       }
       return res;
    }
};

59.
#include<vector>

using namespace std;

class Solution {
public:
    int derections[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
    vector<vector<int>> generateMatrix(int n) 
    {
        int derectionindex=0;
        int row=0;
        int colmn=0;
        vector<vector<int>> matrix(n,vector<int>(n,0));
        for(int i=1;i<=n*n;i++)
        {
            matrix[row][colmn]=i;
            int nextrow=row+derections[derectionindex][0];
            int nextcolmn=colmn+derections[derectionindex][1];

            if(nextrow>=n || nextrow<0 || nextcolmn>=n|| nextcolmn<0|| matrix[nextrow][nextcolmn]!=0)
            {
                derectionindex=(derectionindex+1)%4;
            }
            row=row+derections[derectionindex][0];
            colmn=colmn+derections[derectionindex][1];
        }
        return matrix;
    }
};

73
#include <vector>

using namespace std;

//简单--基本操作即可
class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) 
    {
        int m=matrix.size();
        int n=matrix[0].size();
        vector<int> row;
        vector<int> colmn;
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(matrix[i][j]==0)
                {
                    row.push_back(i);
                    colmn.push_back(j);
                }
            }
        }
        //将行置零
        for(int i=0;i<row.size();i++)
        {
            //将某一行置零
            for(int h=0;h<n;h++)
            {
                matrix[row[i]][h]=0;
            }
        }

        //将列置零
        for(int i=0;i<colmn.size();i++)
        {
            for(int l=0;l<m;l++)
            {
                matrix[l][colmn[i]]=0;
            }
        }
        return;
    }

};

//法一的另一种写法
//遍历法
class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) 
    {
        vector<int> twozero;
        vector<int> colmnzero;
        int m=matrix.size();
        int n=matrix[0].size();
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(matrix[i][j]==0)
                {
                    twozero.push_back(i);
                    colmnzero.push_back(j);
                }
            }
        }

        for(int i=0;i<twozero.size();i++)
        {
            for(int j=0;j<n;j++)
            {
                matrix[twozero[i]][j]=0;
            }
        }
        for(int i=0;i<colmnzero.size();i++)
        {
            for(int j=0;j<m;j++)
            {
                matrix[j][colmnzero[i]]=0;
            }
        }
        return;

    }
};

79.

#include<vector>
#include<unordered_set>
using namespace std;

//递归搜索---类似于岛屿问题

//注意,这里有个小问题,就是,我们要记录当前搜索下已经使用过的元素,防止在一条搜索中重复使用某个元素(比如绕圈).
//这里使用的方法是,对于当前搜索,将使用过的元素设为空,然后进入下一条搜索的时候恢复!
class Solution {
public:
    bool exist(vector<vector<char>>& board, string word) 
    {
        for(int i=0;i<board.size();i++)
        {
            for(int j=0;j<board[0].size();j++)
            {
                if(infect(board,i,j,word))
                    return true;
            }
        }
        return false;
    }

    bool infect(vector<vector<char>>& board,int i,int j,string& s)
    {
        if(s.size()==0)
            return true;
        if(i<0 || j<0 || i>=board.size()|| j>=board[0].size())
            return false;

        
    
        if(board[i][j]!=s[0])
            return false;

        char temp=board[i][j];
        board[i][j]='\0';//记录遍历了
        string temps= s.substr(1,s.size()-1);
        bool a=infect(board,i-1,j,temps);
        bool b=infect(board,i+1,j,temps);
        bool c=infect(board,i,j+1,temps);
        bool d=infect(board,i,j-1,temps);

        board[i][j]=temp;//恢复
        return a||b||c||d;
    }
};

//另一种写法
class Solution {
public:
    bool exist(vector<vector<char>>& board, string word) 
    {
        int n=board.size();
        int m=board[0].size();

        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(infect(board,i,j,word,0))
                    return true;
            }
        }
        return false;
    }

    bool infect(vector<vector<char>>& board,int i,int j,string& s,int k)
    {
        if(k==s.size())
            return true;
        if(i<0 || j<0 || i>=board.size()|| j>=board[0].size())
            return false;

        
    
        if(board[i][j]!=s[k])
            return false;

        char temp=board[i][j];
        board[i][j]='\0';//记录遍历了
        
        bool a=infect(board,i-1,j,s,k+1);
        bool b=infect(board,i+1,j,s,k+1);
        bool c=infect(board,i,j+1,s,k+1);
        bool d=infect(board,i,j-1,s,k+1);

        board[i][j]=temp;//恢复
        return a||b||c||d;
    }
};


130.
#include<string>
#include<vector>

using namespace std;

class Solution {
public:
    void solve(vector<vector<char>>& board) 
    {
        int m=board.size();
        if(m<=2) return ;
        int n=board[0].size();
        //1 找边界上的O,并进行感染的过程,即将与边界的O接触的O全部标记上
        for(int i=0;i<n;i++)
        {
            dfs(board,0,i);
            dfs(board,m-1,i);
        }
        for(int i=1;i<m-1;i++)
        {
            dfs(board,i,0);
            dfs(board,i,n-1);

        }

        //2 根据记号进行重写
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (board[i][j] == 'A') {
                    board[i][j] = 'O';
                } else if (board[i][j] == 'O') {
                    board[i][j] = 'X';
                }
            }
        }

        return ;

        
    }
    void dfs(vector<vector<char>>& board,int i,int j)
    {
        //base_case
        if(i<0 || i>=board.size() || j<0|| j>=board[0].size() || board[i][j]!='0')
        {
            return;
        }

        board[i][j]='A';
        dfs(board,i+1,j);
        dfs(board,i-1,j);
        dfs(board,i,j+1);
        dfs(board,i,j-1);
    }
};

200.
#include<vector>
#include<string>

using namespace std;

//岛屿感染问题

//my
class Solution {
public:
    int numIslands(vector<vector<char>>& grid) 
    {
        int m=grid.size();
        int n=grid[0].size();
        int res=0;
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(grid[i][j]=='1')
                {
                    res++;
                    infection(i,j,grid);
                }
            }
        }
        return res;

    }

    //实现感染。将从i,j开始的相邻的1全部变成0
    void infection(int i,int j,vector<vector<char>>& grid)
    {
        int m=grid.size();
        int n=grid[0].size();
        //base_case
        if(i<0 || i>=m || j<0 || j>=n || grid[i][j]=='0')
        {
            return;
        }

        grid[i][j]='0';

        infection(i+1,j,grid);
        infection(i-1,j,grid);
        infection(i,j+1,grid);
        infection(i,j-1,grid);

    }
};

#include<string>
#include<vector>

using namespace std;

class Solution {
public:
    int maxAreaOfIsland(vector<vector<int>>& grid) 
    {
        int m=grid.size();
        int n=grid[0].size();
        int count=0;
        int res=0;
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(grid[i][j]==1)
                {
                    count=infection(grid,i,j);
                    res=max(res,count);
                }
            }
        }
        return res;
    }

    //返回的是矩阵中,ij为中心的,感染的格子的数量
    int infection(vector<vector<int>> & grid,int i,int j)
    {
        int m=grid.size();
        int n=grid[0].size();
        
        //base_case
        if(i<0 || j<0 || i>=m || j>=n || grid[i][j]==0)
        {
            return 0;
        }

        grid[i][j]=0;
       

        int a=infection(grid,i+1,j);
        int b=infection(grid,i-1,j);
        int c=infection(grid,i,j-1);
        int d=infection(grid,i,j+1);

        return 1+a+b+c+d;

        
    }
};

JZ04
#include<vector>
using namespace std;
class Solution {
public:
    bool findNumberIn2DArray(vector<vector<int>>& matrix, int target)
    {
        if(matrix.size()==0 )
            return false;
        int n=matrix.size();//行数
        int m=matrix[0].size();//列数
        int i=0;//第一行
        int j=m-1;//第一列

        while(i<n && j>=0)
        {
            if(matrix[i][j]==target)
                return true;
            else if(matrix[i][j]>target)
                j--;
            else if(matrix[i][j]<target)
                i++;
            
           
        }
        return false;;
    }
};
JZ13.
#include<vector>

using namespace std;

class Solution {
public:
    int movingCount(int m, int n, int k) 
    {
        vector<vector<int>> mark(m,vector<int>(n,0));
        return foot(m,n,k,0,0,mark);
    }

    //表示从i,j开始走,得到的最大的格子数
    int foot(int m,int n,int k,int i,int j,vector<vector<int>> & mark)
    {
        //base_case
        if(i<0|| i>=m|| j<0 ||j>=n)
            return 0;
        if((i/10+i%10+j/10+j%10)>k)
            return 0;
        if(mark[i][j]==1)
            return 0;

        mark[i][j]=1;
        int a=foot(m,n,k,i+1,j,mark);
        int b=foot(m,n,k,i-1,j,mark);
        int c=foot(m,n,k,i,j+1,mark);
        int d=foot(m,n,k,i,j-1,mark);
    
        return 1+a+b+c+d;
    }
};

NOTE

对于矩阵的搜索,往往需要记录已经访问过的格子,通常有两种方法:
- 使用一个单独的相同大小的矩阵来记录,访问过的置1
- 在原矩阵上,将遍历过的元素置空,遍历到某个位置的时候,先判断这个位置是不是为空。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值