前書き
二分法は、5つの基本アルゴリズムの中で分割統治アルゴリズムの1つです。二分法の考え方によれば、二分法の考え方は非常に単純です。
- 間隔を2つの部分に分割し、検索要素が属する部分を決定します。
- 間隔を更新して、最初のステップを繰り返します。間隔が1つの要素のみに短縮されるまで。
二分探索法は、実際の使用において比較的大きな制限があります。二分探索法は、次の要件に準拠する必要があります。
- 配列やリンクリストなどのシーケンシャルストレージ構造を使用する必要があります。収集は認められません。
- 順番に並べる必要があります。つまり、保管時に順番に並べます。
例えば
例:10桁の配列。aからzまでの10文字を順に格納します。これには文字xが含まれます。二分法に従って文字xを見つけます。
a | c | d | f | j | l | ん | q | バツ | と |
まず、配列の中央で要素jを見つけます(jまたはlは問題ありませんが、jを例にとります)。jはxより小さく、要素は配列に順番に格納されます。次に、xはjとzの間にある必要があります。
- jとzの間の要素nを取り、nはまだxより小さい。
- nとzの間の要素qを取り、qはxより小さい。
- q〜zの真ん中にある要素を取り、xを見つけます。
上記は、バイナリ検索の簡単な例です。コード実装を使用する場合は、再帰を使用する必要があります。困難は次のとおりです。
- 終了条件を決定する方法。
- 中央値が2つある場合は、どちらを採用するか。
- 最後の間隔に2つの要素しかない場合に正しい値を取得する方法。
応用
次に例を示します。
重複の数を見つける:
n + 1の整数を含む配列numがあり、その数がすべて1〜n(1とnを含む)の場合、少なくとも1つの整数が繰り返されることがわかります。繰り返される整数が1つしかないと仮定して、繰り返される数を見つけます。
例1:
输入: [1,3,4,2,2]
输出: 2
ソース:LeetCode
リンク:元のタイトルリンク
アイデア:
タイトルから次の条件を抽出できます。
- 繰り返される数は1つだけです。
- すべての数値はnの範囲です。
- 合計n + 1個の要素があります。
質問は、繰り返される要素の値を見つけることだけを必要とし、要素の位置を気にしないので、二分法を使用してそれを見つけることができます。
すべての要素は1からnの間であり、1つの要素のみが繰り返されるため、そのような繰り返し数がないと仮定すると、この配列のn / 2未満の要素の数は、n / 2より大きい要素の数と同じになります。 。この数値を加算すると、バランスが崩れ、n / 2より大きい間隔に属するか、n / 2より小さい間隔に属するかを判断できます。
これをキーとして繰り返し、最後にこの繰り返された要素の値を取得します。
コード:
package leetcode;
public class FindDuplicate {
int num = 0;
public int findDuplicate(int[] nums) {
int minLine = 1;
int maxLine = nums.length-1;
dichotomySearch(minLine,maxLine,nums);
return num;
}
public void dichotomySearch(int minLine,int maxLine,int[] nums) {
int flag = 0;
int median = (minLine + maxLine)/2;
//only two number
if(minLine==maxLine-1||minLine==maxLine){
for (int i = 0; i < nums.length; i++) {
if (nums[i]==minLine){
flag++;
}
}
if (flag>1){
num = minLine;
}else {
num = maxLine;
}
return;
}
for (int i = 0; i < nums.length; i++) {
if (nums[i] < median && nums[i]>=minLine){
flag--;
}
if (nums[i] > median && nums[i]<=maxLine){
flag++;
}
}
if (flag<=0){
maxLine = median;
dichotomySearch(minLine,maxLine,nums);
}else {
minLine = median;
dichotomySearch(minLine,maxLine,nums);
}
}
public static void main(String[] args) {
int[] nums = {1,1};
FindDuplicate findDuplicate = new FindDuplicate();
System.out.println(findDuplicate.findDuplicate(nums));
}
}