1. 程式人生 > 其它 >leetcode初級演算法——陣列

leetcode初級演算法——陣列

技術標籤:leetcodepython演算法陣列

(題目源自leetcode,方法都是自(cai)己(ji)寫的,可能比較符合菜雞們的思路)

1.刪除排序陣列中的重複項

給定一個排序陣列,你需要在 原地 刪除重複出現的元素,使得每個元素只出現一次,返回移除後陣列的新長度。

不要使用額外的陣列空間,你必須在 原地 修改輸入陣列 並在使用 O(1) 額外空間的條件下完成。

示例 1:

給定陣列 nums = [1,1,2],

函式應該返回新的長度 2, 並且原陣列 nums 的前兩個元素被修改為 1, 2。

你不需要考慮陣列中超出新長度後面的元素。

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        a=0
        b=1
        amount = 1
        if len(nums)==0:
            return 0
        while b<len(nums):
            if nums[a]==nums[b]:
                b=b+1
            else:
                a=a+1
                nums[a]=nums[b]
                b=b+1
                amount += 1
        return amount

使用雙指標,a記錄重複的需要更改的位置。b後移,遇到不同的元素,則對a位置的重複元素進行覆蓋。

2.買賣股票的最佳時機 II

給定一個數組,它的第 i 個元素是一支給定股票第 i 天的價格。

設計一個演算法來計算你所能獲取的最大利潤。你可以儘可能地完成更多的交易(多次買賣一支股票)。

注意:你不能同時參與多筆交易(你必須在再次購買前出售掉之前的股票)。

示例 1:

輸入: [7,1,5,3,6,4]
輸出: 7
解釋: 在第 2 天(股票價格 = 1)的時候買入,在第 3 天(股票價格 = 5)的時候賣出, 這筆交易所能獲得利潤 = 5-1 = 4 。
隨後,在第 4 天(股票價格 = 3)的時候買入,在第 5 天(股票價格 = 6)的時候賣出, 這筆交易所能獲得利潤 = 6-3 = 3 。

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        profit = 0
        for i in range(1,len(prices)):
            profit += max(0,prices[i]-prices[i-1])
        return profit

每一天比前一天高的價格均為利潤

3.旋轉陣列

給定一個數組,將陣列中的元素向右移動 k 個位置,其中 k 是非負數。

示例 1:

輸入: [1,2,3,4,5,6,7] 和 k = 3
輸出: [5,6,7,1,2,3,4]

解釋:
向右旋轉 1 步: [7,1,2,3,4,5,6]
向右旋轉 2 步: [6,7,1,2,3,4,5]
向右旋轉 3 步: [5,6,7,1,2,3,4]

class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        k = k%len(nums)
        while k > 0:
            nums.insert(0,nums.pop())
            k = k - 1

陣列每pop一個,就insert到前面。

4.存在重複元素

給定一個整數陣列,判斷是否存在重複元素。

如果任意一值在陣列中出現至少兩次,函式返回 true 。如果陣列中每個元素都不相同,則返回 false 。

示例 1:

輸入: [1,2,3,1]
輸出: true

class Solution:
    def containsDuplicate(self, nums: List[int]) -> bool:
        return len(nums)!=len(set(nums))

轉set去掉重複元素,與原列表長度不想等,說明重複了

5.只出現一次的數字

給定一個非空整數陣列,除了某個元素只出現一次以外,其餘每個元素均出現兩次。找出那個只出現了一次的元素。

說明:

你的演算法應該具有線性時間複雜度。 你可以不使用額外空間來實現嗎?

示例 1:

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

