Python小白 Leetcode刷題歷程 No.16-No.20 最接近的三數(shù)之和、電話號(hào)碼的字母組合、四數(shù)之和、刪除鏈表的倒數(shù)第N個(gè)節(jié)點(diǎn)、有效的括號(hào) (有題干 有代碼 有思路心得)

Python小白 Leetcode刷題歷程 No.16-No.20 最接近的三數(shù)之和、Phone Number的字母組合、四數(shù)之和、刪除鏈表的倒數(shù)第N個(gè)節(jié)點(diǎn)、有效的括號(hào)

寫在前面:

作為一個(gè)計(jì)算機(jī)院的大學(xué)生,總覺得僅僅在學(xué)校粗略的學(xué)習(xí)計(jì)算機(jī)專業(yè)課是不夠的,尤其是假期大量的空檔期,作為一個(gè)小白,實(shí)習(xí)也莫得路子,又不想白白耗費(fèi)時(shí)間。于是選擇了Leetcode這個(gè)平臺(tái)來刷題庫。編程我只學(xué)過基礎(chǔ)的C語言,現(xiàn)在在自學(xué)Python,所以用Python3.8刷題庫。現(xiàn)在我Python掌握的還不是很熟練,算法什么的也還沒學(xué),就先不考慮算法上的優(yōu)化了,單純以解題為目的,復(fù)雜程度什么的以后有時(shí)間再優(yōu)化。計(jì)劃順序五個(gè)題寫一篇日志,希望其他初學(xué)編程的人起到一些幫助,寫算是對(duì)自己學(xué)習(xí)歷程的一個(gè)見證了吧。

有一起刷LeetCode的可以關(guān)注我一下,我會(huì)一直發(fā)LeetCode題庫Python3解法的,也可以一起探討。

覺得有用的話可以點(diǎn)贊關(guān)注下哦,謝謝大家!
········································································································································································
題解框架:

    1.題目,難度
    2.題干,題目描述
    3.題解代碼(Python3(不是Python,是Python3))
    4.或許有用的知識(shí)點(diǎn)(不一定有)
    5.解題思路
    6.優(yōu)解代碼及分析(當(dāng)我發(fā)現(xiàn)有比我寫的好很多的代碼和思路我就會(huì)寫在這里)

········································································································································································

No.16.最接近的三數(shù)之和

難度:中等
題目描述:


在這里插入圖片描述

題解代碼(Python3.8)

class Solution:
    def threeSumClosest(self, nums: List[int], target: int) -> int:
        nums.sort()
        res=nums[0]+nums[1]+nums[2]
        d=abs(res-target)
        l=len(nums)
        for i in range(l-2):
            L=i+1
            R=l-1
            while L<R:
                if abs(nums[i]+nums[L]+nums[R]-target)<d:
                    res=nums[i]+nums[L]+nums[R]
                    d=abs(res-target)
                if (nums[i]+nums[L]+nums[R])==target:
                    return res 
                elif nums[i]+nums[L]+nums[R]>target:
                    R -=1
                else:
                    L +=1
        return res

或許有用的知識(shí)點(diǎn):
abs(x)=x的絕對(duì)值。

解題思路:
第十五題‘No.15.三數(shù)之和’思路類似,從一個(gè)數(shù)組中確定三個(gè)數(shù),可以先for循環(huán)確定一個(gè)數(shù),再用雙指針法確定后兩個(gè)數(shù),然后判斷,根據(jù)判斷結(jié)果移動(dòng)指針直到不滿足L<R。

No.17.電話號(hào)碼的字母組合

難度:中等
題目描述:


在這里插入圖片描述

題解代碼(Python3.8)

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        phone={'2':['a','b','c'],'3':['d','e','f'],'4':['g','h','i'],'5':['j','k','l'],
               '6':['m','n','o'],'7':['p','q','r','s'],'8':['t','u','v'],'9':['w','x','y','z']}
        def backtrack(combination,next_digits):
            if len(next_digits)==0:
                output.append(combination)
            else:
                for letter in phone[next_digits[0]]:
                    backtrack(combination+letter,next_digits[1:])
        output=[]
        if digits:
            backtrack("",digits)
        return output

或許有用的知識(shí)點(diǎn):
回溯算法,在樹形結(jié)構(gòu)中找全部的解,通常使用回溯算法。

解題思路:
對(duì)與“23”我們不難推斷出它的解為下圖:


在這里插入圖片描述

這顯然是在樹形結(jié)構(gòu)求樹葉的全部解,在樹形結(jié)構(gòu)中找全部的解,通常使用回溯算法。
先寫出這個(gè)題的字典,phone={‘?dāng)?shù)字(key)’:‘對(duì)應(yīng)字母(value)’},然后定義回溯函數(shù)運(yùn)算即可,當(dāng)剩余數(shù)字長度為0,結(jié)束循環(huán),否則,for遍歷這個(gè)數(shù)字的所有字母值,在每個(gè)循環(huán)中再次進(jìn)行回溯函數(shù)。

No.18.四數(shù)之和

難度:中等
題目描述:


在這里插入圖片描述

