1. 创建链表,2.合并链表,3.删除链表中的元素,4.翻转链表中的一段位置的元素
# 链表节点
class ListNode(object):
def __init__(self,val=0,next=None):
self.val=val
self.next=next
# 链表操作
class SinglyLinkedList(object):
# 创建链表
def create(self,list):
lenth=len(list)
if lenth==0:
return None
head=ListNode(list[0],None)
tail=head
for i in range(lenth-1):
node=ListNode(list[i+1],None)
tail.next=node
tail=node
return head
# 浏览链表
def scan(self,linkedlist):
tail=linkedlist
list=[]
while(tail):
list.append(tail.val)
tail=tail.next
return list
2.1 将两个链表合并为一个升序链表(LeetCode 例21.)
# 链表合并
class Solution(object):
def mergeTwoLists(self, l1, l2):
if not l1 and not l2:
return l1
elif not l1 and l2:
return l2
elif l1 and not l2:
return l1
tail1=l1
tail2=l2
if tail1.val<tail2.val:
head=tail1
tail1=tail1.next
head.next=None
else:
head=tail2
tail2=tail2.next
head.next=None
tail=head
while(tail1 and tail2):
if tail1.val<tail2.val:
tail.next=tail1
tail1=tail1.next
tail=tail.next
tail.next=None
else:
tail.next=tail2
tail2=tail2.next
tail=tail.next
tail.next=None
if tail1:
tail.next=tail1
elif tail2:
tail.next=tail2
return head
2.2 合并k个升序链表
class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
if not lists:
return None
head1=lists.pop(0)
while lists:
# 每两个链表进行一次合并
head2=lists.pop(0)
if not head2: # 若head2为空,如[[],[]]
continue
elif not head1: # 若head1为空,head2不为空,如[[],[1]]
head1=head2
continue
# head1和head2都不为空
if head1.val>head2.val:
head1,head2=head2,head1 # 让head1指向头结点值较小的链表
head=head1 # head指向合并后链表的头结点
tail=head # 主链表的滑动指针
head1=head1.next
tail.next=None
# 链表合并
while head1 and head2:
if head1.val<=head2.val:
tail.next=head1
tail=head1
head1=head1.next
tail.next=None
else:
tail.next=head2
tail=head2
head2=head2.next
tail.next=None
# 将没合并完的链表合并到链表head中
if head1:
tail.next=head1
if head2:
tail.next=head2
# 将合并后的链表作为head1继续进行合并
head1=head
return head1
3. 删除链表中重复的元素(LeetCode 例82.)
输入:head = [1,2,3,3,4,4,5]
输出:[1,2,5]
输入:head = [1,1,1,2,3]
输出:[2,3]
解析:
class Solution(object):
def deleteDuplicates(self, head):
v=ListNode()
v.next=head # 虚拟指针防止开头部分重复导致head节点删除
p=v
q=p.next
flag=0
while(q and q.next): # q:链表是否是空链表 q.next:是否是链表最后一个元素
if p.next.val==q.next.val:
q=q.next
flag=1
else:
if flag==0:
p=p.next
q=p.next
else:
p.next=q.next
q.next=None
q=p.next
flag=0
if p.next!=q: # 链表结尾处重复
p.next=None
return v.next
3. 删除链表倒数第n个元素,并返回头结点(一次扫描实现)
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
输入:head = [1], n = 1
输出:[]
# 一趟扫描实现 (比较费内存)
class Solution(object):
def removeNthFromEnd(self, head, n):
listNode=[]
tail=head
# list中每个元素指向链表节点中的每个元素
while(tail):
listNode.append(tail)
tail=tail.next
num=len(listNode)
if num==1: # 如果链表只有一个元素
return None
if num==n: # 如果删除链表表头
head=listNode[0].next
listNode[0].next=None
return head
listNode[num-n-1].next=listNode[num-n].next
listNode[num-n].next=None
return head
4.1 链表逆置
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
if not head or not head.next: # 如果链表为空,或者只有一个节点
return head
p=head.next
head.next=None
while p:
q=p.next
p.next=head
head=p
p=q
return head
4.2 翻转链表中指定位置的元素 (leetcode 例92.)
输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]
# 设置一个虚拟指针
class Solution(object):
def reverseBetween(self, head, left, right):
v=ListNode() # 设置一个虚拟指针
v.next=head
num=1
while(num<left):
num+=1
v=v.next
p=v.next
q=p
while(left!=right):
right -= 1
r=q.next
q.next=r.next
r.next=p
v.next=r
p=r
if left==1: # 如果从第一个元素开始,则逆置后head指针已经改变位置
return v.next
else:
return head
5. 链表位置的奇偶重排序 (原链表中奇数位置全放放前边,偶数位置都放后边。注意元素个数为奇数个和偶数个的判断条件是不同的)
class Solution:
def oddEvenList(self , head: ListNode) -> ListNode:
# write code here
if not head or not head.next:
return head
head1=head # 奇数链表头节点
head2=head.next # 偶数链表头节点
tail1=head1
tail2=head2
while tail1 and tail2:
if not tail2.next: # 链表元素有偶数个的时候,tail1已经指向了奇数链表的最后一个节点
tail1.next=head2 # 奇数链表的尾部与偶数链表头部相连
break
else:
tail1.next=tail2.next
tail1=tail1.next
if not tail1.next: # 链表元素有奇数个,tail1已经指向奇数链表的尾部,但是tail2还没有指向偶数链表的尾部
tail2.next=tail1.next # 先让tail2.next=None
tail1.next=head2 # 奇数链表与偶数链表相连
break
else:
tail2.next=tail1.next
tail2=tail2.next
return head