美文网首页
Python小白 Leetcode刷题历程 No.16-N

Python小白 Leetcode刷题历程 No.16-N

作者: _LanXiu | 来源:发表于2020-01-31 00:15 被阅读0次

Python小白 Leetcode刷题历程 No.16-No.20 最接近的三数之和、Phone Number的字母组合、四数之和、删除链表的倒数第N个节点、有效的括号

写在前面:

作为一个计算机院的大学生,总觉得仅仅在学校粗略的学习计算机专业课是不够的,尤其是假期大量的空档期,作为一个小白,实习也莫得路子,又不想白白耗费时间。于是选择了Leetcode这个平台来刷题库。编程我只学过基础的C语言,现在在自学Python,所以用Python3.8刷题库。现在我Python掌握的还不是很熟练,算法什么的也还没学,就先不考虑算法上的优化了,单纯以解题为目的,复杂程度什么的以后有时间再优化。计划顺序五个题写一篇日志,希望其他初学编程的人起到一些帮助,写算是对自己学习历程的一个见证了吧。

有一起刷LeetCode的可以关注我一下,我会一直发LeetCode题库Python3解法的,也可以一起探讨。

觉得有用的话可以点赞关注下哦,谢谢大家!
········································································································································································
题解框架:

    1.题目,难度
    2.题干,题目描述
    3.题解代码(Python3(不是Python,是Python3))
    4.或许有用的知识点(不一定有)
    5.解题思路
    6.优解代码及分析(当我发现有比我写的好很多的代码和思路我就会写在这里)

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

No.16.最接近的三数之和

难度:中等
题目描述:


在这里插入图片描述

题解代码(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

或许有用的知识点:
abs(x)=x的绝对值。

解题思路:
第十五题‘No.15.三数之和’思路类似,从一个数组中确定三个数,可以先for循环确定一个数,再用双指针法确定后两个数,然后判断,根据判断结果移动指针直到不满足L<R。

No.17.电话号码的字母组合

难度:中等
题目描述:


在这里插入图片描述

题解代码(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

或许有用的知识点:
回溯算法,在树形结构中找全部的解,通常使用回溯算法。

解题思路:
对与“23”我们不难推断出它的解为下图:


在这里插入图片描述

这显然是在树形结构求树叶的全部解,在树形结构中找全部的解,通常使用回溯算法。
先写出这个题的字典,phone={‘数字(key)’:‘对应字母(value)’},然后定义回溯函数运算即可,当剩余数字长度为0,结束循环,否则,for遍历这个数字的所有字母值,在每个循环中再次进行回溯函数。

No.18.四数之和

难度:中等
题目描述:


在这里插入图片描述

题解代码(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:                                      #最小数>target/4,跳出循环
                break
            if i>0 and nums[i]==nums[i-1]:                             #最小数与上一轮循环相同,防止重复解,跳过
                continue
            for j in range(l)[::-1]:
                if nums[j]<(target/4)-1:                                      #最大数<target/4,跳出循环
                    break
                if j<l-1 and nums[j]==nums[j+1]:                             #最大数与上一轮循环相同,防止重复解,跳过
                    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]:          #左指针向右跳过重复值,防止重复解 
                            L +=1
                        while L<R and nums[R]==nums[R-1]:          #右指针向左跳过重复值,防止重复解 
                            R -=1
                        L +=1
                        R -=1
                    elif nums[i]+nums[L]+nums[R]+nums[j] > target:              #四数和>0,右指针大了,左移
                        R -=1
                    else:                                          #四数和<0,左指针小了,右移
                        L +=1   
        return res

解题思路:
这题跟例题第十五题‘No.15.三数之和’基本一致,只不过多了个数,我们可以确定一个最大数和一个最小数,中间两数用双指针。这道题我代码中的标注很详细,解题思路和15题基本一致。

No.19.删除链表的倒数第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

或许有用的知识点:
当处理链表且需要考虑空链表时,我们或许可以设置一个哑结点,即dummy.next = head。快慢指针思想(见‘优解代码及分析’)。

解题思路:
这个题要求删除链表的倒数第 n 个节点,并且返回链表的头结点。为了避免空链表的特殊情况,我们要设置一个哑节点。因为链表是单向的,我们首先要知道链表的总长度i,再将第i-1-n个节点直向下下个节点即可,最后我们返回哑节点的下个节点即为原链表的头节点。

优解代码及分析:
优解代码(Python3.8)

class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        # 增加一个哑节点方便边界判断
        dummy = ListNode(0)
        dummy.next,a,b = head,dummy,dummy
        # 第一个循环,b指针先往前走n步
        while n>0 and b:
            b,n = b.next,n-1
        # 假设整个链表长l<n,那么第一次遍历完后b=NULL,于是后面的判断就不用继续了,直接返回
        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指针也跟着走,当b=NULL时遍历结束,a指针就指向要删除的节点的前一个位置
        while b.next:
            a,b = a.next,b.next
        # 删除节点并返回   
        a.next = a.next.next
        return dummy.next

分析:
使用了快慢指针思想,只用了一次遍历就找到了倒数第n个节点。如需快慢指针的具体内容和其他用途可以查看本题‘或许有用的知识点’中的链接。

No.20.有效的括号

难度:简单
题目描述:


在这里插入图片描述

题解代码(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==['?']

或许有用的知识点:
temp=list.pop(),是弹出list中最后一个元素,并储存到temp中,list.pop()就是直接弹出最后一个元素。
解决括号配对这类二元就近配对的问题,可以运用栈的思想。

解题思路:设‘(’类的为开括号,‘)’类的为闭括号,设置一个字典dic={‘闭括号(key)’:’开括号(value)’}。用for循环遍历字符串中每一个字符,如果这个字符是开括号(不是dic的key),就把它写入list中,如果这个字符是闭括号,就弹出list中最后一个字符,判断与该字符对应字符是否相等,不相等则False。为了防止开括号数量小造成闭括号匹配出错的情况,我们应先给list赋一个初值,最后返回判断list是否与初值相同的布尔值。

相关文章

网友评论

      本文标题:Python小白 Leetcode刷题历程 No.16-N

      本文链接:https://www.haomeiwen.com/subject/uwwwthtx.html