【leetcode】袁廚精選題總結之什麼時候用雙指針,該咋用? - 新聞資(zī)訊 - 雲南小程序開發|雲南軟件開發|雲南網站(zhàn)建設-西山區知普網絡科技工作室

159-8711-8523

雲南網建設/小程序開發/軟件開發

知識

不管是網站(zhàn),軟件還是小程序,都要直接或間接能為您産生價值,我們在追求其視覺表現的同時,更側重于功能的便捷,營銷的便利,運營的高效,讓網站(zhàn)成為營銷工具,讓軟件能切實提升企業(yè)内部管理水平和(hé)效率。優秀的程序為後期升級提供便捷的支持!

您當前位置>首頁 » 新聞資(zī)訊 » 技術(shù)分享 >

【leetcode】袁廚精選題總結之什麼時候用雙指針,該咋用?

發表時間:2020-10-18

發布人:葵宇科技

浏覽次數:46

那些可(kě)以用雙指針解決的題目

  • 什麼時候用雙指針,該咋用?
    • 雙指針思想
      • 35.搜索插入位置
      • 27.移除元素
      • 209,長度最小的子(zǐ)數組

什麼時候用雙指針,該咋用?

雙指針思想

雙指針是我們做題中(zhōng)經常用到的思想,所以這個(gè)在刷題初期是一定要會的。其實我們早就學習過這個(gè)方法,我們通(tōng)過二分查找來描述一下(xià)這個(gè)思想。

二分查找首先定義兩個(gè)指針,左指針和(hé)右指針,分别指向數組的頭和(hé)尾,然後計算出他倆的中(zhōng)間的索引,其值和(hé)目标值進行比較,如(rú)果目标值更大則說明目标值在中(zhōng)間索引和(hé)右指針中(zhōng)間,則需要移動(dòng)左指針到中(zhōng)間索引的後一位。如(rú)果目标值比中(zhōng)間值小,則需要移動(dòng)右指針到中(zhōng)間索引的前一位。不斷執行,直至找到目标值,或當該數組不含有目标值,左指針和(hé)右指針重合時跳出該循環。

有序數組的二分查找

二分查找代碼

 public static int halfnum(int[] arraynum ,int b){
            int hi =arraynum.length-1;
            int lo = 0;
            //先判斷數組是不是空
            if (arraynum.length==0){
                return -1;
            }            
            while(hi>=lo){
                 //判斷是否等于要猜的數
                if(b==arraynum[(hi+lo)/2]){
                    return (hi+lo)/2;
                }
                //大于中(zhōng)間數的情況
                else if (b>arraynum[(hi+lo)/2]){
                    lo= (hi+lo)/2+1;
                }
                //小于中(zhōng)間數的情況
                else{
                    hi=(hi+lo)/2-1;
                }
            }
           return -1;
        }

35.搜索插入位置

給定一個(gè)排序數組和(hé)一個(gè)目标值,在數組中(zhōng)找到目标值,并返回其索引。如(rú)果目标值不存在于數組中(zhōng),返回它将會被按順序插入的位置。你(nǐ)可(kě)以假設數組中(zhōng)無重複元素。

示例 1:

輸入: [1,3,5,6], 5
輸出: 2

示例 2:

輸入: [1,3,5,6], 2
輸出: 1

示例 3:

輸入: [1,3,5,6], 7
輸出: 4

示例 4:

輸入: [1,3,5,6], 0
輸出: 0

題目很好理解,但是我們想要一次AC是不太容易的。我們根據題意可(kě)以想到,這樣共有四種可(kě)能

在這裡插入圖片描述

插入情況無非就這幾種

(1)比數組裡的任何值都小,插入頭部

(2)比數組裡的任何值都大,插入尾部

(3)查詢到數組元素,返回該處索引值

(4)數組内無該元素,将其插入兩元素之間。

所以我們可(kě)以通(tōng)過以下(xià)代碼實現該題

class Solution {
    public int searchInsert(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while(left <= right) {
            //中(zhōng)間值,與target對比
            int mid = (left + right) / 2;
            //第三種情況
            if(nums[mid] == target) {
                return mid;
            //移動(dòng)左指針
            } else if(nums[mid] < target) {
                left = mid + 1;
            } else {
                //移動(dòng)右指針
                right = mid - 1;
            }
        }
        //1,2,4三種情況都在循環内部,我們隻需輸出左指針即可(kě)。
        return left;
    }
}

剛才我們說了雙指針思想的重要性,下(xià)面這個(gè)題目也是可(kě)以完全通(tōng)過雙指針思想實現的,所以說雙指針的思想是必須有的。你(nǐ)可(kě)以通(tōng)過下(xià)面這個(gè)題目完全體會到雙指針的重要性

27.移除元素

給你(nǐ)一個(gè)數組 nums 和(hé)一個(gè)值 val,你(nǐ)需要 原地 移除所有數值等于 val 的元素,并返回移除後數組的新長度。

不要使用額外的數組空間,你(nǐ)必須僅使用 O(1) 額外空間并 原地 修改輸入數組。

