- 会做不代表熟练
- 这道题我遇到过好几次。
(1)第一次是B站的语音算法工程师岗(2023年5月校招面试一面),写出来了;
(2)第二次是360的自然语言处理工程师岗(2023年6月2日校招一面,没写出来)
其实第一次写出来的时候是比较卡的,因为我好久没有笔试了,但是思路可能比较顺畅,知道怎么处理细节;写完也就没管了,哪知道后面又遇到了这题,所以还是得熟练。
1.题目
题目还行,但是需要注意的地方有很多,首先需要思路清楚。在思路清楚的基础上再注意细节。
2.分析
分成几个部分来做,分别是:
- step1.先split 链表
- step2.再翻转链表,
- step3.再交叉合并链表。
在第三步中,需要注意尾节点的一个处理。如下图所示:
当我们已经合并得到1->4
时,后面的2 与 3,需要尾节点串联起来,那么这个串联部分的代码怎么写?主要是想清楚才好写!
3.代码
本文提供两个版本的代码:
代码一:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reorderList(self, head: ListNode) -> None:
"""
Do not return anything, modify head in-place instead.
"""
# step1.先split 链表
# step2. 翻转链表
# step3. merge 链表
head1,head2 = self.splitLink(head)
head2 = self.reverseLink(head2)
start = self.mergeLink(head1,head2)
return start
def splitLink(self,head):
slow = fast = head
while(fast.next and fast.next.next):
slow = slow.next
fast = fast.next.next
tmp = slow.next
slow.next = None
# 返回两个链表的头节点
return head,tmp
# 翻转链表
def reverseLink(self,head):
pre = None
while(head):
nx = head.next
head.next = pre
pre = head
head = nx
return pre
# 交叉匹配即可
def mergeLink(self,head1,head2):
cur,head = head1 ,head1
head1 = head1.next # 往后
cur.next = None # 初始化
cnt = 0
while(head1 and head2):
if cnt% 2 == 0: # 接head2
cur.next = head2
head2 = head2.next
cur = cur.next
cur.next = None
else: # 接head1
cur.next = head1
head1 = head1.next
cur = cur.next
cur.next = None
cnt += 1
if head1:
cur.next = head1
if head2:
cur.next = head2
return head
代码一应该是没有代码二好懂的,代码二如下:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reorderList(self, head: ListNode) -> None:
"""
Do not return anything, modify head in-place instead.
"""
if head is None or head.next is None:
return head
# step1. 得到链表的中点
slow = fast = head
while(fast and fast.next and fast.next.next):
fast = fast.next.next
slow = slow.next
# 得到第二个链表的头结点
h2 = slow.next
slow.next = None # 置为空
# step2. 将链表翻转
pre = None
while(h2):
tmp = h2.next
h2.next = pre
pre = h2
h2 = tmp
# 得到第二个链表的头
h2 = pre
# print(h2.val)
# while(h2):
# print(h2.val)
# h2 = h2.next
# step3. 拼接两个链表
h1 = res = head # 最后返回的结果
tail = None # 表示合并得到链表的尾节点
while(h1 and h2):
tmp1 = h1.next
tmp2 = h2.next
h1.next = h2
if cur is None:
tail = h2
else:
tail.next = h1
tail = h2 # 更新尾节点
# 更新节点
h1 = tmp1
h2 = tmp2
if h1:
tail.next = h1
return res