首页 > 编程语言 >献芹奏曝-Python面试题-算法-链表篇

献芹奏曝-Python面试题-算法-链表篇

时间:2022-09-03 15:46:04浏览次数:103  
标签:面试题 ListNode val Python self head next 链表 def

上一篇:献芹奏曝-Python面试题 

      开篇的话:本文目的是收集和归纳力扣上的算法题,希望用python语言,竭我所能做到思路最清奇、代码最简洁、方法最广泛、性能最高效,了解常见题目,找到最利于记忆的答案,更加从容的应对面试。希望广思集益,共同进步。

链表篇

  1. 237. 删除链表中的节点(难度系数✯)

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        def deleteNode(self, node):
            """
            :type node: ListNode
            :rtype: void Do not return anything, modify node in-place instead.
            """
            node.val = node.next.val
            node.next = node.next.next
    View Code

    运行结果:1:耗时超过36%。2:内存超过78% 

    知识点/技巧: 把下一位赋值给当前

  2. 19. 删除链表的倒数第 N 个结点(难度系数✯)

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution:
        def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
            # 1:通过for循环计算列表长度。TODO:可以单独封装成方法
            _len = 0
            _len_head = head
            while _len_head:
                _len += 1
                _len_head = _len_head.next
            pre = head
            # 删除头结点
            if _len-n == 0:            
                return head.next
            # 找到前一个结点 【1,2,3,4,5】 n=2
            for i in range(_len-n-1):
                pre = pre.next
            # 让前一个结点的next指向要删除结点的next
            pre.next = pre.next.next
            return head
    
    
           
    方法一

    运行结果:1:耗时超过55%。2:内存超过93% 

    知识点/技巧: 通过for循环,计算列表长度。列表长度-N找到待删除的前一个结点 

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution:
        def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
            slow = head
            fast = head
            # 快的先走n步
            for i in range(n):
                fast = fast.next
            if not fast:
                # fast 走到末尾了,表示删除首节点
                return head.next        
            while fast.next:
                fast = fast.next
                slow = slow.next
            # fast比slow快n步,最后一次fast.next条件成立,fast走到了倒数第二个结点,slow也走到了倒数N+1个结点
            slow.next = slow.next.next
            return head
            
    方法二-双指针

    运行结果:1:耗时超过93%。2:内存超过90% 

    知识点/技巧: 通过双指针,一个在前,一个在后。前的到头,后面的到达目标位置

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution:
        def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
            pos = self.length(head,n)
            if pos == n:
                return head.next
            return head
    
        def length(self, head: Optional[ListNode], n: int):
            if head is None:
                return 0
            pos = self.length(head.next,n)+1
            if pos == n+1:
                head.next = head.next.next
            return pos
            
    方法三-递归

    运行结果:1:耗时超过8%。2:内存超过93% 

    知识点/技巧:递归

  3. 206. 反转链表(难度系数✯)

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    from copy import deepcopy
    class Solution:
        def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:        
            if not head or not head.next:
                return head
            val_list = []
            # 暴力反转,先把所有的值放到列表中,再把列表中的值倒着重写组装成列表
            while head.next:
                cur_head = deepcopy(head)
                cur_head.next = None
                val_list.append(cur_head)
                head = head.next
            new_head = head
            for item in reversed(val_list):
                head.next = item
                head = head.next        
            return new_head  
    暴力反转

    运行结果:1:超时

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    from copy import deepcopy
    class Solution:
        def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:        
    
            new_head = None
            while head:
                # temp = head.next # 先获取到下一个节点,把它做head节点,从而实现不断while循环
                # head.next = new_head # 实现反转 
                # new_head = head
                # head = temp 
                head.next,new_head,head =new_head, head,head.next              
            return new_head 
    双链表求解 一行代码

    运行结果:1:耗时超过66%。2:内存超过76% 

    知识点/技巧:把原链表的结点一个个摘掉,每次摘掉的链表都让他成为新的链表的头结点,然后更新新链表

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    from copy import deepcopy
    class Solution:
        def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:        
            if not head or not head.next:
                return head
            reverse = self.reverseList(head.next)
            head.next.next = head
            head.next = None
            return reverse
    递归调用

    运行结果:1:耗时超过99.06%。2:内存超过8.89% 

    知识点/技巧:递归调用之后head.next节点就会成为reverse节点的尾结点,我们可以直接让head.next.next = head;

  4. 21. 合并两个有序链表(难度系数✯)
    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution:
        def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
            dummy = ListNode()
            move = dummy
            while list1 and list2:
                if list1.val < list2.val:
                    move.next = list1
                    list1 = list1.next
                else:
                    move.next = list2
                    list2 = list2.next
                # 每次比完,移动一位
                move = move.next   
            move.next = list1 if list1 else list2
            return dummy.next
    方法一

    运行结果:1:耗时超过42%。2:内存超过49% 

    知识点/技巧:取最小数据添加到当前节点后面

  5. 141. 环形链表 (难度系数✯)
    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        def hasCycle(self, head: Optional[ListNode]) -> bool:
            if not head:
                return False
            fast = head
            slow = head
            while fast and fast.next:
                slow = slow.next
                fast = fast.next.next
                if slow == fast:
                    return True            
            else:
                # 有尽头,所以不为环
                return False
    快慢指针

    运行结果:1:耗时超过76%。2:内存超过71% 

    知识点/技巧:慢指针针每次走一步,快指针每次走两步,如果相遇就说明有环,如果有一个为空说明没有环。类似钟表上的分针与秒针

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        def hasCycle(self, head: Optional[ListNode]) -> bool:
            i=0
            while head and head.next and i<10**4+1 :
                head = head.next
                i += 1       
            else:
                return i>10**4
    暴力破解

    运行结果:1:耗时超过31%。2:内存超过31% 

    知识点/技巧:根据题意,设置10**4为边界。

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        def hasCycle(self, head: Optional[ListNode]) -> bool:
            set_result = set()
            while head:
                if head in set_result:
                    return True
                else:
                    set_result.add(head)  
                head = head.next   
            else:
                return False
    set集合

    运行结果:1:耗时超过90%。2:内存超过80% 

    知识点/技巧:利用set集合判断,其实list也可以。 

  6.  

 

