程式設計小白用Python刷LeetCode學習筆記——前100題

夬_syx發表於2018-10-07

程式設計小白用Python刷LeetCode學習筆記

程式設計小白剛學完Python的基本語法,開始試著用Python刷LeetCode,連最簡單的題目都是看答案的,很心酸,不過不管能不能提高程式設計能力,至少可以學點演算法知識吧,希望能堅持。記錄一下答案。

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]
        """
        d = {}
        for i, n in enumerate(nums):
            m = target - n
            if m in d:
                return [d[m], i]
            else:
                d[n] = i

7.反轉整數
給定一個 32 位有符號整數,將整數中的數字進行反轉。

示例 1:
輸入: 123
輸出: 321
示例 2:
輸入: -123
輸出: -321
示例 3:
輸入: 120
輸出: 21

注意:
假設我們的環境只能儲存 32 位有符號整數,其數值範圍是 [−231, 231 − 1]。根據這個假設,如果反轉後的整數溢位,則返回 0。

解:

class Solution:
    def reverse(self, x):
        """
        :type x: int
        :rtype: int
        """
        tmp=abs(x)
        sum=0
        while tmp>0:
            sum=sum*10+tmp%10
            tmp=tmp//10
        if x<0:
            sum=-sum
        if sum<2**31 and sum>-2**31:
            return sum
        else:
            return 0
            

9.迴文數
這道題自己嘗試寫了一下,把數字轉換成字串放在列表裡再比較反轉前後兩個列表是否相同,提交後速度確實不快,只擊敗33%左右的答案,看了下別人寫的最優解,速度一下子就提高了很多。非常弱了,但是至少自己嘗試著寫出一個解了,菜鳥暗自開心一下下,雖然題目真的超簡單,其實本科學C的時候就寫過了,然而並沒有記住。
自己寫的解:

class Solution:
    def isPalindrome(self, x):
        """
        :type x: int
        :rtype: bool
        """
        strs=list(str(x))
        tmp=[]
        for value in strs:
            tmp.insert(0,value)
        return strs==tmp

偷偷看的最優解:

class Solution:
    def isPalindrome(self, x):
        """
        :type x: int
        :rtype: bool
        """
        if x<0:
            return False
        high=1
        while x/high>=10:
            high*=10
        while x//high==x%10:
            x=x%high//10
            high=high/100
            if high<1:
                return True
        return False
        

羅馬數字包含以下七種字元: I, V, X, L,C,D 和 M。

字元 數值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

13.羅馬數字轉整數

例如, 羅馬數字 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
解釋: L = 50, V= 5, III = 3.

示例 5:

輸入: “MCMXCIV”
輸出: 1994
解釋: M = 1000, CM = 900, XC = 90, IV = 4.
解法一:

class Solution:
    def romanToInt(self, s):
        """
        :type s: str
        :rtype: int
        """
        rom_map={'I':1,
            'V':5,
            'X':10,
            'L':50,
            'C':100,
            'D':500,
            'M':1000}
        last_num=None
        result=0
        for char in s:
            curent_num=rom_map[char]
            if last_num is None or last_num>=curent_num:
                result+=curent_num
            elif last_num<curent_num:
                result+=curent_num-2*last_num
            last_num=curent_num
        return result

解法二:

class Solution(object):
    def romanToInt(self, s):
        """
        :type s: str
        :rtype: int
        """
        sum=0
        convert={'M': 1000,'D': 500 ,'C': 100,'L': 50,'X': 10,'V': 5,'I': 1} 
        for i in range(len(s)-1):
            #if (s[i]=='I' or s[i]=='X' or s[i]=='C') and convert[s[i]]<convert[s[i+1]]:
            if convert[s[i]]<convert[s[i+1]]:
                sum=sum-convert[s[i]]
            else:
                sum=sum+convert[s[i]]
        return sum+convert[s[-1]]

14.最長公共字首
編寫一個函式來查詢字串陣列中的最長公共字首。
如果不存在公共字首,返回空字串 “”。

示例 1:

輸入: [“flower”,“flow”,“flight”]
輸出: “fl”

示例 2:

輸入: [“dog”,“racecar”,“car”]
輸出: “”
解釋: 輸入不存在公共字首。

說明:

所有輸入只包含小寫字母 a-z 。

解:

class Solution(object):
    def longestCommonPrefix(self, strs):
        """
        :type strs: List[str]
        :rtype: str
        """

        if not strs: 
            return ''
        s1 = min(strs)
        s2 = max(strs)
        for i,c in enumerate(s1):
            if c != s2[i]:
                    return s1[:i]
        return s1


20.有效的括號
給定一個只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字串,判斷字串是否有效。

有效字串需滿足:

左括號必須用相同型別的右括號閉合。
左括號必須以正確的順序閉合。

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

示例 1:

輸入: “()”
輸出: true

示例 2:

輸入: “()[]{}”
輸出: true

示例 3:

輸入: “(]”
輸出: false

示例 4:

輸入: “([)]”
輸出: false

示例 5:

輸入: “{[]}”
輸出: true

解:

class Solution:
    def isValid(self, s):
        """
        :type s: str
        :rtype: bool
        """
        top_element=''
        stack=[]
        mapping={')':'(',']':'[','}':'{'}
        for char in s:
            if char in mapping:
                if stack:
                    top_element=stack.pop()
                else:
                    '#'
                if mapping[char]!=top_element:
                    return False
            else:
                stack.append(char)
        return not stack
        

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:
    def mergeTwoLists(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        if l1==None:
            return l2
        if l2==None:
            return l1
        if l1.val<=l2.val:
            ret=l1
            ret.next = self.mergeTwoLists(l1.next, l2)
        else:
            ret=l2
            ret.next = self.mergeTwoLists(l1, l2.next)
        return ret
            

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(object):
    def removeDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        pos=0
        this_num=None
        for num in nums:
            if num!=this_num:
                nums[pos]=num
                this_num=num
                pos+=1
        return pos

35.搜尋插入位置
我自己寫的窮舉法:

class Solution:
    def searchInsert(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        if nums[0]>target:
            return 0
        if nums[-1]<target:
            return len(nums)
        for i in range(len(nums)):
            if nums[i]==target:
                return i
            elif nums[i]<target and nums[i+1]>target:
                return i+1

一般遇到有序陣列都應該想到用二分法,下面是一個用二分法的遞迴函式:

class Solution:
    def searchInsert(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        def bs(numlsit, l, r):
            while l <= r:
                mid = int((l + r) / 2)
                if numlsit[mid] == target:
                    return mid
                elif numlsit[mid] < target:
                    return bs(numlsit, mid+1, r)
                else:
                    return bs(numlsit, l, mid-1)
            return l
        
        return bs(nums, 0, len(nums)-1)

53.最大子序和
給定一個整數陣列 nums ,找到一個具有最大和的連續子陣列(子陣列最少包含一個元素),返回其最大和。

示例:

輸入: [-2,1,-3,4,-1,2,1,-5,4],
輸出: 6
解釋: 連續子陣列 [4,-1,2,1] 的和最大,為 6。

解:

class Solution:
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        sums=0
        maxsum=nums[0]
        for value in nums:
            sums=sums+value
            if maxsum<sums:
                maxsum=sums
            if sums<0:
                sums=0
        return maxsum

解法二:

class Solution:
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        length=len(nums)
        for i in range(1,length):
            #當前值的大小與前面的值之和比較,若當前值更大,則取當前值,捨棄前面的值之和
            subMaxSum=max(nums[i]+nums[i-1],nums[i])
            nums[i]=subMaxSum#將當前和最大的賦給nums[i],新的nums儲存的為和值
        return max(nums)

58.最後一個單詞長度
給定一個僅包含大小寫字母和空格 ’ ’ 的字串,返回其最後一個單詞的長度。

如果不存在最後一個單詞,請返回 0 。

說明:一個單詞是指由字母組成,但不包含任何空格的字串。
解:

class Solution:
    def lengthOfLastWord(self, s):
        """
        :type s: str
        :rtype: int
        """
        str = ''
        count = 0
        for i in s[::-1]:
            if str != '' and i==' ':
                return count
            if i != ' ':
                count = count+ 1
                str = str + i
        return count

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

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

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

示例 1:

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

輸入: [4,3,2,1]
輸出: [4,3,2,2]
解釋: 輸入陣列表示數字 4321。
我自己寫的解法:先把列表還原成數然後加一再換回列表

class Solution:
    def plusOne(self, digits):
        """
        :type digits: List[int]
        :rtype: List[int]
        """
        num=0
        for value in digits:
            num=num*10+value
        num=num+1
        new_list=[None]*len(str(num))
        i=len(str(num))-1
        while num>0:
            new_list[i]=num%10
            num=num//10
            i-=1
        return new_list

別人的直接解法:

class Solution(object):
    def plusOne(self, digits):
        """
        :type digits: List[int]
        :rtype: List[int]
        """
        carry = 1
        for i in reversed(range(0, len(digits))):
            digit = (digits[i] + carry) % 10
            carry = 1 if digit < digits[i] else 0
            digits[i] = digit
        if carry == 1:
            return [1] + digits
        return digits

69.x的平方根

實現 int sqrt(int x) 函式。

計算並返回 x 的平方根,其中 x 是非負整數。

由於返回型別是整數,結果只保留整數的部分,小數部分將被捨去。

示例 1:

輸入: 4
輸出: 2
示例 2:

輸入: 8
輸出: 2
說明: 8 的平方根是 2.82842…,
由於返回型別是整數,小數部分將被捨去。
解法一:
我的想法是用牛頓迭代法求:

class Solution:
    def mySqrt(self, x):
        """
        :type x: int
        :rtype: int
        """
        y=1
        lasty=2
        while y-lasty>=1 or lasty-y>=1:
            lasty=y
            y=(lasty+x/lasty)/2
        return int(y)
            

解法二:二分法

class Solution:
    def mySqrt(self, x):
        left=0;right=x
        while left<right:
            mid=int((left+right)/2)
            if x<mid**2:
                right=mid
            else:
                left=mid+1
        if left>1:
            return left-1
        else:
            return left

70.爬樓梯
假設你正在爬樓梯。需要 n 階你才能到達樓頂。

每次你可以爬 1 或 2 個臺階。你有多少種不同的方法可以爬到樓頂呢?

注意:給定 n 是一個正整數。

示例 1:

輸入: 2
輸出: 2
解釋: 有兩種方法可以爬到樓頂。

  1. 1 階 + 1 階
  2. 2 階
    示例 2:

輸入: 3
輸出: 3
解釋: 有三種方法可以爬到樓頂。
3. 1 階 + 1 階 + 1 階
4. 1 階 + 2 階
5. 2 階 + 1 階
**注意:**此時相當於求斐波那契數列的第n個數

class Solution(object):
    def climbStairs(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n<=2:
            return n
        a=[0]*(n+1)
        a[1]=1
        a[2]=2
        for i in range(3,n+1):
            a[i]=a[i-1]+a[i-2]
        return a[n]

88.合併兩個有序陣列
給定兩個有序整數陣列 nums1 和 nums2,將 nums2 合併到 nums1 中,使得 num1 成為一個有序陣列。

說明:

初始化 nums1 和 nums2 的元素數量分別為 m 和 n。
你可以假設 nums1 有足夠的空間(空間大小大於或等於 m + n)來儲存 nums2 中的元素。
示例:

輸入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3

輸出: [1,2,2,3,5,6]
我的解法:

class Solution:
    def merge(self, nums1, m, nums2, n):
        """
        :type nums1: List[int]
        :type m: int
        :type nums2: List[int]
        :type n: int
        :rtype: void Do not return anything, modify nums1 in-place instead.
        """
        num=nums1[:m]+nums2
        for i in range(m+n):
            value=min(num)
            nums1[i]=value
            num.remove(value)

別人的解法,我真是想不到。。。

class Solution:
    def merge(self, nums1, m, nums2, n):
        """
        :type nums1: List[int]
        :type m: int
        :type nums2: List[int]
        :type n: int
        :rtype: void Do not return anything, modify nums1 in-place instead.
        """
        while m>0 and n>0:
            if nums1[m-1]>=nums2[n-1]:
                nums1[m+n-1]=nums1[m-1]
                m-=1
            else:
                nums1[m+n-1]=nums2[n-1]
                n-=1
        if n>0:
            nums1[:n]=nums2[:n]

相關文章