マトリックスクラスの質問(コード制御能力をテストする)

コンテンツ

らせん行列I

2.スパイラルマトリックスII

3.画像を回転させます

4つの対角トラバーサル

5.行列のゼロ化

6.順序付けられた行列のk番目に小さい数


らせん行列I

54.スパイラルマトリックス-LeetCode(leetcode-cn.com)

トピックの説明:

 問題解決のアイデア:

 この質問は、私たちの日常生活で玉ねぎをはがすのと同じです。まず皮をむき、次に中身をはがします。この問題も同様です。すべての境界を通過する開始点と終了点を定義します。それから中に入ってください。詳細については、コードを参照してください。

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
      vector<int>ans;  //记录答案                                              
        int row1=0;//边界开始位置的行
        int col1=0;//边界结束开始位置的列
        int row2=matrix.size()-1;//边界结束的列
        int col2=matrix[0].size()-1;//边界结束的列
        while(row1<=row2&&col1<=col2)//如果两个点错过了说明已经遍历结束了
        {
            Print(matrix,ans,row1++,col1++,row2--,col2--);
        }
            
         return ans;
    }
    void Print(vector<vector<int>>&matrix,vector<int>&ans,int row1,int col1,int row2,int col2)
    {
        if(row1==row2)//两个点的行变成一样了直接从这一行遍将其放入答案中
        {
           for(int i=col1;i<=col2;i++)
           {
               ans.push_back(matrix[row1][i]);
           }
           return;
        }
         //列相等
         if(col1==col2)
         {//直接将这一列遍历放入答案中
            for(int i=row1;i<=row2;i++)
            {
                ans.push_back(matrix[i][col1]);
            }
            return;
         }
        //说明行和列不相等将边框打印
        //提前记录一下方便后序遍历
         int rowStart=row1;
         int colStart=col1;
        while(colStart<col2)//打印最上层的边框
        {
            ans.push_back(matrix[row1][colStart++]);
        }
        //打印往下走的边框
        while(rowStart<row2)
        {
            ans.push_back(matrix[rowStart++][col2]);
        }
        //打印往左走的
        while(colStart>col1)
        {
            ans.push_back(matrix[row2][colStart--]);
        }
        //往上走
        while(rowStart>row1)//注意这里是大于防止重复遍历
        {
            ans.push_back(matrix[rowStart][col1]);
          
            rowStart--;
        }


    }
};

2.スパイラルマトリックスII

59.スパイラルマトリックスII-LeetCode(leetcode-cn.com)

トピックの説明:

問題解決のアイデア:前の質問に答えた後、この質問を直接削除できます。事前にスペースを開いて値を配列に入力するだけで済みます。これは基本的に前の質問と同じです。詳細はコードをご覧ください

class Solution {
public:
     int num=1;
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>>ans(n,vector<int>(n));
        int row1=0;
        int col1=0;
        int row2=n-1;
        int col2=n-1;
        while(row1<=row2&&col1<=col2)
        {
            Print(ans,row1++,col1++,row2--,col2--);
        }
        return ans;
    }
     void Print(vector<vector<int>>&ans,int row1,int col1,int row2,int col2)
    {
        if(row1==row2)//两个点的行变成一样了直接从这一行遍将其放入答案中
        {
           for(int i=col1;i<=col2;i++)
           {
               ans[row1][i]=num++;
           }
           return;
        }
         //列相等
         if(col1==col2)
         {//直接将这一列遍历放入答案中
            for(int i=row1;i<=row2;i++)
            {
                ans[i][col1]=num++;
            }
            return;
         }
        //说明行和列不相等将边框打印
        //提前记录一下方便后序遍历
         int rowStart=row1;
         int colStart=col1;
        while(colStart<col2)//打印最上层的边框
        {
            ans[row1][colStart++]=num++;
        }
        //打印往下走的边框
        while(rowStart<row2)
        {
            ans[rowStart++][col2]=num++;
        }
        //打印往左走的
        while(colStart>col1)
        {
            ans[row2][colStart--]=num++;
        }
        //往上走
        while(rowStart>row1)//注意这里是大于防止重复遍历
        {
            ans[rowStart][col1]=num++;
          
            rowStart--;
        }


    }
    
};