題解代碼(Python3.8)

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        l=len(nums)                                            #特解
        if l<4:
            return []
        res=[]
        nums.sort()                                                 
        for i in range(l-2):
            if nums[i]>(target/4)+1:                                      #最小數(shù)>target/4,跳出循環(huán)
                break
            if i>0 and nums[i]==nums[i-1]:                             #最小數(shù)與上一輪循環(huán)相同,防止重復(fù)解,跳過
                continue
            for j in range(l)[::-1]:
                if nums[j]<(target/4)-1:                                      #最大數(shù)<target/4,跳出循環(huán)
                    break
                if j<l-1 and nums[j]==nums[j+1]:                             #最大數(shù)與上一輪循環(huán)相同,防止重復(fù)解,跳過
                    continue
                L=i+1
                R=j-1
                while L<R:
                    if nums[i]+nums[L]+nums[R]+nums[j] == target:
                        res.append([nums[i],nums[L],nums[R],nums[j]])
                        while L<R and nums[L]==nums[L+1]:          #左指針向右跳過重復(fù)值,防止重復(fù)解 
                            L +=1
                        while L<R and nums[R]==nums[R-1]:          #右指針向左跳過重復(fù)值,防止重復(fù)解 
                            R -=1
                        L +=1
                        R -=1
                    elif nums[i]+nums[L]+nums[R]+nums[j] > target:              #四數(shù)和>0,右指針大了,左移
                        R -=1
                    else:                                          #四數(shù)和<0,左指針小了,右移
                        L +=1   
        return res

解題思路:
這題跟例題第十五題‘No.15.三數(shù)之和’基本一致,只不過多了個(gè)數(shù),我們可以確定一個(gè)最大數(shù)和一個(gè)最小數(shù),中間兩數(shù)用雙指針。這道題我代碼中的標(biāo)注很詳細(xì),解題思路和15題基本一致。

No.19.刪除鏈表的倒數(shù)第N個(gè)節(jié)點(diǎn)

難度:中等
題目描述:


在這里插入圖片描述

題解代碼(Python3.8)

class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        dummy=ListNode(0)
        dummy.next=head
        i=0
        p=dummy
        while p:
            p=p.next
            i+=1
        p=dummy
        j=0
        while True:
            if j==i-1-n:
                p.next=p.next.next
                return dummy.next 
            p=p.next
            j+=1

或許有用的知識(shí)點(diǎn):
當(dāng)處理鏈表且需要考慮空鏈表時(shí),我們或許可以設(shè)置一個(gè)啞結(jié)點(diǎn),即dummy.next = head??炻羔?biāo)枷耄ㄒ姟畠?yōu)解代碼及分析’)。

解題思路:
這個(gè)題要求刪除鏈表的倒數(shù)第 n 個(gè)節(jié)點(diǎn),并且返回鏈表的頭結(jié)點(diǎn)。為了避免空鏈表的特殊情況,我們要設(shè)置一個(gè)啞節(jié)點(diǎn)。因?yàn)殒湵硎菃蜗虻?,我們首先要知道鏈表的總長度i,再將第i-1-n個(gè)節(jié)點(diǎn)直向下下個(gè)節(jié)點(diǎn)即可,最后我們返回啞節(jié)點(diǎn)的下個(gè)節(jié)點(diǎn)即為原鏈表的頭節(jié)點(diǎn)。

優(yōu)解代碼及分析:
優(yōu)解代碼(Python3.8)

class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        # 增加一個(gè)啞節(jié)點(diǎn)方便邊界判斷
        dummy = ListNode(0)
        dummy.next,a,b = head,dummy,dummy
        # 第一個(gè)循環(huán),b指針先往前走n步
        while n>0 and b:
            b,n = b.next,n-1
        # 假設(shè)整個(gè)鏈表長l<n,那么第一次遍歷完后b=NULL,于是后面的判斷就不用繼續(xù)了,直接返回
        if not b:
     ![在這里插入圖片描述](https://img-blog.csdnimg.cn/20200126050737205.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xhblhpdV8=,size_16,color_FFFFFF,t_70)       return head
        # 第二次,b指針走到鏈表最后,a指針也跟著走,當(dāng)b=NULL時(shí)遍歷結(jié)束,a指針就指向要?jiǎng)h除的節(jié)點(diǎn)的前一個(gè)位置
        while b.next:
            a,b = a.next,b.next
        # 刪除節(jié)點(diǎn)并返回   
        a.next = a.next.next
        return dummy.next

分析:
使用了快慢指針?biāo)枷?,只用了一次遍歷就找到了倒數(shù)第n個(gè)節(jié)點(diǎn)。如需快慢指針的具體內(nèi)容和其他用途可以查看本題‘或許有用的知識(shí)點(diǎn)’中的鏈接。

No.20.有效的括號(hào)

難度:簡(jiǎn)單
題目描述:


在這里插入圖片描述

題解代碼(Python3.8)

class Solution:
    def isValid(self, s: str) -> bool:
        stack=['?']
        dic={')':'(','}':'{',']':'['}
        for char in s:
            if char in dic:
                top=stack.pop()
                if top != dic[char]:
                    return False
            else:
                stack.append(char)
        return  stack==['?']

或許有用的知識(shí)點(diǎn):
temp=list.pop(),是彈出list中最后一個(gè)元素,并儲(chǔ)存到temp中,list.pop()就是直接彈出最后一個(gè)元素。
解決括號(hào)配對(duì)這類二元就近配對(duì)的問題,可以運(yùn)用棧的思想。

解題思路:設(shè)‘(’類的為開括號(hào),‘)’類的為閉括號(hào),設(shè)置一個(gè)字典dic={‘閉括號(hào)(key)’:’開括號(hào)(value)’}。用for循環(huán)遍歷字符串中每一個(gè)字符,如果這個(gè)字符是開括號(hào)(不是dic的key),就把它寫入list中,如果這個(gè)字符是閉括號(hào),就彈出list中最后一個(gè)字符,判斷與該字符對(duì)應(yīng)字符是否相等,不相等則False。為了防止開括號(hào)數(shù)量小造成閉括號(hào)匹配出錯(cuò)的情況,我們應(yīng)先給list賦一個(gè)初值,最后返回判斷l(xiāng)ist是否與初值相同的布爾值。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容