件名の説明:
あなたを与える m
の行 n
列の2次元グリッド grid
と整数を k
。あなたはする必要があります grid
移行 k
回。たびに「移行」の動作は以下の活動につながります。
- 位置
grid[i][j]
の要素がに移動されますgrid[i][j + 1]
。 - 位置
grid[i][n - 1]
の要素がに移動されますgrid[i + 1][0]
。 - 位置
grid[m - 1][n - 1]
の要素がに移動されますgrid[0][0]
。
戻ってください k
による移動時間の後に、二次元のグリッド。例:
输入:grid
= [1,2,3]、[4,5,6 ]、[7,8,9]、K = 1つの
出力:[[9,1,2]、[3,4,5]、[ 6,7,8]]
输入:grid
= [3,8,1,9]、[19,7,2,5 ]、[4,6,11,10]、[12,0,21,13]、K = 4
出力:[[ 12,0,21,13]、[3,8,1,9]、[19,7,2,5]、[4,6,11,10]
制約:
1 <= grid.length <= 50
1 <= grid[i].length <= 50
-1000 <= grid[i][j] <= 1000
0 <= k <= 100
問題解決のアイデア:
次に、被験者の要求に応じて転送番号の一次元配列に抽象的な2次元配列であるが知ることができる私のアイデアは、数字のシーケンスの前部に移しk個の一次元配列のこの回数の後、実際に移行k倍であります全体のプロセスは、円運動のように想像することができます。Iは、NK要素を格納されている最初の2つの1次元配列とk個の要素に頼っように、これら2つのシリアル・アレイ・トラバーサル、コレクションへの記憶素子が移動することでした。Oの時間複雑度(M * N +(M + N))。コードは次の通り:
リスト<リスト<Integer型>> res_list。 公衆リスト<リスト<整数>> shiftGrid(INT [] []グリッド、INT K){ 場合(k個%(grid.length *グリッド[0] .LENGTH)== 0 ){ res_list = 新しい LinkedListの<> (); 以下のために(INT [] G:グリッド){
// 整数[] GG = IntStream.of(G))(.boxedコレクト(Collectors.toList())のtoArray(新しい整数[0]);。。 リスト<整数> LS = IntStream.of(g)は().boxedコレクト(Collectors.toList())。 (LS)res_list.add。 } 戻りres_list。 } INT temp_len = grid.length *グリッド[0 ] .LENGTH。 K = K%(temp_len)。 INT [] TEMPは= 新しい INT [temp_len- K]。 INT [] TEMP2は= 新しい INT [K]。 int型のインデックス= 0 ; 用(INT [] int値:グリッド){ ため(INT ANINT:int型){ 場合(インデックス<(temp_len- K)) TEMP [インデックス] = ANINT。 他の{ TEMP2 [インデックス- (temp_len-K)] = ANINT。 } インデックス ++ 。 } } LinkedListの <整数> temp_list = 新しい LinkedListの<> (); res_list = 新しい LinkedListは<> (); 用(INTが I = 0; I <= temp_len; I ++ ){ 場合(I%グリッド[0] .LENGTH == 0 &&(I> =グリッド[0 ] .LENGTHする)){ (temp_list)をres_list.add。 temp_list = 新しい LinkedListは<> (); } 場合(I < K) temp_list.add(TEMP2 [I])。 他の 場合(I < temp_len) temp_list.add(TEMP [I - K])。 } 戻りres_list。 }
注意:
プログラムを書くときはコレクションに基本データ型に格納されていないいくつかの知識の誤差を、犯し、ストレージはオブジェクトのみを参照することができます。各コレクション要素は、実際の内容はスタック領域または方法に格納されている参照変数であるが、基本的なデータ型は、スタックメモリ空間に割り当てられ、スタック上のデータは、いつでも取り下げることができます。したがって、パッケージングによって、データ・タイプ、ストレージ基準に基本的なオブジェクトタイプ。より便利に、塩基間の自動アンパックおよびパッキング機能、データ型変換のおかげで、対応するオブジェクトが非常に便利になる、基本的なデータタイプは自動的にメモリに設定することができ、システムが自動的に梱包されますラッパークラスとして、その後、それらのセットに追加。
一次元アレイは、私は直接は、Arrays.asListによってセットに変換する場合しかし、本LSセット演算プログラムにおいて、各行は、私は、一次元アレイの2次元配列を取得し、ループのために増強することにより、順次格納されます(S)INT []は整数間違っに準拠し、アレイ中のIは変換されてG要素が結果にラッパークラスの型があり、そのように存在する結果は、型変数のインスタンス(複数可)を示唆していない、エラーが発生したコレクションにコンパイル上記特定のコードに示すように設定、。
その他のよりよい解決策:モジュロ演算
時間の複雑さについて学ぶことはO(M * N)であるので、このソリューションは、与えられた公式の解Leetcodeです。次のように具体的なアイデアがあります:
アナログ方法、より効率的な素子転写の新たな位置の直接計算に加えて、問題の2次元アレイを移動させます。二段階での新しい位置を計算します:
- 新しい列は何ですか?
- 新ラインは何ですか?
位置3行5列の格子を仮定 I 1 = 及び J = 3 値の移行における時間 K = 88 。
ステップ1:計算新しい列の値
移行ステップkの後、k番目の列の値がすべてのステップを変更し、列の値が変化するが、移動あたりの列の数は非常に5であるため、周期運動の間に横方向のない無限格子要素は、考えられますマイナーな要素は、元の列の位置(音符列位置ではなく、正確な位置)に戻ります。
したがって、移行ステップkは、要素の列位置は(88 + 3)5%で計算することができるので、その列のための新しい場所。
抽象一般式:new_col =(J + K)%のNUM_COLS、要素のJ開始列の値は、グリッドの列の合計数をNUM_COLS。
ステップ2:新しい行の値を計算
行値変換素子は、長手方向に円運動である値は最後の列から決定するため、新しい行の値を決定するために、変更されるように、列の値は、行0の最後の列になりまれに、そして場合のみ0の数、商業的に線本明細書で使用されるモバイルコンピューティングの数に移動します。
一般式の要約:NEW_ROW =(I +(J + K)/ NUM_COLS)%のNUM_ROWS、iは開始ライン要素の値、行のNUM_ROWS番号
コードは以下の通りであります:
公衆リスト<リスト<整数>> shiftGrid(INT [] []グリッド、INT K){ int型 NUMCOLS =グリッド[0 ] .LENGTH。 int型 numRowsの数= grid.length。 // 2Dリストのセットアップ。 リスト<リスト<Integer型>> newGrid = 新しい ArrayListを<> (); 用(INTの列= 0、行<numRowsの数、行++ ){ リスト <整数> newRow = 新規のArrayList <> (); newGrid.add(newRow)。 用(INT ; COL <NUMCOLS; COL ++ COL = 0 ){ newRow。); } } のための(int型の列= 0、行<numRowsの数、行++ ){ ための(int型 COL = 0、COL <NUMCOLS; COL ++ ){ int型ニューコール=(COL + K)%のNUMCOLS。 INT wrapAroundCount =(COL + K)/ NUMCOLS。 INT newRow =(行+ wrapAroundCount)%のnumRowsの数。 newGrid.get(newRow).SET(ニューコール、グリッド[行] [COL])。 } } 戻りnewGridと、 }
注:リストのコレクションがインデックス化され、それがコレクションインデックスを介してアクセスすることができます。