leetcode刷題總結(六)

2019/9/21:迴文數

題目鏈接:https://leetcode-cn.com/problems/palindrome-number/

這題考慮兩種方式,轉換成字符串或者就用整數本身進行操作:

class Solution(object):
    def isPalindrome(self, x):
        """
        :type x: int
        :rtype: bool
        """
        return True if str(x)==str(x)[::-1] else False

直接整數考慮可以這樣:

首先用一個變量記錄數字的最高位,比如12321,可以標記爲help爲10000,第一個末位爲1,第一個首位爲12321/10000=1,接下來我們需要計算232是否爲迴文。我們需要去掉首位和末位。可以採用x % help / 10的方式,12321%10000 ==2321可以將最高位去掉,然後2321/10 ==232可以將最低爲去掉。最後不要忘記將help/100

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

2019/9/22:字符串轉換整數 (atoi)

題目鏈接:https://leetcode-cn.com/problems/string-to-integer-atoi/

class Solution:
    def myAtoi(self, s: str) -> int:
        return max(min(int(*re.findall('^[\+\-]?\d+', s.lstrip())), 2**31 - 1), -2**31)		# 因爲findall返回的是一個列表,並且其中只有一個元素,是可迭代對象,所以可以解包,另外就是做大小值判斷了

"""
^:匹配字符串開頭
[\+\-]:代表一個+字符或-字符
?:前面一個字符可有可無
\d:一個數字
+:前面一個字符的一個或多個
\D:一個非數字字符
*:前面一個字符的0個或多個
"""

如果不用正則,應該是下面這種方案:

class Solution(object):
    def myAtoi(self, str):
        """
        :type str: str
        :rtype: int
        """
        #去掉左邊字符
        str=str.lstrip()
        #如果字符串空,返回
        if len(str)==0:
            return 0
        #設置默認輸出爲0
        last=0
        #如果有符號設置起始位置2,其餘的爲1
        i=2 if str[0]=='-'or str[0]=='+'  else 1
        #循環,直到無法強轉成int,跳出循環
        while i <= len(str):
            try:
                last=int(str[:i])
                i+=1
            except:
                break
        #如果數字超出範圍,返回範圍最大值
        if last<-2147483648 :
            return -2147483648
        if last>2147483647:
            return 2147483647
        return last

2019/9/26:兩數相加與字符串相乘

題目鏈接:https://leetcode-cn.com/problems/add-strings/

題目中意思可以理解爲要我們重新模擬一下兩數相加和兩數相乘的步驟,首先來看兩數相加,我們可以考慮用雙指針的解法對其進行解答:

class Solution(object):
    def addStrings(self, num1, num2):
        """
        :type num1: str
        :type num2: str
        :rtype: str
        """
        i,j,carry = len(num1) - 1,len(num2) - 1,0
        res = ""
        while i >= 0 and j >= 0:
            n1 = int(num1[i]) if i >= 0 else 0  # 從末尾開始取並進行補0操作,如果num1的前面位數小於num2,那麼將None替換成0
            n2 = int(num2[j]) if j >= 0 else 0
            tmp = n1 + n2 + carry
            print(tmp)
            carry = tmp // 10
            res = str(tmp % 10) + res
            i , j = i - 1,j - 1
        return "1" + res if carry else res

然後關於兩數相乘,不太清楚什麼是BigInteger,感覺好像只有下面這種滿足了題意,但有點複雜,所以以後回過頭來複習的時候再看吧。
Python 字符串暴力模擬豎式乘法計算過程

2019/9/26:反轉字符串

題目鏈接:https://leetcode-cn.com/problems/reverse-string/comments/

因爲看到標題是雙指針了,所以這題應該就是考雙指針概念,很容易就寫出代碼:

class Solution(object):
    def reverseString(self, s):
        """
        :type s: List[str]
        :rtype: None Do not return anything, modify s in-place instead.
        """
        prev,cur = 0,len(s) - 1
        while prev < cur:
            s[prev],s[cur] = s[cur],s[prev]
            prev,cur = prev + 1,cur - 1
            if prev >= cur:
                return s
            else:
                continue

2019/9/26:反轉字符串中的單詞 III

題目鏈接:https://leetcode-cn.com/problems/reverse-words-in-a-string-iii/

題目很簡單,直接寫出代碼爲:

class Solution(object):
    def reverseWords(self, s):
        """
        :type s: str
        :rtype: str
        """
        c = a.split()
        for i in range(len(c)):
            c[i] = c[i][::-1]
        s = " ".join(c)
        return s

""" return " ".join([i[::-1] for i in a.split()]) """

