1. 程式人生 > >【leetcode】python演算法題庫——簡單難度【1】

【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 位有符號整數,其數值範圍是  [-2^{^{31}}, 2^{^{31}}-1] 。根據這個假設,如果反轉後的整數溢位,則返回 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, LCD 和 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. 左括號必須用相同型別的右括號閉合。
  2. 左括號必須以正確的順序閉合。

注意空字串可被認為是有效字串。

示例 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