目次
1.定規法とは
2 ポインター手法は、配列または文字列関連の問題を解決するために使用される一般的なアルゴリズム手法です。この方法では、2 つのポインター (ルーラー) を使用して配列または文字列の異なる位置を指し、2 つのポインターの位置を調整することで問題を解決します。
ルーラー メソッドの基本的な考え方は、配列または文字列をトラバースすることによって、問題を 2 つのポインター間の特定の関係に変換することです。ポインタの位置を移動することにより、問題の要件を満たすように 2 つのポインタ間の距離が常に調整されます。
ルーラー メソッドの一般的なアプリケーション シナリオには次のようなものがあります。
- スライディング ウィンドウの問題: 2 つのポインターを維持してウィンドウを定義し、ウィンドウの位置とサイズを継続的に調整することで関連する問題を解決します。たとえば、最小のカバー部分文字列、最長の非繰り返し文字部分文字列などの問題です。
- 高速ポインターと低速ポインターの問題: 2 つのポインター (高速ポインター 1 つと低速ポインター 1 つ) を維持し、さまざまな移動戦略を通じて、関連する問題を解決します。たとえば、連結リストにリングがあるかどうかを判断したり、連結リストの中間ノードを見つけたりします。
- 2 つの順序付けされた配列をマージする問題: 2 つの順序付けされた配列の終端をそれぞれ指す 2 つのポインターを維持し、サイズを比較して、大きい要素をマージされた配列に順番に入れることによって、マージ問題は解決されます。
定規法の利点は、そのシンプルかつ効率的なアルゴリズムのアイデアにあり、多くの問題を解決するのに適しています。2 つのポインターの開始位置を合理的に設定し、問題の要件に応じてポインターの移動戦略を調整することで、一部の複雑な配列または文字列関連の問題を迅速に解決できます。
2. 定規の使い方
以下は、ルーラー メソッドを使用してスライディング ウィンドウ問題を解決する (最小カバー部分文字列を見つける) Java サンプル コードの例です。
import java.util.HashMap;
import java.util.Map;
public class TwoPointersExample {
public static String minWindow(String s, String t) {
// 使用HashMap存储目标字符串中每个字符的出现次数
Map<Character, Integer> target = new HashMap<>();
for (char c : t.toCharArray()) {
target.put(c, target.getOrDefault(c, 0) + 1);
}
int left = 0; // 左指针
int right = 0; // 右指针
int count = 0; // 计数器,用于记录满足条件的字符个数
int minLen = Integer.MAX_VALUE; // 最小覆盖子串的长度
int minStart = 0; // 最小覆盖子串的起始位置
Map<Character, Integer> window = new HashMap<>(); // 存储当前窗口内的字符及其出现次数
while (right < s.length()) {
char c = s.charAt(right); // 移动右指针,扩展窗口
window.put(c, window.getOrDefault(c, 0) + 1);
if (target.containsKey(c) && window.get(c).intValue() == target.get(c).intValue()) {
// 当窗口内某个字符数量满足要求时,更新计数器
count++;
}
while (count == target.size()) {
// 当窗口内的字符满足要求时,移动左指针,缩小窗口
if (right - left + 1 < minLen) {
minLen = right - left + 1;
minStart = left;
}
char leftChar = s.charAt(left);
window.put(leftChar, window.get(leftChar) - 1);
if (target.containsKey(leftChar) && window.get(leftChar).intValue() < target.get(leftChar).intValue()) {
// 当窗口内某个字符数量不满足要求时,更新计数器
count--;
}
left++;
}
right++;
}
return minLen == Integer.MAX_VALUE ? "" : s.substring(minStart, minStart + minLen);
}
public static void main(String[] args) {
String s = "ADOBECODEBANC";
String t = "ABC";
String result = minWindow(s, t);
System.out.println("最小覆盖子串为: " + result);
}
}
上記のコードは、スライディング ウィンドウ (左ポインターと右ポインター) を維持し、HashMap を使用してウィンドウ内の文字の出現数をカウントします。ウィンドウ内の文字が条件を満たしたら、左ポインタを移動してウィンドウを縮小し、カバーされる最小部分文字列の開始位置と長さを記録します。最後に、カバーする最小の部分文字列を返します。定規法の代表的な応用例です。
3. 定規法のメリットと応用シーン
定規法の利点は次のとおりです。
-
低い時間計算量: 通常、ルーラー メソッドは 2 つのポインターを維持することによって配列または文字列を走査し、各要素は最大 1 回処理されるため、時間計算量は通常 O(N) (N は要素の数) です。
-
スペースの複雑さが低い: ルーラー メソッドでは、通常、一定レベルの追加スペース (2 つのポインターなど) を使用するだけでよく、追加の配列やデータ構造は必要ありません。
-
アルゴリズムの考え方はシンプルです。定規メソッドの考え方は比較的直観的で、理解し、実装するのが簡単です。
ルーラー メソッドは次のシナリオに適用できます。
-
スライディング ウィンドウ問題: 定規法は、スライディング ウィンドウ問題、つまり固定サイズのウィンドウ内をスライドさせ、ウィンドウの位置とサイズを調整することで問題を解決するためによく使用されます。たとえば、カバーする最小の部分文字列や、連続する最長の部分配列などを見つけるなどの問題です。
-
高速ポインタと低速ポインタの問題: 定規法は、高速ポインタと低速ポインタの問題を解決するためにもよく使用されます。高速ポインタと低速ポインタの 2 つのポインタを維持することにより、関連する問題はさまざまな移動戦略を通じて解決されます。たとえば、連結リストにリングがあるかどうかを判断したり、連結リストの中間ノードを見つけたりします。
-
順序付き配列のマージ問題: ルーラー メソッドを使用すると、2 つの順序付き配列の末尾を指す 2 つのポインターを維持し、サイズを比較して大きい要素を 1 つずつマージされた配列に入れることで、2 つの順序付き配列をマージできます。 、マージ問題を解決します。
一般に、ルーラー メソッドは、配列または文字列を走査し、2 つのポインターの位置を維持することで問題を解決する必要があるシナリオに適しています。その利点はそのシンプルさと高効率にあり、さまざまな現実的な問題の解決に適しています。