Leetcode之javascript解題(No33-34)

附上個人github倉庫,會不斷更新leetcode解題答案,提供一個思路,你們共勉git

在個人主頁和github上能夠看到更多的關於leetcode的解題報告!(由於不知道爲何掘金沒有將其發佈出來,目前已經聯繫掘金客服)

但願能夠給star,鼓勵繼續更新解題思路

author: thomasgithub

No34:Search for Range(Medium)

題目

Given an array of integers 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

For exampleui

Given [5, 7, 7, 8, 8, 10] and target value 8,
return [3, 4]. // 下標3,4是數組8
複製代碼

這道題讓咱們在一個有序整數數組中尋找相同目標值的起始和結束位置,沒若是沒有找到就返回[-1,-1]spa

思路

這道題讓咱們在一個有序整數數組中尋找相同目標值的起始和結束位置,並且限定了時間複雜度爲O(logn),這是典型的二分查找法的時間複雜度,因此這道題咱們也須要用此方法。code

  • 方法一cdn

    • 咱們的思路是對原數組使用兩次二分查找法,分別找出一個起始和結束位置
  • 方法二:利用二分法找到起始位置,而後向右遍歷,找到邊界

代碼

  • 方法一
let arr1 = [1,1,2,2,3,4,4,7,8];
let arr = [5,7,7,8,8,10],
  target = 8;
let searchRange = function(arr, target) {
  let len = arr.length,
    res = [-1, -1];
  for (let i = 0, j = len-1; i <= j;) {
    let mid = Math.floor((i + j) / 2);
    if (arr[mid] < target) { // 先判斷小於target的狀況
      i = mid + 1;
    }else {
      j = mid - 1; // 應對恰好i = mid + 1後就指向了target值
      if (arr[mid] === target) {
        res[0] = mid; // 獲得起始index
      }
    }
  }

  for (let i = 0, j = len-1; i <= j;) {
    let mid = Math.floor((i + j) / 2);
    if (arr[mid] > target) {// 先判斷大於target的狀況
      j = mid - 1;
    }else {
      i = mid + 1; // 應對恰好i = mid + 1後就指向了target值
      if (arr[mid] === target) {
        res[1] = mid; // 獲得結束index
      }
    }
  }

  return res;
};
console.log(searchRange(arr,target)); // [3, 4]
複製代碼
  • 方法二
/**
 * 方法2
 *
 * 找到res[0]以後,就向右遍歷,直到不是該值,就能夠獲得右邊界了
 * 時間複雜度沒上面的方法好
 */

let searchRange1 = function(arr, target) {
  let len = arr.length,
    res = [-1, -1];
  for (let i = 0, j = len-1; i <= j;) {
    let mid = Math.floor((i + j) / 2);
    if (arr[mid] < target) {
      i = mid + 1;
    }else {
      j = mid - 1; // 應對恰好i = mid + 1後就指向了target值
      if (arr[mid] === target) {
        res[0] = mid; // 獲得最左邊的值
      }
    }
  }
  let k;
  res[1] = res[0];
  for (k = res[0] + 1; k < len; k++) { // 找到右邊界
    if (arr[k] === target) {
      res[1] += 1;
    }
  }

  return res;
};
console.log(searchRange1([1],1)); // [0, 0]
console.log(searchRange1([2,2],2)); // [0, 1]
console.log(searchRange1([5,7,7,8,8,10],8)); // [3, 4]
console.log(searchRange1([1,3],1)); // [0, 0]
console.log(searchRange1([3,3,3],3)); // [0, 0]
複製代碼

注:二分法:其假設咱們找到目標值(可是有多個目標值連在一塊兒)blog

  • 一、若是咱們先判斷arr[mid] < target(先判斷小於target的狀況),再判斷剩下的,最後獲得的結果就是要找的多個目標值target的最左邊的值
  • 二、若是咱們先判斷arr[mid] > target(也就是先判斷大於target的狀況),再判斷剩下的,最後獲得的結果就是要找的多個目標值target的最右邊的值

No35:Search Insert Position(Easy)

題目

從給定排好順序的數組,找出給定目標數字下標,存在則返回下標,不存在則返回目標數應該插入的位置下標。 Example 1:

Input: [1,3,5,6], 5
Output: 2
複製代碼

Example 2:

Input: [1,3,5,6], 2
Output: 1
複製代碼

Example 3:

Input: [1,3,5,6], 7
Output: 4
複製代碼

Example 4:

Input: [1,3,5,6], 0
Output: 0
複製代碼

思路

思路就是每次取中間,若是等於目標即返回,不然根據大小關係切去一半。所以算法複雜度是O(logn),空間複雜度O(1)

代碼

let arr = [1,3,5,6],
	target = 5;

let searchInset = function(arr, target) {
  let len = arr.length,
			res = 0;
  for (let i = 0, j = len -1; i <= j;) {
    let mid = Math.floor((i+j)/2);
  if (arr[mid] === target) {
			return mid;
  }
  if (arr[mid] < target) {
      i = mid + 1;
      res = mid+1; // 更新res
		}else {
    	j = mid - 1;
		}
	}
	return res; //
}
console.log(searchInset(arr,target)); // 2
console.log(searchInset([1,3,5,6],2)); // 2
複製代碼

注意:二分法有一個好處:就是當循環結束時:

(1)若是找到目標元素,那麼就返回當前位置

(2)若是沒有找到目標元素,那麼i必定停在剛好比目標大的index上,j必定停在剛好比目標小的index上,因此我的比較推薦這種實現方式。(初始i在左,j在右)

相關文章
相關標籤/搜索