1. 程式人生 > 其它 >【LeetCode陣列相關】中心下標、旋轉影象、零矩陣

【LeetCode陣列相關】中心下標、旋轉影象、零矩陣

LeetCode724.尋找陣列的中心下標

給你一個整數陣列 nums ,請計算陣列的 中心下標 。

陣列 中心下標 是陣列的一個下標,其左側所有元素相加的和等於右側所有元素相加的和。

如果中心下標位於陣列最左端,那麼左側數之和視為 0 ,因為在下標的左側不存在元素。這一點對於中心下標位於陣列最右端同樣適用。

如果陣列有多箇中心下標,應該返回 最靠近左邊 的那一個。如果陣列不存在中心下標,返回 -1 。

示例 1:

輸入:nums = [1, 7, 3, 6, 5, 6]
輸出:3(我認為這裡是6才對)
解釋:
中心下標是 3 。
左側數之和 sum = nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11 ,
右側數之和 sum = nums[4] + nums[5] = 5 + 6 = 11 ,二者相等。

最開始的思路:

1、將原始的陣列翻轉得到一個新陣列,然後同時遍歷兩個陣列,當相加結果相同時返回當前下標對應的數

問題:

顯然,這種方法只適用於對稱的陣列,是特例

2、樸素的思想是雙層for迴圈去遍歷陣列,相加之後比較得出結果

問題:

因為需要確認邊界,所以慢,容易超時

解題思路:
使用字首法

有這樣的規律,

記陣列全部元素之和為numSum,當遍歷到第i個元素時,其左側元素總和為leftSum,右側則可以表示為全部元素之和減掉左側元素之和再減掉當前第i個元素,即

rightSum = numSum - leftSum - nums[i]

如果左右元素之和相等則找到中心下標

程式碼實現:

class Solution:
    def pivotIndex(self, nums: List[int]) -> int:
        numSum = sum(nums) #求陣列總和
        leftSum = 0
        for i in range(len(nums)):
            # 字首法
            if numSum - leftSum - nums[i] == leftSum: 
                #左右和相等,則返回當前下標
                return i
            #左側總和累加
            leftSum += nums[i]
        return -1

LeetCode48.旋轉影象

給你一幅由 N × N 矩陣表示的影象,其中每個畫素的大小為 4 位元組。請你設計一種演算法,將影象旋轉 90 度。

不佔用額外記憶體空間能否做到?

示例 1:

給定 matrix = 
[
  [1,2,3],
  [4,5,6],
  [7,8,9]
],

原地旋轉輸入矩陣,使其變為:
[
  [7,4,1],
  [8,5,2],
  [9,6,3]
]

示例 2:

給定 matrix =
[
  [ 5, 1, 9,11],
  [ 2, 4, 8,10],
  [13, 3, 6, 7],
  [15,14,12,16]
], 

原地旋轉輸入矩陣,使其變為:
[
  [15,13, 2, 5],
  [14, 3, 4, 1],
  [12, 6, 8, 9],
  [16, 7,10,11]
]

解題思路:

需要找規律,如果用暴力法。確定每個數變化後的位置再一個一個修改,演算法複雜度會比較高

翻轉法是本題一個比較好的結題思路

先將目標矩陣映象翻轉

[                         
  [1,2,3],
  [4,5,6],   
  [7,8,9]
]
映象↓
[
  [3,2,1],
  [6,5,4],     
  [9,8,7]
]

再沿主對角線對摺即可

[
  [3,2,1],
  [6,5,4],     
  [9,8,7]
]
主對角線翻轉↓
[
  [3,6,9],
  [2,5,8],     
  [1,4,7]
]
影象向左旋轉了90°

如果是先主對角線翻轉再映象翻轉的話,影象會向右旋轉90°

因為題目沒有規定方向,所以兩種都可以

程式碼:

class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        # 確定matrix長度
        m1= len(matrix)
        # 先用切片操作映象翻轉matrix
        # matrix[:]等於複製了一個一樣的matrix
        # matrix[::-1]相當於將物件映象翻轉
        matrix[:] = matrix[::-1] #得到映象翻轉後的matrix
        # 沿主對角線翻轉
        # 注意len不是從0開始的
        for i in range(m1):
            for j in range(i):
                matrix[j][i], matrix[i][j] = matrix[i][j], matrix[j][i]

ps:這裡有個python的小技巧--切片操作

例如,

a = 'saiodhoia'
b = a[:]
c = a[::-1]
print(b)
-->saiodhoia
print(c)
-->aiohdoias

# 上述操作對list依然有效

LeetCode73.零矩陣

編寫一種演算法,若M × N矩陣中某個元素為0,則將其所在的行與列清零。

示例 1:

輸入:
[
  [1,1,1],
  [1,0,1],
  [1,1,1]
]
輸出:
[
  [1,0,1],
  [0,0,0],
  [1,0,1]
]

示例 2:

輸入:
[
  [0,1,2,0],
  [3,4,5,2],
  [1,3,1,5]
]
輸出:
[
  [0,0,0,0],
  [0,4,5,0],
  [0,3,1,0]
]

解題思路:

很容易想到用遍歷的方式去做。遇到0怎麼處理是關鍵

一種樸素的解法是使用兩次遍歷

第一次遍歷確定0的位置並儲存下來,第二次根據第一次儲存的位置資訊修改矩陣中的值

程式碼:

class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        # 獲取內外層陣列長度
        m1, m2 = len(matrix), len(matrix[0])
        # 定義兩個陣列用於存放位置資訊,1表示在原陣列中該位置不為0
        row, column = [1]*m1, [1]*m2

        # 第一遍遍歷,定位出0的位置
        for i in range(m1):
            for j in range(m2):
                if matrix[i][j] == 0:
                    # 找到0就標記一下
                    row[i] = 0
                    column[j] = 0
        
        # 第二遍遍歷,按照位置資訊修改矩陣
        for i in range(m1):
            for j in range(m2):
                if row[i] == 0 or column[j] == 0:
                    matrix[i][j] = 0

還有更優解,之後有空再優化