【leetcode】python演算法題庫——簡單難度【1】
1. 兩數之和
給定一個整數陣列和一個目標值,找出陣列中和為目標值的兩個數。
你可以假設每個輸入只對應一種答案,且同樣的元素不能被重複利用。
示例:
給定 nums = [2, 7, 11, 15], target = 9
因為 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
程式碼:
class Solution: def twoSum(self, nums, target): """ :type nums: List[int] :type target: int :rtype: List[int] """ for i in range(len(nums) - 1): for j in range(i + 1, len(nums)): if nums[i] + nums[j] == target: return [i,j] else: continue if __name__ == '__main__': nums = [2,7,11,15] target = 9 out = Solution() output = out.twoSum(nums, target) print(output) #[0, 1]
7. 反轉整數
給定一個 32 位有符號整數,將整數中的數字進行反轉。
示例 1:
輸入: 123
輸出: 321
示例 2:
輸入: -123
輸出: -321
示例 3:
輸入: 120
輸出: 21
注意:
假設我們的環境只能儲存 32 位有符號整數,其數值範圍是 。根據這個假設,如果反轉後的整數溢位,則返回 0。
程式碼:
class Solution: def reverse(self, x): """ :type x: int :rtype: int """ if -10 < x < 10: return x elif (x < (-2**31)) or (x > 2**31 -1): return 0 else: a = abs(x) b = str(a) c = b[::-1] d = int(c) if x < 0: return -d else: return d if __name__ == '__main__': x = -120 out = Solution() output = out.reverse(x) print(output) #-21
9. 迴文數
判斷一個整數是否是迴文數。迴文數是指正序(從左向右)和倒序(從右向左)讀都是一樣的整數。
示例 1:
輸入: 121
輸出: true
示例 2:
輸入: -121
輸出: false
解釋: 從左向右讀, 為 -121 。 從右向左讀, 為 121- 。因此它不是一個迴文數。
示例 3:
輸入: 10
輸出: false
解釋: 從右向左讀, 為 01 。因此它不是一個迴文數。
進階:
你能不將整數轉為字串來解決這個問題嗎?
程式碼:
class Solution: def isPalindrome(self, x): """ :type x: int :rtype: bool """ a = str(x) b = a[::-1] return a==b if __name__ == '__main__': x = 101 out = Solution() output = out.isPalindrome(x) print(output) #True
13. 羅馬數字轉整數
羅馬數字包含以下七種字元:I
, V
, X
, L
,C
,D
和 M
。
字元 數值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
例如, 羅馬數字 2 寫做 II
,即為兩個並列的 1。12 寫做 XII
,即為 X
+ II
。 27 寫做 XXVII
, 即為 XX
+ V
+ II
。
通常情況下,羅馬數字中小的數字在大的數字的右邊。但也存在特例,例如 4 不寫做 IIII
,而是 IV
。數字 1 在數字 5 的左邊,所表示的數等於大數 5 減小數 1 得到的數值 4 。同樣地,數字 9 表示為 IX
。這個特殊的規則只適用於以下六種情況:
I
可以放在V
(5) 和X
(10) 的左邊,來表示 4 和 9。X
可以放在L
(50) 和C
(100) 的左邊,來表示 40 和 90。C
可以放在D
(500) 和M
(1000) 的左邊,來表示 400 和 900。
給定一個羅馬數字,將其轉換成整數。輸入確保在 1 到 3999 的範圍內。
示例 1:
輸入: "III"
輸出: 3
示例 2:
輸入: "IV"
輸出: 4
示例 3:
輸入: "IX"
輸出: 9
示例 4:
輸入: "LVIII"
輸出: 58
解釋: C = 100, L = 50, XXX = 30, III = 3.
示例 5:
輸入: "MCMXCIV"
輸出: 1994
解釋: M = 1000, CM = 900, XC = 90, IV = 4.
程式碼:
class Solution:
def romanToInt(self, s):
"""
:type s: str
:rtype: int
"""
sum = 0
romanDict = {'M': 1000,'D': 500 ,'C': 100,'L': 50,'X': 10,'V': 5,'I': 1}
for i in range(len(s)-1):
if romanDict[s[i]] < romanDict[s[i+1]]:
sum = sum - romanDict[s[i]]
else:
sum = sum + romanDict[s[i]]
result = sum + romanDict[s[-1]]
if 1 <= result <= 3999:
return result
else:
return 'out of range'
if __name__ == '__main__':
s = 'MCMXCIV'
out = Solution()
output = out.romanToInt(s)
print(output) #1994
14. 最長公共字首
編寫一個函式來查詢字串陣列中的最長公共字首。
如果不存在公共字首,返回空字串 ""
。
示例 1:
輸入: ["flower","flow","flight"]
輸出: "fl"
示例 2:
輸入: ["dog","racecar","car"]
輸出: ""
解釋: 輸入不存在公共字首。
說明:
所有輸入只包含小寫字母 a-z
。
程式碼:
import os
class Solution:
# 方法一:直接呼叫現有函式
def longestCommonPrefix_use_os(self, strs):
"""
:type strs: List[str]
:rtype: str
"""
prefix = os.path.commonprefix(strs) # 返回list中,所有元素共有的最長的字首
return prefix
# 方法二:迴圈遍歷每個字串相同索引處的字元是否一致
def longestCommonPrefix(self, strs):
"""
:type strs: List[str]
:rtype: str
"""
# 列表按照各個元素的長度排序
strs = sorted(strs, key=lambda i: len(i))
prefix = ''
# 判斷是否為空列表
if not strs:
return prefix
else:
for i in range(len(strs[0])):
tmp = strs[0][i]
for item in strs:
if item[i] != tmp:
return prefix
prefix += tmp
return prefix
# 方法三:
def longestCommonPrefix_use_zip(self, strs):
"""
:type strs: List[str]
:rtype: str
"""
prefix = ''
# enumerate() 函式用於將一個可遍歷的資料物件(如列表、元組或字串)
# 組合為一個索引序列,同時列出資料和資料下標
for _, item in enumerate(zip(*strs)):
if len(set(item)) > 1:
return prefix
else:
prefix += item[0]
return prefix
if __name__ == '__main__':
strs = ["flower","flow","flight",'flop']
out = Solution()
output = out.longestCommonPrefix_use_os(strs)
print(output) #fl
20. 有效的括號
給定一個只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字串,判斷字串是否有效。
有效字串需滿足:
- 左括號必須用相同型別的右括號閉合。
- 左括號必須以正確的順序閉合。
注意空字串可被認為是有效字串。
示例 1:
輸入: "()"
輸出: true
示例 2:
輸入: "()[]{}"
輸出: true
示例 3:
輸入: "(]"
輸出: false
示例 4:
輸入: "([)]"
輸出: false
示例 5:
輸入: "{[]}"
輸出: true
程式碼:
class Solution:
def isValid1(self, s):
"""
:type s: str
:rtype: bool
"""
if len(s)%2 != 0 or len(s) ==0:
return False
sDict = {'(':1, ')':1, '{':2, '}':2, '[':3, ']':3}
result = 0
for i in range(0, len(s)-1, 2):
result += sDict[s[i]] - sDict[s[i+1]]
return result==0
def isValid2(self, s):
"""
:type s: str
:rtype: bool
"""
# 排除空列表和奇數個元素的列表
if len(s) % 2 == 1 or len(s) == 0:
return False
d = {'{': '}', '[': ']', '(': ')'}
stack = []
for i in s:
if i in d:
stack.append(i)
else:
# 若第一個就是右括號直接排除,不是右括號再入棧
if not stack or d[stack.pop()] != i:
return False
return stack == []
def isValid3(self, s):
"""
:type s: str
:rtype: bool
"""
a = {')':'(', ']':'[', '}':'{'}
l = [None]
for i in s:
if i in a and a[i] == l[-1]:
l.pop()
else:
l.append(i)
return len(l)==1
if __name__ == '__main__':
s = '{[]}'
out = Solution()
output = out.isValid1(s)
print(output) #True
21. 合併兩個有序連結串列
將兩個有序連結串列合併為一個新的有序連結串列並返回。新連結串列是通過拼接給定的兩個連結串列的所有節點組成的。
示例:
輸入:1->2->4, 1->3->4
輸出:1->1->2->3->4->4
程式碼:
# Definition for singly-linked list.
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
# 方法1:遞迴方法
def mergeTwoLists1(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
# 判斷l1和l2是否存在空連結串列,有空連結串列就可以直接返回
if l1==None and l2==None:
return None
if l1==None:
return l2
if l2==None:
return l1
# 找出l1和l2中最小的結點,作為新連結串列的表頭結點
# 然後依次比較遍歷l1和l2,將較小的結點插入在新連結串列的後面
if l1.val<=l2.val:
l1.next=self.mergeTwoLists(l1.next,l2)
return l1
else:
l2.next=self.mergeTwoLists(l1,l2.next)
return l2
# 方法2:非遞迴方法
def mergeTwoLists2(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
head = ListNode(0)
first = head
while l1!=None and l2!=None:
if l1.val <= l2.val:
head.next = l1
l1 = l1.next
else:
head.next = l2
l2 = l2.next
head = head.next
if l1 != None:
head.next = l1
elif l2 != None:
head.next = l2
return first.next
26. 刪除排序陣列中的重複項
給定一個排序陣列,你需要在原地刪除重複出現的元素,使得每個元素只出現一次,返回移除後陣列的新長度。
不要使用額外的陣列空間,你必須在原地修改輸入陣列並在使用 O(1) 額外空間的條件下完成。
示例 1:
給定陣列 nums = [1,1,2],
函式應該返回新的長度 2, 並且原陣列 nums 的前兩個元素被修改為 1, 2。
你不需要考慮陣列中超出新長度後面的元素。
示例 2:
給定 nums = [0,0,1,1,1,2,2,3,3,4],
函式應該返回新的長度 5, 並且原陣列 nums 的前五個元素被修改為 0, 1, 2, 3, 4。
你不需要考慮陣列中超出新長度後面的元素。
說明:
為什麼返回數值是整數,但輸出的答案是陣列呢?
請注意,輸入陣列是以“引用”方式傳遞的,這意味著在函式裡修改輸入陣列對於呼叫者是可見的。
你可以想象內部操作如下:
// nums 是以“引用”方式傳遞的。也就是說,不對實參做任何拷貝
int len = removeDuplicates(nums);
// 在函式裡修改輸入陣列對於呼叫者是可見的。
// 根據你的函式返回的長度, 它會打印出陣列中該長度範圍內的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}
程式碼:
class Solution:
# 方法一,不按照元素大小順序排列
def removeDuplicates1(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
x = []
[x.append(i) for i in nums if not i in x]
return x
# 方法二,按照元素大小順序排列
def removeDuplicates2(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
x = list(set(nums))
return x
if __name__ == '__main__':
nums = [0,0,1,1,1,4,2,2,3,3,4]
out = Solution()
output = out.removeDuplicates2(nums)
print(output) #[0, 1, 2, 3, 4]
27. 移除元素
給定一個數組 nums 和一個值 val,你需要原地移除所有數值等於 val 的元素,返回移除後陣列的新長度。
不要使用額外的陣列空間,你必須在原地修改輸入陣列並在使用 O(1) 額外空間的條件下完成。
元素的順序可以改變。你不需要考慮陣列中超出新長度後面的元素。
示例 1:
給定 nums = [3,2,2,3], val = 3,
函式應該返回新的長度 2, 並且 nums 中的前兩個元素均為 2。
你不需要考慮陣列中超出新長度後面的元素。
示例 2:
給定 nums = [0,1,2,2,3,0,4,2], val = 2, 函式應該返回新的長度5
, 並且 nums 中的前五個元素為0
,1
,3
,0
, 4。 注意這五個元素可為任意順序。 你不需要考慮陣列中超出新長度後面的元素。
說明:
為什麼返回數值是整數,但輸出的答案是陣列呢?
請注意,輸入陣列是以“引用”方式傳遞的,這意味著在函式裡修改輸入陣列對於呼叫者是可見的。
你可以想象內部操作如下:
// nums 是以“引用”方式傳遞的。也就是說,不對實參作任何拷貝
int len = removeElement(nums, val);
// 在函式裡修改輸入陣列對於呼叫者是可見的。
// 根據你的函式返回的長度, 它會打印出陣列中該長度範圍內的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}
程式碼:
class Solution:
def removeElement(self, nums, val):
"""
:type nums: List[int]
:type val: int
:rtype: int
"""
while val in nums:
nums.remove(val)
return len(nums)
if __name__ == '__main__':
nums = [0,1,2,2,3,0,4,2]
val = 2
out = Solution()
output = out.removeElement(nums, val)
print(output) #5
28. 實現strStr()
實現 strStr() 函式。
給定一個 haystack 字串和一個 needle 字串,在 haystack 字串中找出 needle 字串出現的第一個位置 (從0開始)。如果不存在,則返回 -1。
示例 1:
輸入: haystack = "hello", needle = "ll"
輸出: 2
示例 2:
輸入: haystack = "aaaaa", needle = "bba"
輸出: -1
說明:
當 needle
是空字串時,我們應當返回什麼值呢?這是一個在面試中很好的問題。
對於本題而言,當 needle
是空字串時我們應當返回 0 。這與C語言的 strstr() 以及 Java的 indexOf() 定義相符。
程式碼:
class Solution:
def strStr1(self, haystack, needle):
"""
:type haystack: str
:type needle: str
:rtype: int
"""
return haystack.find(needle)
# Python index() 方法檢測字串中是否包含子字串 str ,
# 如果指定 beg(開始) 和 end(結束) 範圍,則檢查是否包含在指定範圍內,
# 該方法與 python find()方法一樣,只不過如果str不在 string中會報一個異常。
def strStr2(self, haystack, needle):
"""
:type haystack: str
:type needle: str
:rtype: int
"""
try:
return haystack.index(needle)
except:
return -1
if __name__ == '__main__':
haystack = 'hello'
needle = 'll'
out = Solution()
output = out.strStr1(haystack, needle)
print(output) #2
35. 搜尋插入位置
給定一個排序陣列和一個目標值,在陣列中找到目標值,並返回其索引。如果目標值不存在於陣列中,返回它將會被按順序插入的位置。
你可以假設陣列中無重複元素。
示例 1:
輸入: [1,3,5,6], 5
輸出: 2
示例 2:
輸入: [1,3,5,6], 2
輸出: 1
示例 3:
輸入: [1,3,5,6], 7
輸出: 4
示例 4:
輸入: [1,3,5,6], 0
輸出: 0
程式碼:
class Solution:
def searchInsert(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
nums.append(target)
# 列表去重後排序
nums = sorted(set(nums))
return nums.index(target)
if __name__ == '__main__':
nums = [1,3,5,6]
target = 7
out = Solution()
output = out.searchInsert(nums, target)
print(output) #4
38. 報數
報數序列是指一個整數序列,按照其中的整數的順序進行報數,得到下一個數。其前五項如下:
1. 1
2. 11
3. 21
4. 1211
5. 111221
1
被讀作 "one 1"
("一個一"
) , 即 11
。11
被讀作 "two 1s"
("兩個一"
), 即 21
。21
被讀作 "one 2"
, "one 1"
("一個二"
, "一個一"
) , 即 1211
。
給定一個正整數 n ,輸出報數序列的第 n 項。
注意:整數順序將表示為一個字串。
示例 1:
輸入: 1
輸出: "1"
示例 2:
輸入: 4
輸出: "1211"
程式碼:
class Solution:
def countAndSay(self, n):
"""
:type n: int
:rtype: str
"""
if n <= 0 or not str(n).isdigit():
return False
if n == 1:
return "1"
if n == 2:
return "11"
# 進行i=3時的迴圈時,它的上一項為'11'
result = '11'
# 用for迴圈不斷去計算逼近最後一次
for i in range(3, n+1):
res = "" # 結果,每次報數都要初始化
count = 1 # 計數變數
for j in range(1, len(result)):
if result[j-1] == result[j]:
count += 1 # 相等則加一
else:
# 一旦遇到不同的變數,就更新結果
res += str(count) + result[j-1]
count = 1 # 重置為1
# 把最後一項及它的數量加上
res += str(count) + result[j]
# 儲存上一次的結果
result = res
return result
if __name__ == '__main__':
n = 5
out = Solution()
output = out.countAndSay(n)
print(output) #111221
class Solution(object):
# 不遞迴方法
def countAndSay(self, n):
"""
:type n: int
:rtype: str
"""
basic_count_say = "1"
for num in range(n - 1): # 從第二個報數開始計算
basic_count_say = self.transform(basic_count_say) # 呼叫報數變換函式
return basic_count_say
def transform(self, basic_count_say): # 報數變換
count = 0 # 某個數字連續出現的次數
temp_cha = basic_count_say[0] # 當前數字
new_str = "" # 新的報數序列
for cha in basic_count_say: # 遍歷舊的報數序列
if temp_cha == cha: # 相同連續數字累加
count += 1
else: # 出現不相同數字就補充新報數序列
new_str = new_str + str(count) + temp_cha
temp_cha = cha # 清零,從頭累加新的數字
count = 1
new_str = new_str + str(count) + temp_cha # 最後一個數字補充到新報數序列中
return new_str
if __name__ == '__main__':
n = 5
out = Solution()
output = out.countAndSay(n)
print(output)
class Solution:
# 遞迴方法
def countAndSay(self, n):
"""
:type n: int
:rtype: str
"""
if n == 1:
return "1"
s = self.countAndSay(n - 1) # !!!!遞迴
count = 0 # 某個數字連續出現的次數
temp_cha = s[0] # 當前數字
new_str = "" # 新的報數序列
for cha in s: # 遍歷舊的報數序列
if temp_cha == cha: # 相同連續數字累加
count += 1
else: # 出現不相同數字就補充新報數序列
new_str = new_str + str(count) + temp_cha
temp_cha = cha # 清零,從頭累加新的數字
count = 1
new_str = new_str + str(count) + str(temp_cha) # 最後一個數字補充到新報數序列中
return new_str
if __name__ == '__main__':
n = 5
out = Solution()
output = out.countAndSay(n)
print(output)
53. 最大子序和
給定一個整數陣列 nums
,找到一個具有最大和的連續子陣列(子陣列最少包含一個元素),返回其最大和。
示例:
輸入: [-2,1,-3,4,-1,2,1,-5,4],
輸出: 6
解釋: 連續子陣列 [4,-1,2,1] 的和最大,為 6。
進階:
如果你已經實現複雜度為 O(n) 的解法,嘗試使用更為精妙的分治法求解。
程式碼:
class Solution:
# 窮舉法,時間複雜度:O(N^2)
def maxSubArray_enu(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
# 若列表元素均小於0,則最大子序列為值最大的元素
if max(nums) < 0:
return max(nums)
# 若列表元素不全小於0
l = len(nums)
maxres = 0
for i in range(0, l):
temp = 0
for j in range(i, l):
temp += nums[j]
if temp > maxres:
maxres = temp
return maxres
# 動態規劃法,時間複雜度:O(N)
# 最大連續的子序列和必須是在位置0-(n-1)之間的某個位置結束
# 將一個問題用動態規劃方法處理的準則:
# “最優子結構”、“子問題重疊”、“邊界”和“子問題獨立”
def maxSubArray_dyn(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
# 若列表元素均小於0,則最大子序列為值最大的元素
if max(nums) < 0:
return max(nums)
# 若列表元素不全小於0
l = len(nums)
maxres = 0
temp = 0
for i in range(l):
# 當迴圈遍歷到第i個位置時,如果其前面的連續子序列和小於等於0,
# 那麼以位置i結尾的最大連續子序列和就是第i個位置的值即nums[i]
if temp < 0:
maxres = nums[i]
# 如果其前面的連續子序列和大於0,
# 則以位置i結尾的最大連續子序列和為maxres[i] = max{ maxres[i-1]+nums[i],nums[i]}
else:
temp += nums[i]
if temp > maxres:
maxres = temp
return maxres
if __name__ == '__main__':
nums = [-2,1,-3,4,-1,2,1,-5,4]
# nums = [-2, -1, -3, -4, -1, -2, -1, -5, -4]
out = Solution()
output = out.maxSubArray_dyn(nums)
print(output) #6
58. 最後一個單詞的長度
給定一個僅包含大小寫字母和空格 ' '
的字串,返回其最後一個單詞的長度。
如果不存在最後一個單詞,請返回 0 。
說明:一個單詞是指由字母組成,但不包含任何空格的字串。
示例:
輸入: "Hello World"
輸出: 5
程式碼:
class Solution:
def lengthOfLastWord(self, s):
"""
:type s: str
:rtype: int
"""
word = s.split(' ')
return len(word[-1])
if __name__ == '__main__':
s = "Hello World"
out = Solution()
output = out.lengthOfLastWord(s)
print(output) #5