class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        nums.sort()
        for i in range(len(nums)//2+1):
            if 2*i==len(nums)-1:
                return nums[2*i]
            if nums[2*i]!=nums[2*i+1]:
                return nums[2*i]

排序後,第一個奇數位與後位不相同的,即為只出現一次的數字。

class Solution:
    def singleNumber(self, nums: List[int]) -> int:
		return sum(set(nums))*2-sum(nums)

一行程式碼,轉set的和雙倍減去原列表的和

6.兩個陣列的交集 II

給定兩個陣列,編寫一個函式來計算它們的交集。

示例 1:

輸入:nums1 = [1,2,2,1], nums2 = [2,2]
輸出:[2,2]

class Solution:
    def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
        small = nums1 if len(nums1)<len(nums2) else nums2
        big = nums2 if len(nums1)<len(nums2) else nums1
        out = []
        for i in range(len(small)):
            if small[i] in big:
                out.append(small[i])
                big.remove(small[i])
        return out

先找出較小的列表small,然後拿small的元素去big比較,重複則在輸出里加入該元素,並把big中的刪除,避免重複。

7.加一

給定一個由 整數 組成的 非空 陣列所表示的非負整數,在該數的基礎上加一。

最高位數字存放在陣列的首位, 陣列中每個元素只儲存單個數字。

你可以假設除了整數 0 之外,這個整數不會以零開頭。

示例 1:

輸入:digits = [1,2,3]
輸出:[1,2,4]
解釋:輸入陣列表示數字 123。

class Solution:
    def plusOne(self, digits: List[int]) -> List[int]:
        digits[-1] += 1
        for i in range(len(digits)-1,0,-1):
            if digits[i]==10:
                digits[i]=0
                digits[i-1]+=1
        
        if digits[0]==10:
            digits[0]=0
            digits.insert(0,1)
        
        return digits

挨位判斷加一是否為10,10則轉0進位
最後看第一位是不是10,是的話,補位。

8.移動零

給定一個數組 nums,編寫一個函式將所有 0 移動到陣列的末尾,同時保持非零元素的相對順序。

示例:

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

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        num = 0
        while num in nums:
            nums.remove(0)
            num = num + 1
        while num > 0:
            nums.append(0)
            num = num-1
        return nums

先檢查0,有的話就remove並記錄次數,最後在列表末尾補上。
也可以雙指標,後面不為0的和前面為0的互換。

9.兩數之和

給定一個整數陣列 nums 和一個目標值 target,請你在該陣列中找出和為目標值的那 兩個 整數,並返回他們的陣列下標。

你可以假設每種輸入只會對應一個答案。但是,陣列中同一個元素不能使用兩遍。

示例:

給定 nums = [2, 7, 11, 15], target = 9

因為 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        #nums.sort()
        for num in nums:
            if (target-num) in nums and (idx1:=nums.index(num))!= (idx2:=nums.index(target-num)):
                return [idx1,idx2]

遍歷列表中的元素num,如果num和target-num都在列表中,且兩者的index不同,則返回。

10.有效的數獨

判斷一個 9x9 的數獨是否有效。只需要根據以下規則,驗證已經填入的數字是否有效即可。

數字 1-9 在每一行只能出現一次。
數字 1-9 在每一列只能出現一次。
數字 1-9 在每一個以粗實線分隔的 3x3 宮內只能出現一次。

在這裡插入圖片描述

class Solution:
    def isValidSudoku(self, board: List[List[str]]) -> bool:
        rows, columns, boxes = defaultdict(set), defaultdict(set), defaultdict(set)
        for row in range(9):
            for col in range(9):
                if board[row][col]=='.':
                    continue
                if board[row][col] in rows[row]:
                    return False
                if board[row][col] in columns[col]:
                    return False
                if board[row][col] in boxes[(row//3)*3+col//3]:
                    return False
                rows[row].add(board[row][col])
                columns[col].add(board[row][col])
                boxes[(row//3)*3+col//3].add(board[row][col])
        return True

defaultdict(set)???待補充
遍歷元素,檢查是否符合條件,不符合條件則返回False

11.旋轉影象

給定一個 n × n 的二維矩陣表示一個影象。

將影象順時針旋轉 90 度。

說明:

你必須在原地旋轉影象,這意味著你需要直接修改輸入的二維矩陣。請不要使用另一個矩陣來旋轉影象。

示例 1:

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

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

class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        n = len(matrix[0])
        col = defaultdict(list)
        for i in range(n):
            for j in range(n):
                col[j].append(matrix[i][j])
        for r in range(n):
            for c in range(n):
                matrix[r][n-c-1]=col[r][c]

兩次遍歷,第一次複製列,第二次遍歷,根據規律在原列表上賦值。

class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        matrix[:] = zip(*reversed(matrix))

大佬一行解法,reversed???待補充