Dieser Artikel vermittelt Ihnen relevantes Wissen über Java. Die Halbierungsmethode ist ein sehr effizienter Algorithmus, der häufig im Computersuchprozess verwendet wird. Im Folgenden werden die Grundidee und die Umsetzung der Dichotomie anhand von Beispielen ausführlich erläutert. Ich hoffe, dass dies für alle hilfreich ist.
Empfohlenes Lernen: „Java-Video-Tutorial“
Idee:
Code
class Solution { public int search(int[] arr, int t) { if (arr == null || arr.length < 1) { return -1; } int l = 0; int r = arr.length - 1; while (l <= r) { int m = l + ((r - l) >> 1); if (arr[m] == t) { return m; } else if (arr[m] > t) { r = m - 1; } else { l = m + 1; } } return -1; } }
Zeitkomplexität O(logN)
. O(logN)
。
示例 1:
输入: nums = [1,3,5,6], target = 5
输出: 2
说明:如果要在num
这个数组中插入 5 这个元素,应该是插入在元素 3 和 元素 5 之间的位置,即 2 号位置。
示例 2:
输入: nums = [1,3,5,6], target = 2
输出: 1
说明:如果要在num
这个数组中插入 2 这个元素,应该是插入在元素 1 和 元素 3 之间的位置,即 1 号位置。
示例 3:
输入: nums = [1,3,5,6], target = 7
输出: 4
说明:如果要在num
这个数组中插入 7 这个元素,应该是插入在数组末尾,即 4 号位置。
通过上述示例可以知道,这题本质上就是求在一个有序数组中,找大于等于某个数最左侧的位置,如果不存在,就返回数组长度(表示插入在最末尾位置)
我们只需要在上例基础上进行简单改动即可,上例中,我们找到满足条件的位置就直接return
了
if (arr[m] == t) { return m; }
在本问题中,因为要找到最左侧的位置,所以,在遇到相等的时候,只需要先把位置记录下来,不用直接返回,然后继续去左侧找是否还有满足条件的更左边的位置。
同时,在遇到arr[m] > t
条件下,也需要记录下此时的m
位置,因为这也可能是满足条件的位置。
代码:
class Solution { public static int searchInsert(int[] arr, int t) { int ans = arr.length; int l = 0; int r = arr.length - 1; while (l <= r) { int m = l + ((r - l)>>1); if (arr[m] >= t) { ans = m; r = m - 1; } else { l = m + 1; } } return ans; } }
整个算法的时间复杂度是O(logN)
。
思路
本题也是用二分来解,当通过二分找到某个元素的时候,不急着返回,而是继续往左(右)找,看能否找到更左(右)位置匹配的值。
代码如下:
class Solution { public static int[] searchRange(int[] arr, int t) { if (arr == null || arr.length < 1) { return new int[]{-1, -1}; } return new int[]{left(arr,t),right(arr,t)}; } public static int left(int[] arr, int t) { if (arr == null || arr.length < 1) { return -1; } int ans = -1; int l = 0; int r = arr.length - 1; while (l <= r) { int m = l + ((r - l) >> 1); if (arr[m] == t) { ans = m; r = m - 1; } else if (arr[m] < t) { l = m +1; } else { // arr[m] > t r = m - 1; } } return ans; } public static int right(int[] arr, int t) { if (arr == null || arr.length < 1) { return -1; } int ans = -1; int l = 0; int r = arr.length - 1; while (l <= r) { int m = l + ((r - l) >> 1); if (arr[m] == t) { ans = m; l = m + 1; } else if (arr[m] < t) { l = m +1; } else { // arr[m] > t r = m - 1; } } return ans; } }
时间复杂度 O(logN)
。
思路
假设数组长度为N
,首先判断0
号位置的数和N-1
位置的数是不是峰值位置。
0
号位置只需要和1
号位置比较,如果0
号位置大,0
号位置就是峰值位置,可以直接返回。
N-1
号位置只需要和N-2
号位置比较,如果N-1
号位置大,N-1
号位置就是峰值位置,可以直接返回。
如果0
号位置和N-1
在上轮比较中均是最小值,那么数组的样子必然是如下情况:
由上图可知,[0..1]
区间内是增长趋势, [N-2...N-1]
区间内是下降趋势。
那么峰值位置必在[1...N-2]
之间出现。
此时可以通过二分来找峰值位置,先来到中点位置,假设为mid
,如果中点位置的值比左右两边的值都大:
arr[mid] > arr[mid+1] && arr[mid] > arr[mid-1]
则mid
numDas in dieses Array eingefügte Element 5 sollte zwischen Element 3 und Element 5, also Position 2, eingefügt werden. 🎜🎜Beispiel 2:🎜🎜Eingabe: nums = [1,3,5,6], Ziel = 2🎜🎜Ausgabe: 1🎜🎜Erläuterung: Wenn Sie 2 in das Array <code>num
einfügen möchten Das Element sollte zwischen Element 1 und Element 3, also Position 1, eingefügt werden. 🎜🎜Beispiel 3:🎜🎜Eingabe: nums = [1,3,5,6], Ziel = 7🎜🎜Ausgabe: 4🎜🎜Erläuterung: Wenn Sie 7 in das Array num
einfügen möchten Das Element sollte am Ende des Arrays eingefügt werden, also an Position 4. 🎜🎜Aus dem obigen Beispiel können Sie erkennen, dass der Kern dieser Frage darin besteht, die Position ganz links in einem geordneten Array zu finden, die größer oder gleich einer bestimmten Zahl ist. Wenn sie nicht vorhanden ist, geben Sie die Länge des Arrays zurück (angeben). dass es am Ende eingefügt wird (Position)🎜🎜Wir müssen nur einfache Änderungen basierend auf dem obigen Beispiel vornehmen. Wenn wir im obigen Beispiel die Position finden, die die Bedingungen erfüllt, kehren wir direkt zurück🎜public class LeetCode_0162_FindPeakElement {
public static int findPeakElement(int[] nums) {
if (nums.length == 1) {
return 0;
}
int l = 0;
int r = nums.length - 1;
if (nums[l] > nums[l + 1]) {
return l;
}
if (nums[r] > nums[r - 1]) {
return r;
}
l = l + 1;
r = r - 1;
while (l <= r) {
int mid = l + ((r - l) >> 1);
if (nums[mid] > nums[mid + 1] && nums[mid] > nums[mid - 1]) {
return mid;
}
if (nums[mid] < nums[mid + 1]) {
l = mid + 1;
} else if (nums[mid] < nums[mid - 1]) {
r = mid - 1;
}
}
return -1;
}
}
🎜In dieser Frage müssen Sie die Position ganz links finden. Wenn Sie also auf Gleichheit stoßen, müssen Sie zunächst nur die Position aufzeichnen, ohne direkt zurückzukehren, und dann weiter nach links gehen, um herauszufinden, ob sie vorhanden ist ist eine linke Position, die die Bedingungen erfüllt. 🎜🎜Wenn Sie auf arr[m] > t
stoßen, müssen Sie zu diesem Zeitpunkt auch die Position von m
aufzeichnen, da dies der Fall ist kann auch ein Ort sein, der die Bedingungen erfüllt. 🎜🎜Code: 🎜rrreee🎜Die zeitliche Komplexität des gesamten Algorithmus beträgt O(logN)
. 🎜🎜Finden Sie die erste und letzte Position eines Elements in einem sortierten Array🎜🎜🎜🎜Denken🎜🎜Diese Frage wird auch durch binäre Division gelöst. Wenn ein Element durch binäre Division gefunden wird, eilen Sie nicht zurück, sondern suchen Sie weiter nach links (rechts), um zu sehen, ob Sie etwas weiter finden können nach links (rechts) ) Positionsübereinstimmungswert. 🎜🎜Der Code lautet wie folgt: 🎜rrreee🎜Zeitkomplexität O(logN)
. 🎜🎜Lokales Maximalproblem🎜🎜🎜🎜Ideen🎜🎜 Angenommen Stellen Sie sicher, dass die Länge des Arrays N
ist. Bestimmen Sie zunächst, ob die Zahl an Position 0
und die Zahl an Position N-1
Spitzenpositionen sind. 🎜🎜Die 0
-Position muss nur mit der 1
-Position verglichen werden. Wenn die 0
-Position größer ist, wird die 0
-Position verwendet. code> position Dies ist die Spitzenposition und kann direkt zurückgegeben werden. 🎜🎜Die N-1
-Position muss nur mit der N-2
-Position verglichen werden. Wenn die N-1
-Position größer ist, N Position -1
ist die Spitzenposition und kann direkt zurückgegeben werden. 🎜🎜Wenn die Position 0
und N-1
beide Minimalwerte in der letzten Vergleichsrunde sind, dann muss das Array wie folgt aussehen: 🎜🎜🎜🎜Wie aus dem obigen Bild ersichtlich ist, [ 0..1] Das Code>-Intervall zeigt einen wachsenden Trend und das <code>[N-2...N-1]
-Intervall weist einen Abwärtstrend auf. 🎜🎜Dann muss die Peak-Position zwischen [1...N-2]
liegen. 🎜🎜Zu diesem Zeitpunkt können Sie die Spitzenposition durch Halbierung ermitteln. Gehen Sie zunächst zur Mittelpunktposition, vorausgesetzt, dass diese mitte
ist als die Werte auf der linken und rechten Seite:🎜rrreee🎜Die mittlere
-Position ist die Spitzenposition und wird direkt zurückgegeben. 🎜🎜Ansonsten gibt es die folgenden zwei Situationen: 🎜🎜Fall 1: Der Wert der Mittelposition ist kleiner als der Wert der Mittelposition 1🎜趋势如下图:
则在[1...(mid-1)]
区间内继续二分。
情况二:mid 位置的值比 mid + 1 位置的值小
趋势是:
则在[(mid+1)...(N-2)]
区间内继续上述二分。
完整代码
public class LeetCode_0162_FindPeakElement { public static int findPeakElement(int[] nums) { if (nums.length == 1) { return 0; } int l = 0; int r = nums.length - 1; if (nums[l] > nums[l + 1]) { return l; } if (nums[r] > nums[r - 1]) { return r; } l = l + 1; r = r - 1; while (l <= r) { int mid = l + ((r - l) >> 1); if (nums[mid] > nums[mid + 1] && nums[mid] > nums[mid - 1]) { return mid; } if (nums[mid] < nums[mid + 1]) { l = mid + 1; } else if (nums[mid] < nums[mid - 1]) { r = mid - 1; } } return -1; } }
时间复杂度O(logN)
。
推荐学习:《java视频教程》
Das obige ist der detaillierte Inhalt vonVerstehen Sie kurz die Grundideen und die Implementierung der Dichotomie in Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!