287.重複を探す
- 元の配列は変更できません(配列が読み取り専用であると想定)。
- 追加のO(1)スペースのみを使用できます 。
- 時間の複雑さはO(n 2)未満です 。
- 配列には繰り返し数が1つしかありませんが、複数回出現する可能性があります。
元の配列は変更できず、余分なO1スペースしか使用しないため、マップレコードを使用したり、新しい配列を維持したりすることはできません
時間の複雑さはn2以内であるため、ブルートフォース検索も望ましくありません。
データ範囲は1〜n-1であるため、配列が境界を越えないことが保証されるため、リンクリストの高速および低速のポインター検索アルゴリズムが使用されます
https://www.cnblogs.com/fankongkong/p/7007869.html
1. 示されているように、高速ポインターが低速ポインターよりもリングを1つだけ取る場合
2.示されているように、初めて会議するとき
3.この時点で、図に示すように、先頭にすばやく再割り当てします
4. 2回歩くと、リングの入口ノードが見つかります
ステップを再編成して問題を解決する
a。最初のステップは、リング内のミーティングポイントを見つけることです。fastとslowを使用して、リンクリストの先頭をポイントします。slowは一度に1ステップずつ、fastは一度に2ステップずつ、fast == slowがリングでミーティングポイントを見つけるまで続きます。
b。2番目のステップは、リングの入り口を見つけることです。前のステップを実行し、fast == slowの場合、fastによって渡されるノードの数は2x、slowによって渡されるノードの数はx、リング内にn個のノードがあり、fastは2x = n + x; nよりも低速で歩く= x;
スローが実際にリングの一歩を踏み出し、リンクされたリストの先頭をファストポイントにすると、スローの位置は変更されないままであることがわかります。
次の図に示すように、リンクリストの先頭からリングインターフェースまでの距離がyであるとすると、xyは、リンク内を移動したリンクリストの先頭yを除いて低速ポインターが移動した距離を表し、低速でyステップ歩きます。このとき、高速ノードと低速ノードが交わると、fast == slow、x-y + y = x = n、つまり、slowはリングの入り口を指します。
442.配列内の重複データ
より良い解決策は、鳩の巣の原則 + データの交換です
余分なスペースとO(n)時間の複雑さなし
下付き文字i-1の位置にサイズiの数を入れ、行が間違った後の残りの位置は冗長です。
位置iの数値kの場合、k!= i-1なので、kをk-1の位置にスローし、変更された数値がi-1かどうかを確認するか、または位置が正しい場合は(ソートアルゴリズムのように)変更を続けます。次の位置に移動します。
すべての位置が処理されたら、もう一度スキャンして、位置と一致しない数値と数値が余分な数値であることを確認します。余分なスペースを使用できないため、追加のメモリなしでスワップまたはスワップします(プラスまたはマイナスのスワップも可能です)。
public List <Integer> findDuplicates(int [] nums){ Set <Integer> res = new HashSet <>(); for(int i = 0; i <nums.length; i ++){ while(nums [i]!= i + 1){ if(nums [i] == nums [nums [i] -1]){ res.add(nums [i]); ブレーク; } swap(nums、i、nums [i] -1); } } System.out.println(res.toString()); 新しいArrayList <>(res);を返します。 } public void swap(int [] nums、int a、int b){ nums [a] ^ = nums [b]; nums [b] ^ = nums [a]; nums [a] ^ = nums [b]; }