元素的順序可(kě)以改變。你(nǐ)不需要考慮數組中(zhōng)超出新長度後面的元素。

示例 1:

給定 nums = [3,2,2,3], val = 3,

函數應該返回新的長度 2, 并且 nums 中(zhōng)的前兩個(gè)元素均為 2。

你(nǐ)不需要考慮數組中(zhōng)超出新長度後面的元素。

示例 2:

給定 nums = [0,1,2,2,3,0,4,2], val = 2,

函數應該返回新的長度 5, 并且 nums 中(zhōng)的前五個(gè)元素為 0, 1, 3, 0, 4。

注意這五個(gè)元素可(kě)為任意順序。

你(nǐ)不需要考慮數組中(zhōng)超出新長度後面的元素。

該題目我們可(kě)以創建兩個(gè)指針,一前一後,前面的負責探路(lù)後面的負責填充,當前面查詢到需要移除的元素時直接跳過該元素,繼續前進。後面的指針隻負責往該數組裡面填充不需要移除的數字。所以我們可(kě)以根據以下(xià)代碼實現

class Solution {
    public int removeElement(int[] nums, int val) {
    //特殊情況
      if(nums==null){
          return 0;
      }     
      int j = 0;//慢指針,i代表快指針
      for(int i = 0;i<nums.length;i++){
         //正常情況直接賦值給i          
          if(nums[i]!=val){
              nums[j]=nums[i];
              j++;
          }
          //如(rú)果為需要删除的值時,則快指針移動(dòng),慢指針不動(dòng)。
      }
       return j;
    }
}

剛才我們學習了兩個(gè)雙指針的題目,是不是對這個(gè)做題思想有了一些理解了,下(xià)面我們來使用一個(gè)更加高級的雙指針,這個(gè)也是經常使用的思想,但是歸根結底還是雙指針思想。

該題目的思想也是雙指針的思想,不過這個(gè)代碼比較難寫一些,用到的情況也是比較多的,所以我們這個(gè)題目要用心體會一下(xià)。

209,長度最小的子(zǐ)數組

給定一個(gè)含有 n 個(gè)正整數的數組和(hé)一個(gè)正整數 s ,找出該數組中(zhōng)滿足其和(hé) ≥ s 的長度最小的 連續 子(zǐ)數組,并返回其長度。如(rú)果不存在符合條件的子(zǐ)數組,返回 0。

示例:

輸入:s = 7, nums = [2,3,1,2,4,3]
輸出:2
解釋:子(zǐ)數組 [4,3] 是該條件下(xià)的長度最小的子(zǐ)數組

題目含義比較好理解,則是在數組裡面找出長度最小的子(zǐ)數組,子(zǐ)數組的元素和(hé)大于等于目标值。這個(gè)題目我們就用到了滑動(dòng)窗口的思想。

滑動(dòng)窗口:就是通(tōng)過不斷調節子(zǐ)數組的起始位置和(hé)終止位置,進而得到我們想要的結果我們也可(kě)以看成是雙指針的一種。

在該題中(zhōng),我們可(kě)能遇到這種情況 大家思考一下(xià),數組的值是1,2,3,4,5我們的s為5,所以我們第一次的子(zǐ)數組(滑動(dòng)窗口)長度則為3,1+2+3>5,這時左指針在1的位置,右指針在3的位置,但是2+3=5同樣符合,所以我們就需要移動(dòng)左指針,此時窗口長度則改為2了。然後我們保留該值,繼續移動(dòng)左指針,判斷3是否仍符合,此時發現不符合了,則需要移動(dòng)右指針,移動(dòng)到下(xià)一個(gè)符合情況的元素,繼續執行剛才的步驟,直到數組的最後。所以整個(gè)過程中(zhōng)滑動(dòng)窗口的長度變化為,3,2,3,2,3,2,1,最小的則為1.

我們可(kě)以通(tōng)過以下(xià)代碼解決該題。

class Solution {
    public int minSubArrayLen(int s, int[] nums) {
        int chiledlen = Integer.MAX_VALUE;
        int winlen = 0;//窗口大小
        int sum = 0;
        int i = 0;//起始長度位置
        for(int j = 0 ; j < nums.length;j++){
              sum += nums[j];
              //發現符合條件的情況
              //循環内部的代碼是精髓所在
              while(sum>=s){
                  winlen = j-i+1;
                  chiledlen = Math.min(chiledlen,winlen);
                  //下(xià)面兩行是滑動(dòng)窗口的意義所在,改變起點位置,判斷是否仍符合條件
                  sum-=nums[i];
                  i++;
              }

        }
        return chiledlen == Integer.MAX_VALUE ? 0:chiledlen;
    }
}

通(tōng)過以上三個(gè)題目我們是不是對雙指針思想有了一些理解了,該思想不僅可(kě)以用在數組的題目上,鍊表同樣适用。所以我們要完全掌握,這三個(gè)題目大家有時間的話還是自己動(dòng)手做一下(xià)。


在這裡插入圖片描述

相關(guān)案例查看更多