LeetCode力ボタン75.色の分類
4541 ワード
タイトル説明(中難易度)
配列を与えて、含まれる数は0,1,2の1つだけで、これらの数字を小さいものから大きいものに並べ替えます.
解法一
タイトルの下のFollow upは1つの解法に言及して、1回の配列を遍歴して、0の出現の回数を統計して、1の出現の回数、2の出現の回数、それから更に配列を遍歴して、回数によって、配列の要素を相応の値に変えます.もちろん私たちは0の回数と1の回数を記録するだけで、残りは2の回数です.
時間複雑度:O(n).
空間複雑度:O(1).
解法二
上のアルゴリズムでは,配列を2回遍歴し,1回だけ遍歴する方法を考えてみよう.単純な場合、0と1の2つの数しか含まれていないとしたら、どうすればいいのでしょうか.
元の配列が1 0 1 0だと仮定すると、ポインタを1つ使うことができます.zero_positionは、そのポインタが指す位置を意味し、前の位置はすべて0である.それからもう一つのポインタiでこの配列を巡り、0を見つけたら0を現在のzero_に置きます.positionが指す位置、zero_移動後.Zでzero_を表すposition、下の遍歴過程を見てください.
私たちの現在の問題に戻って、私たちは3つの数字を持っています.それでは、2つのポインタを使うことができます.1つはzeroです.positionは、前と同じように、前の位置をすべて0にします.もう一つのポインタ、two_position、ここに注意して、その後ろの位置はすべて2を保存します.そして配列全体を巡るだけでいいです.
下辺は1つの遍歴の過程の中の図を描いて、理解して、Zの前はすべて0を保存して、Tの後ろはすべて2を保存します.
時間複雑度:O(n).
空間複雑度:O(1).
解法三
解法2には全部で3つの数があり、自然に3つの部分に分けられ、2つのポインタで間隔を置くことができますが、5つの数があれば、解法2は適用されないかもしれません.leetcodeで別の解法を発見し,ここの解法2を参考に,大問題化小の思想を用いた.
3つのポインタn 0,n 1,n 2を用いて,配列された配列の現在の0の末尾,1の末尾,2の末尾をそれぞれ表す.
次に、現在iの位置を0に遍歴し、n 2ポインタを後ろに移動し、現在の数字を2に設定し、n 1ポインタを後ろに移動し、現在の数字を1に設定し、n 0ポインタを後ろに移動し、現在の数字を0に設定するだけです.
次に、iが指す0を現在の順序の0に挿入する位置の末尾に達する.
そのため、前に新しい数字が挿入されているため、必ず数字が上書きされます.ポインタを後ろに移動した後、対応するポインタの位置を対応する数にします.n 2ポインタを後ろに移動して2にします.n 1ポインタを後ろに移動して1にします.例えば、前に3つの2があった場合、前に1つの数字が挿入されているため、1つの2が上書きされるので、1つの2を追加します.
時間複雑度:O(n).
空間複雑度:O(1).
総
解法二ポインタを利用して、元の空間に物を保存するのは古典的です.解法三、実は本質は私たちがよく使う再帰思想で、まず小さな問題が解決したと仮定して、それからもう一つの数がどう操作すればいいかを仮定します.
もっと詳しくて分かりやすい問題の詳細は
leetcode.wang .
配列を与えて、含まれる数は0,1,2の1つだけで、これらの数字を小さいものから大きいものに並べ替えます.
解法一
タイトルの下のFollow upは1つの解法に言及して、1回の配列を遍歴して、0の出現の回数を統計して、1の出現の回数、2の出現の回数、それから更に配列を遍歴して、回数によって、配列の要素を相応の値に変えます.もちろん私たちは0の回数と1の回数を記録するだけで、残りは2の回数です.
public void sortColors(int[] nums) {
int zero_count = 0;
int one_count = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 0) {
zero_count++;
}
if (nums[i] == 1) {
one_count++;
}
}
for (int i = 0; i < nums.length; i++) {
if (zero_count > 0) {
nums[i] = 0;
zero_count--;
} else if (one_count > 0) {
nums[i] = 1;
one_count--;
} else {
nums[i] = 2;
}
}
}
時間複雑度:O(n).
空間複雑度:O(1).
解法二
上のアルゴリズムでは,配列を2回遍歴し,1回だけ遍歴する方法を考えてみよう.単純な場合、0と1の2つの数しか含まれていないとしたら、どうすればいいのでしょうか.
元の配列が1 0 1 0だと仮定すると、ポインタを1つ使うことができます.zero_positionは、そのポインタが指す位置を意味し、前の位置はすべて0である.それからもう一つのポインタiでこの配列を巡り、0を見つけたら0を現在のzero_に置きます.positionが指す位置、zero_移動後.Zでzero_を表すposition、下の遍歴過程を見てください.
1 0 1 1 0 Z,i 0 ,i
^
Z
i
1 0 1 1 0 0, Z 0, Z ,Z
^ ^
Z i
0 1 1 1 0 i
^
i
Z
0 1 1 1 0 i
^ ^
Z i
0 1 1 1 0 i
^ ^
Z i
0 1 1 1 0 0, Z 0, Z ,Z
^ ^
Z i
0 0 1 1 1
^ ^
Z i
私たちの現在の問題に戻って、私たちは3つの数字を持っています.それでは、2つのポインタを使うことができます.1つはzeroです.positionは、前と同じように、前の位置をすべて0にします.もう一つのポインタ、two_position、ここに注意して、その後ろの位置はすべて2を保存します.そして配列全体を巡るだけでいいです.
下辺は1つの遍歴の過程の中の図を描いて、理解して、Zの前はすべて0を保存して、Tの後ろはすべて2を保存します.
0 1 0 2 1 2 2 2
^ ^ ^
Z i T
public void sortColors(int[] nums) {
int zero_position = 0;
int two_position = nums.length - 1;
for (int i = 0; i <= two_position; i++) {
if (nums[i] == 0) {
//
int temp = nums[zero_position];
// 0
nums[zero_position] = 0;
//
nums[i] = temp;
//
zero_position++;
} else if (nums[i] == 2) {
//
int temp = nums[two_position];
// 2
nums[two_position] = 2;
//
nums[i] = temp;
//
two_position--;
// , i ,
// , for i++
// i--
// zero_position ,
//
i--;
}
}
}
時間複雑度:O(n).
空間複雑度:O(1).
解法三
解法2には全部で3つの数があり、自然に3つの部分に分けられ、2つのポインタで間隔を置くことができますが、5つの数があれば、解法2は適用されないかもしれません.leetcodeで別の解法を発見し,ここの解法2を参考に,大問題化小の思想を用いた.
3つのポインタn 0,n 1,n 2を用いて,配列された配列の現在の0の末尾,1の末尾,2の末尾をそれぞれ表す.
0 0 1 2 2 2 0 2 1
^ ^ ^ ^
n0 n1 n2 i
次に、現在iの位置を0に遍歴し、n 2ポインタを後ろに移動し、現在の数字を2に設定し、n 1ポインタを後ろに移動し、現在の数字を1に設定し、n 0ポインタを後ろに移動し、現在の数字を0に設定するだけです.
0 0 1 2 2 2 2 2 1 n2
^ ^ ^
n0 n1 i
n2
0 0 1 1 2 2 2 2 1 n1
^ ^ ^
n0 n1 i
n2
0 0 0 1 2 2 2 2 1 n0
^ ^ ^
n0 n1 i
n2
次に、iが指す0を現在の順序の0に挿入する位置の末尾に達する.
そのため、前に新しい数字が挿入されているため、必ず数字が上書きされます.ポインタを後ろに移動した後、対応するポインタの位置を対応する数にします.n 2ポインタを後ろに移動して2にします.n 1ポインタを後ろに移動して1にします.例えば、前に3つの2があった場合、前に1つの数字が挿入されているため、1つの2が上書きされるので、1つの2を追加します.
public void sortColors(int[] nums) {
int n0 = -1, n1 = -1, n2 = -1;
int n = nums.length;
for (int i = 0; i < n; i++) {
if (nums[i] == 0) {
n2++;
nums[n2] = 2;
n1++;
nums[n1] = 1;
n0++;
nums[n0] = 0;
} else if (nums[i] == 1) {
n2++;
nums[n2] = 2;
n1++;
nums[n1] = 1;
} else if (nums[i] == 2) {
n2++;
nums[n2] = 2;
}
}
}
時間複雑度:O(n).
空間複雑度:O(1).
総
解法二ポインタを利用して、元の空間に物を保存するのは古典的です.解法三、実は本質は私たちがよく使う再帰思想で、まず小さな問題が解決したと仮定して、それからもう一つの数がどう操作すればいいかを仮定します.
もっと詳しくて分かりやすい問題の詳細は
leetcode.wang .