題目描述
給定一個 n
個元素有序的(升序)整型陣列 nums
和一個目標值 target
,寫一個函式搜尋 nums
中的 target
,如果目標值存在返回下標,否則返回 -1
。
示例 1:
輸入: nums = [-1,0,3,5,9,12], target = 9
輸出: 4
解釋: 9 出現在 nums 中並且下標為 4
示例 2:
輸入: nums = [-1,0,3,5,9,12], target = 2
輸出: -1
解釋: 2 不存在 nums 中因此返回 -1
力扣原題目地址:https://leetcode.cn/problems/...
解法一,使用陣列原生方法indexOf
var search = function (nums, target) {
return nums.indexOf(target)
};
陣列的原生方法,使用真方便。不過有時候需要多擴充一些處理問題的方式,以後遇到需求時,大有裨益
解法二,迴圈所有判斷是否等於目標值
var search = function (nums, target) {
let whichIndex = -1
for (let i = 0; i < nums.length; i++) {
if (nums[i] == target) {
whichIndex = i
return whichIndex
}
}
return whichIndex
};
假設我們要找的值,就是正好在最後一個位置,那麼就得把整個迴圈全部走一遍,才能找到我們所要找的那個數值。所以時間複雜度就是O(n)
。為了進一步提升效率,減少用時,所以二分法解題的方式就應運而生
解法三,二分法解題
所謂二分法可以簡單理解為:
- 指定開始位置、結束位置、然後不斷縮小其範圍最終找到我們想要找到的值;
- 由於二分法的一半一半的縮小範圍,所以其時間複雜度是
O(\log n)
另外注意:
- 二分法適用於有序的陣列,即從小到大或者從大到小的陣列
- 二分法搭配while迴圈可讀性會更加直觀明瞭
在工作中for迴圈使用次數比較多,while迴圈並不是特別多,所以為了更好的理解二分法的,我們來簡單複習一下while的迴圈知識
while迴圈複習
// 當符合condition條件的時候,會繼續不斷迴圈執行花括號裡面的程式碼
// 所以當達到某種情況下的時候,需要讓condition條件變為false,這樣的話,才會結束迴圈
// 要不然就會死迴圈哦
while (condition) {
// .....
}
// eg:使用while迴圈列印0~10
let num = 0
while (num <= 10) { // 翻譯:當num的值小於等於10的時候,就不斷迴圈
console.log(num);
num++
}
while和for迴圈的區別
固定陣列、固定長度、固定執行次數一般使用for迴圈
做邊界區分、不知道要迴圈多少次一般使用while迴圈
while比for功能更加強大
二分法程式碼
var search = function (arr, num) {
let firstIndex = 0
let lastIndex = arr.length - 1
// 注意firstIndex是要小於等於lastIndex值的,因為區間不斷縮小最終重合
while (firstIndex <= lastIndex) {
// console.log('firstIndex', firstIndex, 'lastIndex', lastIndex); // 看列印結果,有助於更好理解
let middleIndex = Math.floor((firstIndex + lastIndex) / 2) // 陣列長度為偶數時要向下取整,所以乾脆都向下取整唄
if (arr[middleIndex] == num) { // 若恰好中間索引數正好是我們所要找的那個數,返回索引即可
return middleIndex
} else if (arr[middleIndex] > num) { // 若中間數比要找的數大,說明要找到數在左邊,那麼開始區間不用動,結束區間更改為中間數左邊一個位置即可
lastIndex = middleIndex - 1
} else if (arr[middleIndex] < num) { // 同理...
firstIndex = middleIndex + 1
}
}
return -1 // 找不到的話,返回-1
};
這裡大家可以把while (firstIndex <= lastIndex) {......}
改為while (true) {......}
看看列印結果就會更好的理解了。雖然會死迴圈