コンテンツ
らせん行列I
トピックの説明:
問題解決のアイデア:
この質問は、私たちの日常生活で玉ねぎをはがすのと同じです。まず皮をむき、次に中身をはがします。この問題も同様です。すべての境界を通過する開始点と終了点を定義します。それから中に入ってください。詳細については、コードを参照してください。
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
トピックの説明:
問題解決のアイデア:前の質問に答えた後、この質問を直接削除できます。事前にスペースを開いて値を配列に入力するだけで済みます。これは基本的に前の質問と同じです。詳細はコードをご覧ください
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.画像を回転させます
トピックの説明:
問題解決のアイデア:
この質問の実現の考え方は、前の質問とほぼ同じです。最初に外側の回転が行われ、次に内側の回転が行と行が等しくなるまで回転されます。
上図に示すように、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つの対角トラバーサル
トピックの説明:
問題解決のアイデア:
正の対角線には、同じ対角線上の各点の(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.行列のゼロ化
トピックの説明:
問題解決のアイデア:
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番目に小さい数
トピックの説明:
問題解決のアイデア:
アイデアは非常に単純です:
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);//返回结果 } };