二分法查找平方和_面试手撕系列:二分法
生活随笔
收集整理的這篇文章主要介紹了
二分法查找平方和_面试手撕系列:二分法
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
最近春招開始了,面試面著面著一言不合就開始手撕代碼手撕就手撕,接下來我打算寫幾個專題講講面試中手撕的常見題目?這些都是LeetCode上有的題目?手撕無非就是?樹、鏈表、二分、字符串這些常用的數據結構所以接下來請關注我們的專題吧二分法二分法查找,也稱為折半法,是一種在有序數組中查找特定元素的搜索算法。二分法查找的思路如下:(1)首先,從數組的中間元素開始搜索,如果該元素正好是目標元素,則搜索過程結束,否則執行下一步。(2)如果目標元素大于/小于中間元素,則在數組大于/小于中間元素的那一半區域查找,然后重復步驟(1)的操作。(3)如果某一步數組為空,則表示找不到目標元素。二分法查找的時間復雜度O(logn)。感覺很抽象的樣子 舉一個簡單通俗易懂的例子你不知道自己長得怎么樣,然后去找了10個人 ,評分分別為1-10分首先把5號拉出來,讓大家看看是不是這個人和你比哪個優秀如果你比五號選手長得帥,那么你就不用和1-4號比了,這個區間就縮短成[5-10]如果不幸的比五號選手長得丑,那么這個區間就縮短成了[1-4]這里介紹兩個二分法的模板 主要區別在于當前數是被劃分到左區間還是右區間模板boolcheck(int?x)?{/*?...?*/}?//?檢查x是否滿足某種性質//?區間[l, r]被劃分成[l, mid]和[mid + 1, r]時使用:
intbsearch_1(int?l,?int?r){while?(l?????{int?mid?=?l?+?r?>>?1;if?(check(mid))?r?=?mid;????//?check()判斷mid是否滿足性質else?l?=?mid?+?1;
????}return?l;
}//?區間[l, r]被劃分成[l, mid - 1]和[mid, r]時使用:
intbsearch_2(int?l,?int?r){while?(l?????{int?mid?=?l?+?r?+?1?>>?1;if?(check(mid))?l?=?mid;else?r?=?mid?-?1;
????}return?l;
}二分法作為一種搜索上快速的算法,可以把復雜度從O(N)變成O(log N),要滿足二分法搜索的條件是搜索區間內滿足單調性為什么會有兩個模板呢可以看到在區分id的時候可以分為mid=(l+r)/2和(l+r)/2+1與此同時 帶來了當前數字索引劃分區間的不同話不多說先來兩個題目試一試水69 X的平方根實現 int sqrt(int x) 函數。計算并返回 x 的平方根,其中 x 是非負整數。由于返回類型是整數,結果只保留整數的部分,小數部分將被舍去。示例 1:輸入: 4輸出: 2示例 2:輸入: 8輸出: 2說明: 8 的平方根是 2.82842...,
由于返回類型是整數,小數部分將被舍去。這個題目使用二分法還是比較明顯的使用二分法搜索平方根的思想很簡單,就類似于小時候我們看的電視節目中的“猜價格”游戲,高了就往低了猜,低了就往高了猜,范圍越來越小。因此,使用二分法猜算術平方根就很自然。存在三種情況: //采用二分模板?mid劃到了左區間long?left=1;long?right=x;while(left????????????long?mid=(left+right)/2+1;if(mid*mid>x)//平方大于目標數?往低走
????????????????????right=mid-1;else?if(mid*mid//平方大于目標數?往低走
????????????????????left=mid;else?{//平方和恰好等于目標數?跳出循環
????????????????????left=mid;break;
????????????}
????}return?(int)(left);74 搜索二維矩陣編寫一個高效的算法來判斷 m x n 矩陣中,是否存在一個目標值。該矩陣具有如下特性:每行中的整數從左到右按升序排列。每行的第一個整數大于前一行的最后一個整數。輸入:
matrix = [
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
target = 3輸出: true輸入:
matrix = [
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
target = 13輸出: false這個題目也可以采用二分 先找一下規律發現 每行的第一個整數大于前一行的最后一個整數 所以這個數組 從上到下 從左到右是依次遞增的 所以我們可以采用兩次二分法第一次二分的目的是鎖定這個數在哪一行上int?left=0;
int?right=Hang-1;
while(left<right){int?mid=(left+right)/2+1;if(matrix[mid][0]>target)//當前這個行首元素大于target?說明不可能在這一行
????????????????right=mid-1;
????????else?if(matrix[mid][0]<=target)//小于或者等于的時候?說明可能是在這一行上left=mid;
????}//最后這個left就是具體哪一行第二次二分的目的是鎖定這個數在這一行的哪一列上主要判斷索引為(Hang,mid)這個元素與target的關系Hang?=?left;
left?=0;
right=Lie-1;while(left????????int?mid=(left+right)/2+1;if(matrix[Hang][mid]>target)//如果這一行上坐標為(Hang,mid)的元素大于target?說明目標數可能在左邊
????????????????right=mid-1;else?if(matrix[Hang][mid]//如果這一行上坐標為(Hang,mid)的元素小于target?說明目標數可能在右邊
????????????????left=mid;else?//相等的話就是Truereturn?true;
}//最后找到這個數但是不一定是和目標數相等?要判斷一下if(matrix[Hang][left]==target)return?true;else????return?false;查找元素的第一個和最后一個位置給定一個按照升序排列的整數數組 nums,和一個目標值 target。找出給定目標值在數組中的開始位置和結束位置。你的算法時間復雜度必須是 O(log n) 級別。如果數組中不存在目標值,返回 [-1, -1]。輸入: nums = [5,7,7,8,8,10], target = 8輸出: [3,4]輸入: nums = [5,7,7,8,8,10], target = 6輸出: [-1,-1]因為數組已經排過序了,我們可以使用二分查找的方法去定位左右下標。1,使用二分法判斷是否存在目標值2,使用二分法找到第一個?大于等于 target?的位置i3,使用二分法找到最后一個?小于等于 target的位置j這個過程類似什么 類似我們高中學過的夾逼準則吧由于數組有序且從小到大排序 那么找到的[i,j]區間里必定是目標區間 當然還得判斷目標區間是否存在使用二分法找到第一個?大于等于 target?的位置iint?left=0;int?right=nums.length-1;while(left<right){int?mid=(left+right)/2+1;if(nums[mid]<=target)left=mid;else???right=mid-1;
????????}使用二分法找到最后一個?小于等于 target?的位置jleft=0;right=nums.length-1;while(left<right){int?mid=(left+right)/2;if(nums[mid]>=target)right=mid;elseleft=mid+1;
}最后驗證區間是否符合我們的要求即可287 尋找重復數給定一個包含 n + 1 個整數的數組 nums,其數字都在 1 到 n 之間(包括 1 和 n),可知至少存在一個重復的整數。假設只有一個重復的整數,找出這個重復的數。輸入: [1,3,4,2,2]輸出: 2輸入: [3,1,3,4,2]輸出: 3說明: 那么我們要找出這個引起質變的數即可int?n=nums.length;int?l=0;int?r=n-1;while(l????????int?mid=(l+r)/2;int?cnt=0;for(int?i=0;i//計算1-mid?上每個數出現的次數if(nums[i]<=mid)
????????????????????????cnt+=1;
????????}if(cnt<=mid)//如果是每個數都出現了一次?那么往大找
????????????????l=mid+1;else//否則往小找
????????????????r=mid;
}return?l;162 尋找峰值峰值元素是指其值大于左右相鄰值的元素。給定一個輸入數組 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。數組可能包含多個峰值,在這種情況下,返回任何一個峰值所在位置即可。你可以假設 nums[-1] = nums[n] = -∞。例 1:輸入: nums = [1,2,3,1]輸出: 2解釋: 3 是峰值元素,你的函數應該返回其索引 2。示例 2:輸入: nums = [1,2,1,3,5,6,4]輸出: 1 或 5解釋: 你的函數可以返回索引 1,其峰值元素為 2;或者返回索引 5, 其峰值元素為 6。說明:
數組[1,2]? ? ? 它的峰值就是2? ? ? 因為1<2< -∞給大家畫一個山峰可以知道山峰的確定和他的絕對高度 無關 和他的相對高度有關只要他是比它的鄰居都高 那它就是山峰抽象成二分法怎么理解 如這個圖所示 我就比較nums[mid]和nums[mid+1]之間的關系無非就是只有兩個情況
????????????????l=mid+1;else//如果下坡了?往回走?直到找到頂峰
????????????????r=mid;
}return?l;最后推薦幾道題目,也是使用二分的,相信你看到這里也對二分有了更高的認識,不再是有序才可以用二分Leetcode-278 第一個錯誤的版本Leetcode-275 H指數IILeetcode-35 搜索插入位置Leetcode-53 尋找旋轉排序數組中的最小值
intbsearch_1(int?l,?int?r){while?(l?????{int?mid?=?l?+?r?>>?1;if?(check(mid))?r?=?mid;????//?check()判斷mid是否滿足性質else?l?=?mid?+?1;
????}return?l;
}//?區間[l, r]被劃分成[l, mid - 1]和[mid, r]時使用:
intbsearch_2(int?l,?int?r){while?(l?????{int?mid?=?l?+?r?+?1?>>?1;if?(check(mid))?l?=?mid;else?r?=?mid?-?1;
????}return?l;
}二分法作為一種搜索上快速的算法,可以把復雜度從O(N)變成O(log N),要滿足二分法搜索的條件是搜索區間內滿足單調性為什么會有兩個模板呢可以看到在區分id的時候可以分為mid=(l+r)/2和(l+r)/2+1與此同時 帶來了當前數字索引劃分區間的不同話不多說先來兩個題目試一試水69 X的平方根實現 int sqrt(int x) 函數。計算并返回 x 的平方根,其中 x 是非負整數。由于返回類型是整數,結果只保留整數的部分,小數部分將被舍去。示例 1:輸入: 4輸出: 2示例 2:輸入: 8輸出: 2說明: 8 的平方根是 2.82842...,
由于返回類型是整數,小數部分將被舍去。這個題目使用二分法還是比較明顯的使用二分法搜索平方根的思想很簡單,就類似于小時候我們看的電視節目中的“猜價格”游戲,高了就往低了猜,低了就往高了猜,范圍越來越小。因此,使用二分法猜算術平方根就很自然。存在三種情況:
平方小于目標數 往高走
平方大于目標數 往低走
平方和恰好等于目標數 跳出循環
????????????????????right=mid-1;else?if(mid*mid//平方大于目標數?往低走
????????????????????left=mid;else?{//平方和恰好等于目標數?跳出循環
????????????????????left=mid;break;
????????????}
????}return?(int)(left);74 搜索二維矩陣編寫一個高效的算法來判斷 m x n 矩陣中,是否存在一個目標值。該矩陣具有如下特性:每行中的整數從左到右按升序排列。每行的第一個整數大于前一行的最后一個整數。輸入:
matrix = [
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
target = 3輸出: true輸入:
matrix = [
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
target = 13輸出: false這個題目也可以采用二分 先找一下規律發現 每行的第一個整數大于前一行的最后一個整數 所以這個數組 從上到下 從左到右是依次遞增的 所以我們可以采用兩次二分法第一次二分的目的是鎖定這個數在哪一行上int?left=0;
int?right=Hang-1;
while(left<right){int?mid=(left+right)/2+1;if(matrix[mid][0]>target)//當前這個行首元素大于target?說明不可能在這一行
????????????????right=mid-1;
????????else?if(matrix[mid][0]<=target)//小于或者等于的時候?說明可能是在這一行上left=mid;
????}//最后這個left就是具體哪一行第二次二分的目的是鎖定這個數在這一行的哪一列上主要判斷索引為(Hang,mid)這個元素與target的關系Hang?=?left;
left?=0;
right=Lie-1;while(left????????int?mid=(left+right)/2+1;if(matrix[Hang][mid]>target)//如果這一行上坐標為(Hang,mid)的元素大于target?說明目標數可能在左邊
????????????????right=mid-1;else?if(matrix[Hang][mid]//如果這一行上坐標為(Hang,mid)的元素小于target?說明目標數可能在右邊
????????????????left=mid;else?//相等的話就是Truereturn?true;
}//最后找到這個數但是不一定是和目標數相等?要判斷一下if(matrix[Hang][left]==target)return?true;else????return?false;查找元素的第一個和最后一個位置給定一個按照升序排列的整數數組 nums,和一個目標值 target。找出給定目標值在數組中的開始位置和結束位置。你的算法時間復雜度必須是 O(log n) 級別。如果數組中不存在目標值,返回 [-1, -1]。輸入: nums = [5,7,7,8,8,10], target = 8輸出: [3,4]輸入: nums = [5,7,7,8,8,10], target = 6輸出: [-1,-1]因為數組已經排過序了,我們可以使用二分查找的方法去定位左右下標。1,使用二分法判斷是否存在目標值2,使用二分法找到第一個?大于等于 target?的位置i3,使用二分法找到最后一個?小于等于 target的位置j這個過程類似什么 類似我們高中學過的夾逼準則吧由于數組有序且從小到大排序 那么找到的[i,j]區間里必定是目標區間 當然還得判斷目標區間是否存在使用二分法找到第一個?大于等于 target?的位置iint?left=0;int?right=nums.length-1;while(left<right){int?mid=(left+right)/2+1;if(nums[mid]<=target)left=mid;else???right=mid-1;
????????}使用二分法找到最后一個?小于等于 target?的位置jleft=0;right=nums.length-1;while(left<right){int?mid=(left+right)/2;if(nums[mid]>=target)right=mid;elseleft=mid+1;
}最后驗證區間是否符合我們的要求即可287 尋找重復數給定一個包含 n + 1 個整數的數組 nums,其數字都在 1 到 n 之間(包括 1 和 n),可知至少存在一個重復的整數。假設只有一個重復的整數,找出這個重復的數。輸入: [1,3,4,2,2]輸出: 2輸入: [3,1,3,4,2]輸出: 3說明:
不能更改原數組(假設數組是只讀的)。
只能使用額外的 O(1) 的空間。
時間復雜度小于 O(n^2) 。
數組中只有一個重復的數字,但它可能不止重復出現一次。
如果是 那么就說明1-x上每個數都只出現了一次 目標數還得往大找
如果不是 那么說明1-x上有一個數是出現了兩次 目標數得往小了找
????????????????????????cnt+=1;
????????}if(cnt<=mid)//如果是每個數都出現了一次?那么往大找
????????????????l=mid+1;else//否則往小找
????????????????r=mid;
}return?l;162 尋找峰值峰值元素是指其值大于左右相鄰值的元素。給定一個輸入數組 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。數組可能包含多個峰值,在這種情況下,返回任何一個峰值所在位置即可。你可以假設 nums[-1] = nums[n] = -∞。例 1:輸入: nums = [1,2,3,1]輸出: 2解釋: 3 是峰值元素,你的函數應該返回其索引 2。示例 2:輸入: nums = [1,2,1,3,5,6,4]輸出: 1 或 5解釋: 你的函數可以返回索引 1,其峰值元素為 2;或者返回索引 5, 其峰值元素為 6。說明:
你的解法應該是 O(logN) 時間復雜度的。
數組[1,2]? ? ? 它的峰值就是2? ? ? 因為1<2< -∞給大家畫一個山峰可以知道山峰的確定和他的絕對高度 無關 和他的相對高度有關只要他是比它的鄰居都高 那它就是山峰抽象成二分法怎么理解 如這個圖所示 我就比較nums[mid]和nums[mid+1]之間的關系無非就是只有兩個情況
nums[mid]?也就是右邊的元素大于左邊的 那從左往右看就是上坡 上坡路必定存在一個頂峰
nums[mid]>nums[mid+1]?也就是右邊的元素小于等于左邊的 那從右往左看就是一個平滑的下坡,那這個頂峰必定是在mid這個位置之前,不然我也不可能有下坡的空間
????????????????l=mid+1;else//如果下坡了?往回走?直到找到頂峰
????????????????r=mid;
}return?l;最后推薦幾道題目,也是使用二分的,相信你看到這里也對二分有了更高的認識,不再是有序才可以用二分Leetcode-278 第一個錯誤的版本Leetcode-275 H指數IILeetcode-35 搜索插入位置Leetcode-53 尋找旋轉排序數組中的最小值
往期精彩回顧
三月算法崗面經
阿里筆試題兩道
掃碼關注我,加入每日一題算法交流群/秋招備戰群吧請備注 學校+昵稱才可以加群噢總結
以上是生活随笔為你收集整理的二分法查找平方和_面试手撕系列:二分法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 纯jsp实现评论功能_自己实现的java
- 下一篇: 打印的图片不清晰_如何调节图片kb,但又