算法-Leetcode幾個雙指針問題

1.搜索插入位置

https://leetcode-cn.com/problems/search-insert-position/數組

class Solution {
    public int searchInsert(int[] nums, int target) {
        int left=0,right=nums.length-1;
        while(left<=right){
            int mid=(left+right)/2;
            if(nums[mid]<target){
                left=mid+1;
            }else if(nums[mid]>target){
                right=mid-1;
            }else{
                return mid;
            }
        }
        return left;
    }
}

2.搜索二維矩陣

https://leetcode-cn.com/problems/search-a-2d-matrix/大數據

public boolean searchMatrix(int[][] matrix, int target) {
    if(matrix.length == 0)
        return false;
    int row = 0, col = matrix[0].length-1;
    while(row < matrix.length && col >= 0){
        if(matrix[row][col] < target)
            row++;
        else if(matrix[row][col] > target)
            col--;
        else
            return true;
    }
    return false;
}

3.刪除排序數組重複項

https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/人工智能

public int removeDuplicates(int[] nums) {
        // 使用雙指針
        if(nums==null || nums.length == 1){
            return nums.length;
        }
        int i = 0,j =1;
        while(j<nums.length){
            if(nums[i]==nums[j]){
                j++;
            }else{
                i++;
                nums[i]=nums[j];
                j++;
            }
        }
        return i+1;
    }

4.鏈表的中間節點

https://leetcode-cn.com/problems/middle-of-the-linked-list/指針

public ListNode middleNode(ListNode head) {
        ListNode p = head, q = head;
        while (q != null && q.next != null) {
            q = q.next.next;
            p = p.next;
        }
        return p;
}

5.愛生氣的書店老闆

https://leetcode-cn.com/problems/grumpy-bookstore-owner/code

/*
首先 找到不改變的時候客人就滿意的數量和 同時更新數組
這樣問題就轉變爲 求數組指定長度最大和的問題
時間複雜度 O(n) 空間複雜度爲O(1)
*/
class Solution {
    public int maxSatisfied(int[] customers, int[] grumpy, int x) {
        int sum = 0, len = customers.length;
        for (int i = 0; i < len; i++) {
            if (grumpy[i] == 0){
                sum += customers[i];
                customers[i] = 0;
            } 
        }
        int num = customers[0];
        int maxval = customers[0];
        for (int i = 1; i < len; i++){
            if (i < x) num = num + customers[i];
            else num = num + customers[i] - customers[i - x];
            maxval = Math.max(maxval, num);
        }
        
        return (sum + maxval);
    }
}

6.滑動窗口最大值

https://leetcode-cn.com/problems/sliding-window-maximum/排序

/*
  思路: 遍歷數組 L R 爲滑窗左右邊界 只增不減
        雙向隊列保存當前窗口中最大的值的數組下標 雙向隊列中的數從大到小排序,
        新進來的數若是大於等於隊列中的數 則將這些數彈出 再添加
        當R-L+1=k 時 滑窗大小肯定 每次R前進一步L也前進一步 保證此時滑窗中最大值的
        數組下標在[L,R]中,並將當前最大值記錄
  舉例: nums[1,3,-1,-3,5,3,6,7] k=3
     1:L=0,R=0,隊列【0】 R-L+1 < k
            隊列表明值【1】
     2: L=0,R=1, 隊列【1】 R-L+1 < k
            隊列表明值【3】
     解釋:當前數爲3 隊列中的數爲【1】 要保證隊列中的數從大到小 彈出1 加入3
          但隊列中保存的是值對應的數組下標 因此隊列爲【1】 窗口長度爲2 不添加記錄
     3: L=0,R=2, 隊列【1,2】 R-L+1 = k ,result={3}
            隊列表明值【3,-1】
     解釋:當前數爲-1 隊列中的數爲【3】 比隊列尾值小 直接加入 隊列爲【3,-1】
          窗口長度爲3 添加記錄記錄爲隊首元素對應的值 result[0]=3
     4: L=1,R=3, 隊列【1,2,3】 R-L+1 = k ,result={3,3}
            隊列表明值【3,-1,-3】
     解釋:當前數爲-3 隊列中的數爲【3,-1】 比隊列尾值小 直接加入 隊列爲【3,-1,-3】
          窗口長度爲4 要保證窗口大小爲3 L+1=1 此時隊首元素下標爲1 沒有失效
          添加記錄記錄爲隊首元素對應的值 result[1]=3
     5: L=2,R=4, 隊列【4】 R-L+1 = k ,result={3,3,5}
            隊列表明值【5】
     解釋:當前數爲5 隊列中的數爲【3,-1,-3】 保證從大到小 依次彈出添加 隊列爲【5】
          窗口長度爲4 要保證窗口大小爲3 L+1=2 此時隊首元素下標爲4 沒有失效
          添加記錄記錄爲隊首元素對應的值 result[2]=5
    依次類推 若是隊首元素小於L說明此時值失效 須要彈出
*/
class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        if(nums==null||nums.length<2) return nums;
        // 雙向隊列 保存當前窗口最大值的數組位置 保證隊列中數組位置的數按從大到小排序
        LinkedList<Integer> list = new LinkedList();
        // 結果數組
        int[] result = new int[nums.length-k+1];
        for(int i=0;i<nums.length;i++){
            // 保證從大到小 若是前面數小 彈出
            while(!list.isEmpty()&&nums[list.peekLast()]<=nums[i]){
                list.pollLast();
            }
            // 添加當前值對應的數組下標
            list.addLast(i);
            // 初始化窗口 等到窗口長度爲k時 下次移動在刪除過時數值
            if(list.peek()<=i-k){
                list.poll();   
            } 
            // 窗口長度爲k時 再保存當前窗口中最大值
            if(i-k+1>=0){
                result[i-k+1] = nums[list.peek()];
            }
        }
        return result;
    }
}

吳邪,小三爺,混跡於後臺,大數據,人工智能領域的小菜鳥。
更多請關注
file隊列

相關文章
相關標籤/搜索