3.画像を回転させます

インタビューの質問01.07.回転行列-LeetCode(leetcode-cn.com)

トピックの説明:

 問題解決のアイデア:

この質問の実現の考え方は、前の質問とほぼ同じです。最初に外側の回転が行われ、次に内側の回転が行と行が等しくなるまで回転されます。

 

上図に示すように、11番目のステップD \ rightarrowAD→AがAAを上書きしたため(AAが失われます)、この損失により、最後の44番目のステップA\rightarrowBA→Bが値を割り当てることができなくなります。この問題を解決するには、事前に「補助変数tmptmp」を使用してAAを保存することを検討してください。このときのローテーション操作は、次のようになります。

暂存\tmp= A \\ A \ leftarrow D \ leftarrow C \ leftarrow B \leftarrowtmp
暂存tmp=AA
←D←C←B←tmp

 対応するコード:

class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
            int row1=0;
            int col1=0;
            int row2=matrix.size()-1;
            int col2=matrix[0].size()-1;
            while(row1<row2)//如果他们相等了说明不用旋转了
            {
                Rotate(matrix,row1++,col1++,row2--,col2--);
            }
            

    }
    void Rotate(vector<vector<int>>&matrix,int row1,int col1,int row2,int col2)
    {
            for(int i=0;i<col2-col1;i++)
            {
            int tmp=matrix[row1][col1+i];//旋转的第一个元素
             matrix[row1][col1+i] =matrix[row2-i][col1];//这一组最后一个元素覆盖第一个位置
             matrix[row2-i][col1]=matrix[row2][col2-i];//依次覆盖
             matrix[row2][col2-i]=matrix[row1+i][col2];
             matrix[row1+i][col2]=tmp;//将第一个元素放到正确的位置
            }
            
    }
};

4つの対角トラバーサル

498.対角トラバーサル-LeetCode(leetcode-cn.com)

トピックの説明:

問題解決のアイデア:

正の対角線には、同じ対角線上の各点の(x、y)座標の合計が等しいという特性があります。わかりやすい行列を観察すると、合計m + n-1の対角線があり、各対角線は左下から右上、または右上から左下のいずれかになります。最初にこれらを見つけます。 2つの端点を通過し、現在のループの方向に従って移動します。
対角線の性質上、端点の横座標と縦座標のいずれかがわかっている限り、別の次元を取得できます。凡例では、横座標のみを考慮しています。

対応するコード:

class Solution {
public:
    vector<int> findDiagonalOrder(vector<vector<int>>& mat) {
             int endRow=mat.size()-1;
             int endCol=mat[0].size()-1;
             int row1=0;
             int col1=0;
             int row2=0;
             int col2=0;
             vector<int>ans;
             bool fromUp=false;
             while(row1<=endRow)
             {
                 Print(mat,ans,row1,col1,row2,col2,fromUp);
                 row1=col1==endCol?row1+1:row1;//

                 col1=col1==endCol?col1:col1+1;

                  col2=row2==endRow?col2+1:col2;
                  //注意这里要先判断否则会错过最后一些数据老铁可以思考一下

                 row2=row2==endRow?row2:row2+1;
                
                 fromUp=!fromUp;//方向每次取反
             }
             return ans;
    }
    void Print(vector<vector<int>>&mat,vector<int>&ans,int row1,int col1,int row2,int col2,bool fromUp)
    {
           if(fromUp)//如果为true说明是从上面往下面遍历
           {
               while(row1<=row2)
               {
                   ans.push_back(mat[row1++][col1--]);
               }

           }
           else//说明是从下面往上面遍历
           {
                 while(row2>=row1)
                 {
                     ans.push_back(mat[row2--][col2++]);
                 }
           }
    }
};

5.行列のゼロ化

インタビューの質問01.08。ゼロマトリックス-LeetCode(leetcode-cn.com)

トピックの説明:

 問題解決のアイデア:

