题目一:给你一个单链表的头节点 head
,请你判断该链表是否为回文链表。如果是,返回 true
;否则,返回 false
。
方法1:可以创建一个数组,将链表中的值放到数组中,在数组中判断非常简单,将数组反转后看是否相等即可,笔试的时候可以用,代码简单,但空间复杂度为O(N)。
class Solution(object):
def isPalindrome(self, head):
# 创建一个数组
vals = []
cur = head
# 将链表中的值放到数组中
while cur is not None:
vals.append(cur.val)
cur = cur.next
# 判断取反是否相等
return vals == vals[::-1]
方法2:使用快慢指针,不新建任何空间,空间复杂度为O(1),面试可以用。
class Solution(object):
def isPalindrome(self, head):
if head is None:
return True
# 先用快慢指针的方法,找到前半部分的尾结点
first_half_end = self.end_of_first_half(head)
# 反转后半部分的链表
second_half_start = self.reverse_list(first_half_end.next)
# 依次比较看是否相等,遍历到底都相等的话则为回文结构
result = True
first_position = head
second_position = second_half_start
while result and second_position is not None:
if first_position.val != second_position.val:
result = False
first_position = first_position.next
second_position = second_position.next
# 还原链表并返回结果
first_half_end.next = self.reverse_list(second_half_start)
return result
def end_of_first_half(self, head):
fast = head
slow = head
# 快指针走俩步,慢指针走一步,走完慢指针刚好到达前半部分的尾节点
while fast.next is not None and fast.next.next is not None:
fast = fast.next.next
slow = slow.next
return slow
def reverse_list(self, head):
tmp = None
cur = head
# 反转链表
while cur is not None:
next_node = cur.next
cur.next = tmp
tmp = cur
cur = next_node
return tmp
题目二:给定值pivot,将链表划分为小于,等于,大于pivot的形式。
方法1:1、同理我们可以创建一个数组,将链表中的值放到数组中。
2、然后用双指针的方法,将数组划分为小于,等于,大于pivot的形式。
3、最后将数组元素串成链表返回即可。
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
def partition(head, pivot):
vals = []
cur = head
# 遍历链表,将值都放入数组中
while cur is not None:
vals.append(cur.val)
cur = cur.next
# 对数组进行快速排序,使用双指针的方法
left, right = 0, len(vals)-1
i = 0
while left < right:
if vals[i] < pivot:
vals[i],vals[left] = vals[left],vals[i]
left+=1
i+=1
elif vals[i] > pivot:
vals[i],vals[right] = vals[right],vals[i]
right-=1
else:
i+=1
# 将数组元素串成链表
new_head = ListNode(vals[0])
current = new_head
for i in vals[1:]:
current.next = ListNode(i)
current = current.next
return new_head
# 此函数为了输出结果好看
def print_linked_list(head):
current = head
while current:
print(current.val, end=" -> ")
current = current.next
print("None")
if __name__ == "__main__":
# 创建一个样本链表
head = ListNode(3)
head.next = ListNode(6)
head.next.next = ListNode(2)
head.next.next.next = ListNode(8)
head.next.next.next.next = ListNode(5)
head.next.next.next.next.next = ListNode(9)
pivot = 5
print("初始链表:")
print_linked_list(head)
new_head = partition(head, pivot)
print(f"链表按 {pivot} 化为为左边小,中间相等,右边大的形式:")
print_linked_list(new_head)
方法2:由于方法1创建了新的额外数组,空间复杂度大,所以可以使用方法2,空间复杂都为O(1),只需创建6个变量,sh,st为小于部分的头和尾,eh,et为等于部分的头和尾,bh和bt为大于部分的头和尾。
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
# 方法1 空间复杂度O(1) 不创建额外空间
def partition(head, pivot):
# 创建6个变量,小于区域,等于区域,大于区域
sh, st = None, None # 小于部分头尾
eh, et = None, None # 等于部分头尾
bh, bt = None, None # 大于部分头尾
while head:
sign = head
head = head.next # 保留下一节点
sign.next = None # 分离出当前节点,不然可能会出现循环链表
if sign.val < pivot:
# 当区域为空时,头尾结点都赋予该值
if not sh:
sh = sign
st = sign
else:
st.next = sign
st = sign
elif sign.val == pivot:
if not eh:
eh = sign
et = sign
else:
et.next = sign
et = sign
else:
if not bh:
bh = sign
bt = sign
else:
bt.next = sign
bt = sign
# 划分完后将它们串起来,充分讨论所有情况
if st: # 有小于部分
head = sh
if eh: # 且有等于部分
st.next = eh
if bh: # 且有大于部分
et.next = bh
elif bh: # 无等于部分但有大于部分
st.next = bh
elif et: # 无小于部分有等于部分
head = head if head else eh
if bh: # 且有大于部分
et.next = bh
return head if head else bh # 无小于部分也无等于部分
# 此函数为了输出结果好看
def print_linked_list(head):
current = head
while current:
print(current.val, end=" -> ")
current = current.next
print("None")
if __name__ == "__main__":
# 创建一个样本链表
head = ListNode(3)
head.next = ListNode(6)
head.next.next = ListNode(2)
head.next.next.next = ListNode(8)
head.next.next.next.next = ListNode(5)
head.next.next.next.next.next = ListNode(9)
pivot = 5
print("初始链表:")
print_linked_list(head)
new_head2 = partition(head, pivot)
print(f"链表按 {pivot} 化为为左边小,中间相等,右边大的形式:")
print_linked_list(new_head)
题目三:复制含有随即指针节点的链表,并返回新的链表。
可以使用哈希表(字典)的方法。
class Node:
def __init__(self, val, next=None, random=None):
self.val = val
self.next = next
self.random = random
# 使用哈希表的方法(字典)
def copyRandomList(head):
if not head:
return None
# 使用哈希表来建立旧链表结点和新链表结点的映射
mapping = {}
cur = head
# 第一次扫描旧链表,创建新节点并将其添加到哈希表中
while cur:
mapping[cur] = Node(cur.val)
cur = cur.next
cur = head
# 第二次扫描,连接新链表的next和random指针
while cur:
if cur.next:
mapping[cur].next = mapping[cur.next]
if cur.random:
mapping[cur].random = mapping[cur.random]
cur = cur.next
# 返回新链表
return mapping[head]
if __name__ == "__main__":
# 创建一个示例链表
A = Node(1)
B = Node(2)
C = Node(3)
A.next = B
B.next = C
A.random = C
B.random = A
# 复制链表
new_head = copyRandomList(A)
# 打印新链表的值和随机指针的值
curr = new_head
while curr:
print("Value:", curr.val)
if curr.random:
print("Random:", curr.random.val)
else:
print("Random: None")
curr = curr.next