LeetCode進34-二分查找

閒聊

在開算法博客至今,曾經有讀者在評論中質疑過博客中大廠面試題的真實性,在以前某一篇知乎評論中我曾經回覆過而且列出了某些依據,如今看來以爲徹底不必。在此聲明一下,全部算法題都是經過我的精心整理查閱,有些是源於一些開源社區,有些是來自某些開發者面試經驗(面經),還有些則是從某些技術網站獲取...這些算法題選的題的依據是我的判斷理解一些對與算法學習進階比較有表明性的典型問題。後續相似面試題的真實性問題將再也不回覆,最後再次聲明本人開算法博客的初衷是幫助有須要的人,有任何技術方面的問題歡迎交流,非誠勿擾~java

概要

二分查找也稱折半查找,是典型的分治思想的應用,是一種效率較高的查找方法。折半查找要求線性表必須採用順序存儲結構,並且表中元素按關鍵字有序排列。以前的一篇博客LeetCode進階4-分而治之也介紹過度治法,本篇進一步介紹其思想應用的經典算法—二分查找。面試

34. Find First and Last Position of Element in Sorted Array (Medium)

Given an array of integers nums sorted in ascending order, find the starting and ending position of a given target value.算法

Your algorithm's runtime complexity must be in the order of O(log n).數組

If the target is not found in the array, return [-1, -1].bash

Example 1:學習

Input: nums = [5,7,7,8,8,10], target = 8 Output: [3,4] Example 2:網站

Input: nums = [5,7,7,8,8,10], target = 6 Output: [-1,-1]編碼

34. 在排序數組中查找元素的第一個和最後一個位置(中等)

給定一個按照升序排列的整數數組 nums,和一個目標值 target。找出給定目標值在數組中的開始位置和結束位置。spa

你的算法時間複雜度必須是 O(log n) 級別。指針

若是數組中不存在目標值,返回 [-1, -1]。

示例 1:

輸入: nums = [5,7,7,8,8,10], target = 8 輸出: [3,4] 示例 2:

輸入: nums = [5,7,7,8,8,10], target = 6 輸出: [-1,-1]

  • 分類:二分查找(Binary Search)

分析&&思路

按照正常的二分查找思路,循環找到匹配目標數字的下標,繼續將右指針變小查找到第一個目標數字。用新的循環從找到的第一個目標數字下標從左往右查找直到最後一個目標數字。(具體的查找思路見僞代碼)

僞代碼

一、相關聲明
   1.一、聲明搜索用的左右指針,初始左指針下標0,右指針下標數組末位nums.length-1;
   1.二、獲取數組中間下標mid = (l + r) / 2;
   1.三、聲明建立結果數組,初始化賦值-1;
二、循環二分查找,直到左指針大於右指針查找結束
   2.一、若中間位置數字小於目標數字,說明目標數字在mid右邊,將左指針l右移賦值爲mid+1;
   2.二、若中間位置數字大於目標數字,說明目標數字在mid左邊,將右指針r左移賦值爲mid-1;
   2.三、若中間位置數字等於目標數字:
      2.3.一、將mid做爲第一次出現位置存入數組;
      2.3.二、右指針r左移賦值爲mid-1,繼續查找相等的數字直到找到第一次出現的位置;
   2.四、更新mid;
三、從第一次出現的位置開始,循環往右查找最後一次出現的位置:
   3.一、聲明pr指針初始賦值爲第一次出現位置下標;
   3.二、當二分查找已找到目標數字時
      3.2.一、循環直到數組越界或者數組當前元素不等於目標元素時結束:
        3.2.1.一、更新最後一次出現位置下標;
        3.2.1.二、更新以後往右移動指針;
四、最終返回已存儲位置的結果數組;
          
複製代碼

編碼實踐

public int[] searchRange(int[] nums, int target) {
		int l = 0, r = nums.length - 1;
		int mid = (l + r) / 2;
		int res[] = { -1, -1 };
		while (l <= r) {
			if (nums[mid] < target) {
				l = mid + 1;
			} else if (nums[mid] > target) {
				r = mid - 1;
			} else {
				res[0] = mid;
				r = mid - 1;
			}
			mid = (l + r) / 2;
		}
		int pr = res[0];
		if (pr != -1) {
			while (pr <= nums.length - 1 && target == nums[pr]) {
				res[1] = pr++;
			}
		}
		return res;
	}
複製代碼

1.jpg

擴展延伸

本題實際在頭條筆試題中也曾經出現過

有序數組二分查找,返回查找元素最後一次出現的位置,若不存在則返回-1

感興趣能夠結合上面思路思考,下面是題解參考代碼:

public static int searchRange(int[] nums, int target) {
		int l = 0, r = nums.length - 1;
		int mid = (l + r) / 2;
		int res = -1;
		while (l <= r) {
			if (nums[mid] < target) {
				l = mid + 1;
			} else if (nums[mid] > target) {
				r = mid - 1;
			} else {
				res = mid;
				l = mid + 1;
			}
			mid = (l + r) / 2;
		}

		return res;
	}
複製代碼

Alt

關注訂閱號 獲取更多幹貨~
相關文章
相關標籤/搜索