1. 程式人生 > 其它 >第83期-基礎技巧:雙指標 有序陣列的平方

第83期-基礎技巧:雙指標 有序陣列的平方

1 問題描述

給你一個按 非遞減順序 排序的整數陣列 nums,返回 每個數字的平方 組成的新陣列,要求也按 非遞減順序 排序。

示例 1:

輸入:nums = [-4,-1,0,3,10]
輸出:[0,1,9,16,100]
解釋:平方後,陣列變為 [16,1,0,9,100] 排序後,陣列變為 [0,1,9,16,100]

示例 2:

輸入:nums = [-7,-3,2,3,11]
輸出:[4,9,9,49,121]

初始程式碼

from typing import List
class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        
#在此之間填寫程式碼 print(Solution().sortedSquares([-4,-1,0,3,10])) print(Solution().sortedSquares([-7,-3,2,3,11]))
View Code

2 解題思路

  • 標籤:雙指標
  • 如果陣列 nums 中的所有數都是非負數,那麼將每個數平方後,陣列仍然保持升序;
  • 如果陣列 nums 中的所有數都是負數,那麼將每個數平方後,陣列會保持降序。
  • 如果我們能夠找到陣列 nums 中負數與非負數的分界線,那麼就可以用類似「歸併排序」的方法了。
  • 具體地,使用兩個指標分別指向位置 neg 和 neg-1,每次比較兩個指標對應的數,選擇較小的那個放入答案並移動指標。
  • 當某一指標移至邊界時,將另一指標還未遍歷到的數依次放入答案。

#3 解題方法

from typing import List
class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        fd,a=0,len(nums)
        while fd<a:
            if nums[fd]>=0:
                break
            fd+=1
        fd,bk=fd,fd-1
        m=[]
        
while fd<a or bk>-1: if fd==a or (fd<a and bk>-1 and nums[fd]>=-nums[bk]): m.append(nums[bk]**2) bk-=1 else: m.append(nums[fd]**2) fd+=1 return m print(Solution().sortedSquares([-4,-1,0,3,10])) print(Solution().sortedSquares([-7,-3,2,3,11]))
View Code

第1-3,20-21行:題目中已經給出的資訊,執行程式碼時要根據這些程式碼進行編輯
第4行:定義前指標fd並賦值為0,同時定義變數a並複製列表的長度
第5-8行:找出列表中第一個大於等於0的元素並將其索引賦值給fd,若沒找到,則遍歷到最後
第9行:定義前指標、後指標分別為fd、bk,並賦值為fd和fd-1
第10行:定義空列表m用於存放排列後的結果
第11行:當前指標小於列表長度或者後指標大於等於0時執行迴圈
第12行:若前指標等於列表長度或前後指標符合題意且前指標對應列表值大於後指標時
第13-14行:在列表值新增後指標對應的數值的平方並將後指標向後移
第15-17行:其他情況下,在列表值新增前指標對應的數值的平方並將前指標向前移
第18行:返回最後排序後的列表

程式碼執行結果為:

#演算法講解

這裡用到了基礎技巧:雙指標,簡單講解下這個技巧:
什麼是雙指標(對撞指標、快慢指標)
雙指標,指的是在遍歷物件的過程中,不是普通的使用單個指標進行訪問,而是使用兩個相同方向(快慢指標)或者相反方向(對撞指標)的指標進行掃描,從而達到相應的目的。


用法
對撞指標
對撞指標是指在有序陣列中,將指向最左側的索引定義為左指標(left),最右側的定義為右指標(right),然後從兩頭向中間進行陣列遍歷。

對撞陣列適用於有序陣列,也就是說當你遇到題目給定有序陣列時,應該第一時間想到用對撞指標解題。

快慢指標
快慢指標也是雙指標,但是兩個指標從同一側開始遍歷陣列,將這兩個指標分別定義為快指標(fast)和慢指標(slow),兩個指標以不同的策略移動,直到兩個指標的值相等(或其他特殊條件)為止,如fast每次增長兩個,slow每次增長一個。