20.4.10配列の単純な回転

2つのインジケーターがなぜそれほど貧弱なのかわかりません。コードの時間の複雑さはO(n)で、空間の複雑さはO(1)です。

タイトル

配列を指定して、配列内の要素をk桁右に移動します。ここで、kは負ではない数です。

例1:
入力:[1,2,3,4,5,6,7]およびk = 3
出力:[5,6,7,1,2,3,4]
説明:
1ステップ右に回転します:[ 7,1,2,3,4,5,6]
右に2ステップ回転:[6,7,1,2,3,4,5]
右に3ステップ回転:[5,6,7,1、 2,3,4]

例2:
入力:[-1、-100,3,99]およびk = 2
出力:[3,99、-1、-100]
説明:
右に1ステップ回転:[99、-1、-100、 3]
右に2ステップ回転:[3,99、-1、-100]

注:
できるだけ多くの解決策を考えてくださいこの問題を解決するには、少なくとも3つの方法があります。
空間複雑度O(1)のin-situアルゴリズムが必要です。

問題解決のアイデア

  1. 暴力的な解決策は、すべて、時間の複雑さO(kn)、2層ループ、最初の層の回数、2番目の層が一度に1ビットずつアレイを繰り返し移動することです。
  2. トリックを考えて、どういうわけかリング交換を実現しました。
  3. 実現のアイデアは、最初の番号から始めて、それを最後の位置に置き、次に置換された番号がこの時点で消えるということです。事前に保存する必要があります。
  4. 格納された番号の終了位置を探し続け、3の操作を合計n回繰り返します。nの番号しかないためです。
  5. もちろん、numsには6つの数字があり、kが2の場合、1が3に変更され、3が5に変更され、5が1に変更されるなど、特別な状況があります。このまま続行すると、2、4は操作されません。したがって、5を1に変更すると、1は次の数値、つまり2になります。操作を繰り返し続けるだけです。

コードのアイデア

  1. 最初に特殊なケースを削除します。たとえば、k%nums.size()== 0の場合は、6要素の配列が12ビットまたは24ビットシフトされるため、実際に移動する必要はありません。
  2. n回ループ、indexは現在のトラバーサルのインデックス、flagは繰り返されない開始点のインデックス(ソリューション5の問題を解決するために使用)、save1は置き換えられた位置を保存する要素、save2は他のものを置き換える要素(とにかく、私は1つの保存を使い始めたばかりですが、機能しませんでした。2つで解決しました)。
  3. ループが開始するたびに、save1は置き換えられた要素を保存し、この位置の値(save2と等しい)を更新してから、インデックスインデックスをsave1が置き換えられる位置に更新します。
  4. インデックスが更新された後、インデックスが開始インデックスフラグと等しい場合、インデックスと開始インデックスインデックスの両方を+1で更新する必要があります。この要素は移動されているため、save1はこの置き換えられた要素を保存する必要はありません。次の要素に直接更新してください。開始位置がsave2に割り当てられたら。

コード

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        if(nums.size() == 0 || k == 0 || k%nums.size() == 0) return;

        for(int i = 1, index = 0, flag = 0, save1, save2 = nums[0]; i <= nums.size(); i++){
            save1 = nums[(index + k) % nums.size()];
            nums[(index + k) % nums.size()] = save2;
            index = (index + k) % nums.size();
            if(index == flag){
                save1 = nums[++index];
                flag = index;
            }
            save2 = save1;
        }
    }
};

おすすめ

転載: www.cnblogs.com/wasi-991017/p/12676114.html