目录
- 两数相加
- 删除链表的倒数第N个节点
- 合并两个有序链表
- 合并K个排序链表
- 两两交换链表中的节点
- K 个一组翻转链表
- 旋转链表
- 删除排序链表中的重复元素 II
- 删除排序链表中的重复元素
- 分隔链表
- 反转链表 II
- 环形链表||
- 重排链表
2. 两数相加
代码如下:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def addTwoNumbers(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
if l1 is None:
return l2
if l2 is None :
return l1
#设置暂存为,并赋值哑变量
tmp =ListNode(None) #定义一个Node节点
res=tmp #对结果赋值
flag=0
while l1 or l2:
tmp_sum=0
if l1:
tmp_sum=l1.val
l1=l1.next
if l2:
tmp_sum +=l2.val
l2=l2.next
tmp_res=((tmp_sum+flag)%10)
flag=((tmp_sum+flag)//10)
res.next=ListNode(tmp_res)
res=res.next
if flag:
res.next=ListNode(1)
res=tmp.next #指针回到头节点
del tmp
return res
19.删除链表的倒数第N个节点
代码如下:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def removeNthFromEnd(self, head, n):
"""
:type head: ListNode
:type n: int
:rtype: ListNode
"""
dummy=ListNode(0)
dummy.next=head
p1=p2=dummy
for i in range(n):
p1=p1.next
while p1.next:
p1=p1.next
p2=p2.next
p2.next=p2.next.next
return dummy.next
21. 合并两个有序链表
解题思路:递归思想
代码如下:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
if l1==None and l2==None: #基本情况
return None
if l1==None:
return l2
if l2==None:
return l1
if l1.val<=l2.val:
l1.next=self.mergeTwoLists(l1.next,l2)
return l1
else:
l2.next=self.mergeTwoLists(l1,l2.next)
return l2
非递归思想:
class Solution:
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
dummy =ListNode(-1)
res=dummy
if list1 is None and list2 is None:
return None
while list1 or list2:
if list1 is None:
res.next = list2
break
elif list2 is None:
res.next =list1
break
elif list1.val <=list2.val:
res.next = list1
list1 =list1.next
else:
res.next = list2
list2 =list2.next
res=res.next
return dummy.next
23. 合并K个排序链表
解题思路:
先将所有元素加入到一个普通的队列中,然后sort()排序。再对排列好的list串成一个列表。
代码如下:
class Solution(object):
def mergeKLists(self, lists):
"""
:type lists: List[ListNode]
:rtype: ListNode
"""
res=[]
if lists is None:
return []
for i in lists:
while i:
res.append(i.val)
i=i.next
res.sort()
l=ListNode(0)
first=l
for i in res:
l.next=ListNode(i)
l=l.next
return first.next
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
if not lists or len(lists) == 0:
return None
import heapq # 构造小顶堆
heap = []
# 首先 for 嵌套 while 就是将所有元素都取出放入堆中
for node in lists:
while node:
heapq.heappush(heap, node.val)
node = node.next
dummy = ListNode(None)
cur = dummy
# 依次将堆中的元素取出(因为是小顶堆,所以每次出来的都是目前堆中值最小的元素),然后重新构建一个列表返回
while heap:
temp_node = ListNode(heappop(heap))
cur.next = temp_node
cur = temp_node
return dummy.next
24. 两两交换链表中的节点
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def swapPairs(self, head: ListNode) -> ListNode:
dummy = ListNode(0)
dummy.next = head
temp = dummy
while temp.next and temp.next.next:
node1 = temp.next # 奇数位置
node2 = temp.next.next # 偶数位置
temp.next = node2 # 将偶数位的值赋值给奇数位
node1.next = node2.next # 奇数位的的下一个节点指向下一个技术位
node2.next = node1 # 将奇数位的值赋值给偶数位
temp = node1 # 链表指针当前奇数位,next节点为下一个奇数位
return dummy.next
25. K 个一组翻转链表
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例:
给你这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
# 翻转一个子链表,并且返回新的头与尾
# 1-2-3-4-5---6
# 链表反转,把当前节点的指针指向由原来的指向后一个节点,转变成指向前一个节点
def reverse(self, head: ListNode, tail: ListNode):
prev = tail.next # 节点6
p = head # 节点1
while prev != tail: # 节点相同的含义:指针的值相同,指针的next节点也相同
nex = p.next # 节点2
p.next = prev # 节点1指向节点6
prev = p # 移动已修改的链表头指针
p = nex #
return tail, head
def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
dummy = ListNode(0)
dummy.next = head
pre = dummy
# 前指针 pre 下一个节点nex,子链表起始指针 head
while head: # 链表主指针
tail = pre # 每次需要reverse的子链表
# 查看剩余部分长度是否大于等于 k
for i in range(k):
tail = tail.next
if not tail:
return dummy.next
nex = tail.next # 子链表后一个节点
head, tail = self.reverse(head, tail) # 反转head 和 tail 之间的子链表
# 把子链表重新接回原链表
pre.next = head # 子链表前一个节点
tail.next = nex
pre = tail
head = tail.next
return hummy.next
反转链表
def reverseList(self, head: ListNode) -> ListNode:
prev, curr = None, head
while curr is not None:
next = curr.next
curr.next = prev
prev = curr
curr = next
return prev
61. 旋转链表
解题思路:先统计链表节点的个数n,查看最终旋转节点个数k=k%n,然后将链表节点指针走到分界点的位置,分割链表,再重连接。
代码如下:
class Solution(object):
def rotateRight(self, head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
dummy = ListNode(0)
dummy.next = head
if head is None:
return None
#先数链表有几个节点
i = head
count = 1
while i.next is not None:
i = i.next
count += 1
#抛掉重复的转圈,也算一种算法优化吧
k = k%count
if (k == 0) or count == 1:
return head
#把链表头尾连起来
i.next = head
#从dummy开始运动
i = dummy
#运动到新的链表的头的上一个节点
for _ in range(count - k):
i = i.next
j = i.next
i.next = None
return j
82. 删除排序链表中的重复元素 II
给定一个排序列表,删除所有含有重复数字的节点,只保留原始链表中没有重复出现的数字。
解题思路:
1.遍历链表生成哈希表。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def deleteDuplicates(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
# 顺序表
only_list = []
# 哈希表
only_dict = {}
# 新头节点
head2 = ListNode(0)
p = head2
while head:
if head.val in only_dict:
only_dict[head.val] += 1
else:
only_list.append(head.val)
only_dict[head.val] = 1
head = head.next
for i in only_list:
if only_dict[i] == 1:
new = ListNode(i)
p.next = new
p = p.next
return head2.next
思路2:用双指针
h -> 1 -> 2 -> 3 -> 3 -> 4 -> 4 -> 5
pre cur
做法:始终要cur走在pre前面,我们通过判断cur.val == cur.next.val
判断重复元素是否存在。
h -> 1 -> 2 3 3 4 -> 4 -> 5
| |
----------------
pre cur
如果存在重复元素,pre.next==cur.next ;cur =cur.next
,如果不存在重复元素,pre=cur;cur=cur.next,
这里需要通过一个变量标记判断是否存在重复元素。
代码如下:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def deleteDuplicates(self, head: ListNode) -> ListNode:
dummy=ListNode(0)
dummy.next=head
pre=dummy
cur=head
# 双指针,修改指针+ 遍历指针
while cur:
duplicate=False # 是否存在重复元素标记
while cur.next and cur.val==cur.next.val:
cur=cur.next
duplicate=True
if duplicate:
pre.next=cur.next # 空指针对应的next节点,由节点cur节点转换到cur.next
else:
pre=cur
cur=cur.next
return dummy.next
class Solution:
def deleteDuplicates(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
head2 = ListNode(0)
p = head2
while head:
if head.next and head.next.val == head.val:
val = head.val
while head and head.val == val:
head = head.next
# 这一步是防止链表尾全部相同时,新链表尾节点的next不为空
p.next = head
else:
p.next = head
p = head
head = head.next
return head2.next
83. 删除排序链表中的重复元素
给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。
代码如下:
class Solution(object):
def deleteDuplicates(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
p=head
while p:
while p.next and p.val==p.next.val:
p.next=p.next.next
p=p.next
return head
解题思路:如果pre和cur的val值相同的话,pre.next=cur.next
,然后cur=cur.next
pre cur
0 0 1 1
代码如下:
class Solution(object):
def deleteDuplicates(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
pre = None
cur = head
while cur != None:
pre = cur
cur = cur.next
while cur != None and cur.val == pre.val:
pre.next = cur.next
cur = cur.next
return head
86. 分隔链表
给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。
你应当保留两个分区中每个节点的初始相对位置。
示例:
输入: head = 1->4->3->2->5->2, x = 3
输出: 1->2->2->4->3->5
解题思路:
构建两个新链表,小于x的放在链表1,大于或等于x的放在链表2,最后将链表1的表尾指向链表2的表头即可。
代码如下:
class Solution:
def partition(self, head, x):
"""
:type head: ListNode
:type x: int
:rtype: ListNode
"""
head1 = ListNode(0)
head2 = ListNode(0)
phead1 = head1
phead2 = head2
tmp = head
while tmp:
if tmp.val < x:
phead1.next = tmp
tmp = tmp.next
phead1 = phead1.next
phead1.next = None
else:
phead2.next = tmp
tmp = tmp.next
phead2 = phead2.next
phead2.next = None
phead1.next = head2.next
head = head1.next
return head
参数定义
left:
左指针,始终指向左边第一个大于等于x节点的前一个位置
right:
右指针,寻找右边第一个小于x的节点插到left后面
思路
left
指针从左到右找到第一个大于等于x的前一个位置
right
从大于等于x的位置遍历到第一个小于x的位置tmp
,即tmp=right.next
原地移动:right
指向tmp
的后一位,right.next=tmp.next
,tmp
节点移动到left
的下一个位置left.next=tmp
,同时left移动到tmp
,left.next=tmp
复杂度分析
时间复杂度:O(N)
空间复杂度:O(1)
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def partition(self, head: ListNode, x: int) -> ListNode:
if not head:
return
dummy=ListNode(0)
dummy.next=head
left=dummy
while left.next and left.next.val<x:
left=left.next
right=left.next
while right:
while right.next and right.next.val>=x:
right=right.next
if not right.next:
break
# 原地移动
tmp=right.next
right.next=tmp.next
tmp.next=left.next
left.next=tmp
left = tmp
return dummy.next
92. 反转链表 II
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:
if m == n:
return head
dummy = ListNode(-1)
dummy.next = head
a = dummy
for _ in range(m - 1):
a = a.next
d=a.next
for _ in range(n-m):
d = d.next
b, c = a.next, d.next
pre = b
cur = pre.next
while cur != c:
next = cur.next
cur.next = pre
pre = cur
cur = next
a.next = d
b.next = c
return dummy.next
142. 环形链表||
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def detectCycle(self, head: ListNode) -> ListNode:
fast, slow = head, head
while True:
if not (fast and fast.next):
return
fast, slow = fast.next.next, slow.next
if fast == slow:
break
fast = head
while fast != slow:
fast, slow = fast.next, slow.next
return fast
143. 重排链表
给定一个单链表 L 的头节点 head ,单链表 L 重新排列后变为:
L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …
class Solution:
def reorderList(self, head: ListNode) -> None:
if not head:
return
vec = list()
node = head
while node:
vec.append(node)
node = node.next
i, j = 0, len(vec) - 1
while i < j:
vec[i].next = vec[j]
i += 1
if i == j:
break
vec[j].next = vec[i]
j -= 1
vec[i].next = None