1. 0番目の列と0番目の行を使用して、特定の行と特定の列を0に設定するかどうかをマークします。トラバーサルが完了したら、0番目の行と0番目の列をトラバースして、特定の位置をに設定するかどうかを決定します。 0ですが、問題が発生します。0行0列に0がある場合は、変数を使用して記録し、個別に処理する必要があります。詳細については、コードを参照してください。

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
           bool iscol=false;//标记第一行是否要置0
           bool isrow=false;//标记第一列是否要置0;
           for(int i=0;i<matrix[0].size();i++)
           {
               //遍历第一行是否要置0
               if(matrix[0][i]==0)
                 isrow=true;
           }
           for(int i=0;i<matrix.size();i++)
           {
               if(matrix[i][0]==0)
               {
                   iscol=true;
               }
           }
           //用0行和第0列的元素标记这一行和这一列是否需要置0
           for(int i=1;i<matrix.size();i++)
           {
               for(int j=1;j<matrix[0].size();j++)
               {
                   if(matrix[i][j]==0)
                   {
                       matrix[0][j]=0;
                       matrix[i][0]=0;
                   }
               }
           }
           //在遍历一次完成置0
           for(int i=1;i<matrix.size();i++)
           {
               for(int j=1;j<matrix[0].size();j++)
               {
                   if(matrix[0][j]==0||matrix[i][0]==0)
                   //对应第0行的位置和第一列的位置
                   //只要有一个为0就说明这个位置需要被置为0;
                   {
                       matrix[i][j]=0;
                   }
               }
           }
        //单独判断第一行和第一列是否需要置0
        if(isrow)//说明第0行需要置0
        {
           for(int i=0;i<matrix[0].size();i++)
           {
               matrix[0][i]=0;
           }
        }
        if(iscol)//说明第一列需要置0
        {
          for(int i=0;i<matrix.size();i++)
           {
                matrix[i][0]=0;
           }
        }
        //处理结束
    }

};

6.順序付けられた行列のk番目に小さい数

378.順序付けられた行列のK番目に小さい要素-LeetCode(leetcode-cn.com)

トピックの説明:

問題解決のアイデア:

 

アイデアは非常に単純です:

1. 2次元行列で左の最小数と右の最大数を見つけます。次に、k番目に小さい数は左から右の間にある必要がありますmid =(left + right)/2;でmid以下を見つけます2次元行列2。このカウント
がk未満の場合、k番目に小さい数が右半分にあり、midを含まないことを意味します。つまり、leftd = mid + 1、right = rightであり、これにより、 k番目に小さい数は左側にあります〜右
3.このカウントがkより大きい場合、k番目に小さい数が左半分にあり、midを含む可能性があることを意味します。つまり、left = left、right = midであり、これにより、 k番目の最小数は左と右の間にあります
。4。k番目の最小数は各ループで左と右の間にあることが保証されているため、left == rightの場合、k番目の最小数が見つかります。これは右に等しくなります。

対応するコード:

class Solution {
public:
       struct Info
       {
           Info(int n,int cnt)
           {
               near=n;
              num=cnt;
           }
           int near;
           int num;
       };
    int kthSmallest(vector<vector<int>>& matrix, int k) {
        int n=matrix.size();
         int left=matrix[0][0];
         int right=matrix[n-1][n-1];
         int ans=0;
        while(left<=right)
        {
            int mid=(left+right)/2;//取中点二分
            Info* ret=getLessEqualNum(matrix,mid);//看一下小于等于mid的有多少个
            if(ret->num<k)//如果小于k说明二分的中点小了
            {
                left=mid+1;
            }
            else{//大于等于更新ans;
                right=mid-1;
                ans=ret->near;
            }
        }
        return ans;//返回ans
    }
    Info*getLessEqualNum(vector<vector<int>>&matrix,int val)
    {
        int m=0;
        int n=matrix[0].size()-1;
        int num=0;
        int near=INT_MIN;//记录小于等于val离val最近的数
        while(m<matrix.size()&&n>=0)
        {
            if(matrix[m][n]<=val)
            {
              num+=n+1;//把小于val的个数加起来
              near=max(near,matrix[m][n]);//更新near
              m++;
            }
            else
            {
                n--;
            }
        }
        return new Info(near,num);//返回结果
    }
};

おすすめ

転載: blog.csdn.net/qq_56999918/article/details/123790380