leetcode初級演算法——陣列
(題目源自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???待補充