注意: 链表问题伴随着大量指针操作。面试时不要急着写代码,仔细分析设计不容易出错。 由于链表是不连续存储的。当调节节点i的next指针时,需要(这里用tmp)来保存后节点的位置 常见错误: ① 输入链表头指针为null(特殊输入测试)或只有一个节点(一个功能测试)时,程序崩溃 ②反转链表出现断裂 ③返回的头节点不是原始链表的尾节点 解决方法: 提前想好测试用例,心中默默运行代码进行单元测试,再交给面试官
双指针循环解法**
# # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: # 返回ListNode def ReverseList(self, pHead): if not pHead or not pHead.next:# 判断特殊情况,链表为空或者只有一个node return pHead pre = None cur = pHead next = pHead.next while cur:# 注意这个地方是cur,还是cur.next,心中跑完代码再写 tmp = cur.next cur.next = pre pre = cur cur = tmp return pre递归方法 递归方法我总是是是而非的,没有用一个时间段来用递归方法做题
class Solution: # 返回ListNode def ReverseList(self, pHead): if not pHead or not pHead.next: return pHead pNew = self.ReverseList(pHead.next) pHead.next.next = pHead pHead.next = None return pNew思路: hashmap可以解决不是面试官想要的思路,暴力时间复杂度O(MN) 双指针 第二种双指针好好看看!!! 创建两个指针p1和p2,分别指向两个链表的头结点,然后依次往后遍历。如果某个指针到达末尾,则将该指针指向另一个链表的头结点;如果两个指针所指的节点相同,则循环结束,返回当前指针指向的节点。比如两个链表分别为:1->3->4->5->6和2->7->8->9->5->6。短链表的指针p1会先到达尾部,然后重新指向长链表头部,当长链表的指针p2到达尾部时,重新指向短链表头部,此时p1在长链表中已经多走了k步(k为两个链表的长度差值),p1和p2位于同一起跑线,往后遍历找到相同节点即可。其实该方法主要就是用链表循环的方式替代了长链表指针先走k步这一步骤
class Solution:# 傻逼双指针 def FindFirstCommonNode(self, pHead1, pHead2): if not pHead1 or not pHead1.next or not pHead2 or not pHead2.next: return None length1 = 1 length2 = 1 tmp = 0 cur1 = pHead1 cur2 = pHead2 while cur1: cur1 = cur1.next length1 += 1 while cur2: cur2 = cur2.next length2 += 1 if length1 > length2: while tmp < length1 - length2: pHead1 = pHead1.next tmp += 1 if length1 <= length2: while tmp < length2 - length1: pHead2 = pHead2.next tmp += 1 while pHead1: if pHead1.val == pHead2.val and pHead1.next == pHead2.next: return pHead1 else: pHead1 = pHead1.next pHead2 = pHead2.next return None ```python# 巧妙精简化的双指针 # -*- coding:utf-8 -*- # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: def FindFirstCommonNode(self, pHead1, pHead2): if not pHead1 or not pHead1.next or not pHead2 or not pHead2.next: return None p1 = pHead1 p2 = pHead2 while p1 != p2: p1 = p1.next if p1 else pHead2 p2 = p2.next if p2 else pHead1 return p1hashmap
# -*- coding:utf-8 -*- # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: def EntryNodeOfLoop(self, pHead): li = []# 刚开始我用的list命名:不能与关键词重合! p = pHead if not p or not p.next: return None while pHead: if pHead in li:# 列表查找O(N),所以这里换成dict 或者 set # if pHead in dict: # return pHead # else: # dict[pHead] = 1 # pHead = pHead.next #return pHead else: li.append(pHead)# 是将pHead这个节点存到li中,而不是仅仅将pHead.val这个元素 pHead = pHead.next return None class Solution:# 用set def EntryNodeOfLoop(self, pHead): s = set([]) while pHead: if pHead in s: return pHead else: s.add(pHead) pHead = pHead.next return None快慢指针 思路:slow每次走一步,fast每次走两步 ① 判断是否有环:如果slow追上fast(相遇)有环 ② 找入口:让slow从相遇点出发,新指针从pHead出发,每次走一步,相遇即是入口(证明自己找找)
class Solution: def EntryNodeOfLoop(self, pHead): slow,fast = pHead,pHead while fast and fast.next: slow = slow.next fast = fast.next.next if slow == fast: slow2 = pHead while slow != slow2:# 新指针从pHead出大 slow = slow.next slow2 = slow2.next return slow return None双指针 注意! tmp = ListNode(0) return pHead.next
# -*- coding:utf-8 -*- # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: # 返回合并后列表 def Merge(self, pHead1, pHead2): tmp = ListNode(0) pHead = tmp while pHead1 and pHead2:# 注意 if pHead1.val < pHead2.val: tmp.next = pHead1 pHead1 = pHead1.next else: tmp.next = pHead2 pHead2 = pHead2.next tmp = tmp.next if not pHead1: tmp.next = pHead2 if not pHead2: tmp.next = pHead1 return pHead.next注意: ① 链表头节点为空指针 ② 链表节点数小于k ③ k=0
# Definition for singly-linked list. # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: def kthToLast(self, head: ListNode, k: int) -> int: if not head or k < 0: return None a = head b = head for i in range(k): if not b: return None b = b.next while b: a = a.next b = b.next return a.val