2019/9/26:最長公共前綴

題目鏈接:https://leetcode-cn.com/problems/longest-common-prefix/

拿到數組中最長的字符串和最短的字符串,遍歷最短的字符串防止索引超出界限,然後比照有多少相同的前綴:

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,x in enumerate(s1):
            if x != s2[i]:
                return s2[:i]
        return s1

方案二是通過python的內置函數去取數,利用python的zip函數,把str看成list然後把輸入看成二維數組,左對齊縱向壓縮,然後把每項利用集合去重,之後遍歷list中找到元素長度大於1之前的就是公共前綴:

class Solution(object):
    def longestCommonPrefix(self, strs):
        """
        :type strs: List[str]
        :rtype: str
        """
        if not strs: return ""
        ss = list(map(set, zip(*strs)))
        res = ""
        for i, x in enumerate(ss):
            x = list(x)
            if len(x) > 1:
                break
            res = res + x[0]
        return res

2019/9/27:最大子序和

題目鏈接:https://leetcode-cn.com/problems/maximum-subarray/

這題有兩種方式,第一種是動態規劃,因爲有很確的求一個最大值的和,另一種就是分治法。

那麼動態規劃可以這樣寫:

class Solution(object):
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        for i in range(1, len(nums)):
            # 當前索引i永遠存儲0~i的最大和
            nums[i] = max(nums[i], nums[i] + nums[i - 1])
        # 返回每個索引最大和的最大值
        return max(nums)

分治法爲:

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        n = len(nums)
        #遞歸終止條件
        if n == 1:
            return nums[0]
        else:
            #遞歸計算左半邊最大子序和
            max_left = self.maxSubArray(nums[0:len(nums) // 2])
            #遞歸計算右半邊最大子序和
            max_right = self.maxSubArray(nums[len(nums) // 2:len(nums)])
        
        #計算中間的最大子序和,從右到左計算左邊的最大子序和,從左到右計算右邊的最大子序和,再相加
        max_l = nums[len(nums) // 2 - 1]
        tmp = 0
        for i in range(len(nums) // 2 - 1, -1, -1):
            tmp += nums[i]
            max_l = max(tmp, max_l)
        max_r = nums[len(nums) // 2]
        tmp = 0
        for i in range(len(nums) // 2, len(nums)):
            tmp += nums[i]
            max_r = max(tmp, max_r)
        #返回三個中的最大值
        return max(max_right,max_left,max_l+max_r)

2019/9/27:格雷編碼

題目鏈接:https://leetcode-cn.com/problems/gray-code/

class Solution:
    def grayCode(self, n: int) -> List[int]:
        if n==0:
            return [0]

        res=[]
        def back(now,x):
            if len(now)==n:
                res.append(int(now,2))
            elif x==0:
                back(now+'0',0)
                back(now+'1',1)
            else:
                back(now+'1',0)
                back(now+'0',1)
        
        back('',0)
        return res

2019/9/27:全排列

題目鏈接:https://leetcode-cn.com/problems/permutations/

這題開始想到兩種方式,第一種就是python中有一個排列模塊,和前面子集類似,然後很快就可以想到這種方式,代碼爲:

from itertools import permutations

class Solution(object):
    def permute(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        n = len(nums)
        res = []
        for i in permutations(nums,n):
            res.append(i)
        return res

第二種就是按照題目需求,自己寫一個回朔算法了:

class Solution:
    # 利用“回溯法”找到所有排列。
    # 回溯法的重點1:利用全局變量記錄狀態。
    # 回溯法的重點2:利用循環+條件判斷,判斷是否進行下一步探索(回溯)。
    def search(self, nums, res, result):
        # 利用兩個全局變量,res用於記錄每次回溯的結果狀態,result用於記錄最後
        # 完全滿足條件的res。
        if len(res) == len(nums):
            result.append(res.copy())
        else:
            # 利用for循環去探索可能情況
            for i in range(len(nums)):
                # 篩選符合條件的
                if nums[i] not in res:
                    # 用res記錄下這次回溯的結果
                    res.append(nums[i])
                    # 將nums,res,result往下回溯
                    self.search(nums, res, result)
                    # 一定記住在程序的出口,也就是下次探索之前,一定要將本次的狀態記錄刪除
                    # 因爲,res是在回溯之間的全局變量,下次可能性探索之前沒有將本次的記錄
                    # 的記錄刪除,那麼下次探索就會包含本次探索的結果,會造成嚴重的錯誤。
                    res.pop()
                    
    def permute(self, nums: List[int]) -> List[List[int]]:
        result = []
        res = []
        self.search(nums, res, result)
        return result
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章