本文小編為大家詳細(xì)介紹“Java二分法如何實(shí)現(xiàn)”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“Java二分法如何實(shí)現(xiàn)”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識(shí)吧。
創(chuàng)新互聯(lián)主要從事網(wǎng)頁設(shè)計(jì)、PC網(wǎng)站建設(shè)(電腦版網(wǎng)站建設(shè))、wap網(wǎng)站建設(shè)(手機(jī)版網(wǎng)站建設(shè))、響應(yīng)式網(wǎng)站設(shè)計(jì)、程序開發(fā)、網(wǎng)站優(yōu)化、微網(wǎng)站、小程序制作等,憑借多年來在互聯(lián)網(wǎng)的打拼,我們在互聯(lián)網(wǎng)網(wǎng)站建設(shè)行業(yè)積累了豐富的成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì)、網(wǎng)絡(luò)營銷經(jīng)驗(yàn),集策劃、開發(fā)、設(shè)計(jì)、營銷、管理等多方位專業(yè)化運(yùn)作于一體。
思路:
由于是有序數(shù)組,可以先得到中點(diǎn)位置,中點(diǎn)可以把數(shù)組分為左右半邊。
如果中點(diǎn)位置的值等于目標(biāo)值,直接返回中點(diǎn)位置。
如果中點(diǎn)位置的值小于目標(biāo)值,則去數(shù)組中點(diǎn)左側(cè)按同樣的方式尋找。
如果中點(diǎn)位置的值大于目標(biāo)值,則取數(shù)組中點(diǎn)右側(cè)按同樣的方式尋找。
如果最后沒有找到,則返回:-1。
代碼
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; } }
時(shí)間復(fù)雜度 O(logN)
。
示例 1:
輸入: nums = [1,3,5,6], target = 5
輸出: 2
說明:如果要在num
這個(gè)數(shù)組中插入 5 這個(gè)元素,應(yīng)該是插入在元素 3 和 元素 5 之間的位置,即 2 號(hào)位置。
示例 2:
輸入: nums = [1,3,5,6], target = 2
輸出: 1
說明:如果要在num
這個(gè)數(shù)組中插入 2 這個(gè)元素,應(yīng)該是插入在元素 1 和 元素 3 之間的位置,即 1 號(hào)位置。
示例 3:
輸入: nums = [1,3,5,6], target = 7
輸出: 4
說明:如果要在num
這個(gè)數(shù)組中插入 7 這個(gè)元素,應(yīng)該是插入在數(shù)組末尾,即 4 號(hào)位置。
通過上述示例可以知道,這題本質(zhì)上就是求在一個(gè)有序數(shù)組中,找大于等于某個(gè)數(shù)最左側(cè)的位置,如果不存在,就返回?cái)?shù)組長度(表示插入在最末尾位置)
我們只需要在上例基礎(chǔ)上進(jìn)行簡單改動(dòng)即可,上例中,我們找到滿足條件的位置就直接return
了
if (arr[m] == t) { return m; }
在本問題中,因?yàn)橐业阶钭髠?cè)的位置,所以,在遇到相等的時(shí)候,只需要先把位置記錄下來,不用直接返回,然后繼續(xù)去左側(cè)找是否還有滿足條件的更左邊的位置。
同時(shí),在遇到arr[m] > t
條件下,也需要記錄下此時(shí)的m
位置,因?yàn)檫@也可能是滿足條件的位置。
代碼:
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; } }
整個(gè)算法的時(shí)間復(fù)雜度是O(logN)
。
思路
本題也是用二分來解,當(dāng)通過二分找到某個(gè)元素的時(shí)候,不急著返回,而是繼續(xù)往左(右)找,看能否找到更左(右)位置匹配的值。
代碼如下:
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; } }
時(shí)間復(fù)雜度 O(logN)
。
思路
假設(shè)數(shù)組長度為N
,首先判斷0
號(hào)位置的數(shù)和N-1
位置的數(shù)是不是峰值位置。
0
號(hào)位置只需要和1
號(hào)位置比較,如果0
號(hào)位置大,0
號(hào)位置就是峰值位置,可以直接返回。
N-1
號(hào)位置只需要和N-2
號(hào)位置比較,如果N-1
號(hào)位置大,N-1
號(hào)位置就是峰值位置,可以直接返回。
如果0
號(hào)位置和N-1
在上輪比較中均是最小值,那么數(shù)組的樣子必然是如下情況:
由上圖可知,[0..1]
區(qū)間內(nèi)是增長趨勢, [N-2...N-1]
區(qū)間內(nèi)是下降趨勢。
那么峰值位置必在[1...N-2]
之間出現(xiàn)。
此時(shí)可以通過二分來找峰值位置,先來到中點(diǎn)位置,假設(shè)為mid
,如果中點(diǎn)位置的值比左右兩邊的值都大:
arr[mid] > arr[mid+1] && arr[mid] > arr[mid-1]
則mid
位置即峰值位置,直接返回。
否則,有如下兩種情況:
情況一:mid 位置的值比 mid - 1 位置的值小
趨勢如下圖:
則在[1...(mid-1)]
區(qū)間內(nèi)繼續(xù)二分。
情況二:mid 位置的值比 mid + 1 位置的值小
趨勢是:
則在[(mid+1)...(N-2)]
區(qū)間內(nèi)繼續(xù)上述二分。
完整代碼
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; } }
時(shí)間復(fù)雜度O(logN)
。
讀到這里,這篇“Java二分法如何實(shí)現(xiàn)”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識(shí)點(diǎn)還需要大家自己動(dòng)手實(shí)踐使用過才能領(lǐng)會(huì),如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。