标签:面试题,ListNode,val,Python,self,head,next,链表,def
From: https://www.cnblogs.com/YK2012/p/16573028.html

相关文章

  • 【Python】路径相关
    Python自带os.path库相关函数一、判断文件/路径是否存在os.path.isfile()os.path.isdir()os.path.exists()返回值:True/False二、创建文件夹os.makedirs()impor......
  • ubuntu 多版本python并存
    在安装了最新的ubuntu22.04后,自带的python版本为python3.10,然而我需要的一个package仅支持到python3.7。因此,我需要安装python3.7。1、安装python3.7sudoaptupdatesu......
  • 第二节:编程语言与Python介绍
    一引子基于上一节所学,有了计算机硬件,再在硬件之上安装好操作系统,我们就有了一个应用程序的运行平台,我们接下来的任务就是学习如何使用某款编程语言来开发应用程序。 ......
  • Elasticsearch 面试题
    Elasticsearch面试题为什么要使用Elasticsearch?系统中的数据,随着业务的发展,时间的推移,将会非常多,而业务中往往采用模糊查询进行数据的搜索,而模糊查询会导致查询引擎......
  • Python 博客园快速备份脚本
    鉴于有些小伙伴在寻找博客园迁移到个人博客的方案,本人针对博客园实现了一个自动备份脚本,可以快速将博客园中自己的文章备份成Markdown格式的独立文件,备份后的md文件可以直......
  • [AWS] Lambda Python Get Current Account Id
    UnlikeAWS_REGIONorAWS_LAMBDA_FUNCTION_NAME,wecannotgetcurrentaccountidfromtheenvironmentvariables.Inordertotogettheaccountid,wecanuse......
  • Python教程 - 改进温度折线图
    任务介绍之前我们完成了画温度变化图,但是实现的相对简单,这次我们可以改进一下但在改进之前需要学习一下新的知识,画横线和刻度画横线pyplot.hlines()用于在图中从xmin到......
  • java实现单链表源码
    packageMyLink.MySingleLink;importjava.util.Objects;/***单链表结点类**/publicclassNode{/***数据域**/privateObjectdate;/**......
  • java实现双向链表
    package数据结构.链表.双链表;publicclassDoubleNode{privateDoubleNodeprecursor;privateintdate;privateDoubleNodenext;publicDoubleNode(i......
  • Python教程 - 画温度变化图
    任务介绍之前介绍了通过matplotlib来画折线图的基础知识,这次我们用画折线图的知识来画温度变化图温度记录文件首先,我们新建一个txt文件,输入以下内容保存,作为一段时间的......