文章目录
1、找出两个链表的交点
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def getIntersectionNode(self, headA, headB):
p1, p2 = headA, headB
while p1 != p2:
p1 = headB if p1 == None else p1.next
p2 = headA if p2 == None else p2.next
return p1
2、链表反转
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution(object):
def reverseList(self, head):
pre = None
cur = head
while cur != None:
nextp = cur.next
cur.next = pre
pre = cur
cur = nextp
return pre
3、归并两个有序链表
方法一:迭代
每次找两个链表中较小的值加入新的链表,直到有一个链表遍历结束,未结束的那个链表,将剩余的部分连到新链表的尾部。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution(object):
def mergeTwoLists(self, l1, l2):
if not l1:
return l2
if not l2:
return l1
p1, p2 = l1, l2
head = tail = ListNode(0)
while p1 and p2:
if p1.val < p2.val:
tail.next = p1
p1 = p1.next
else:
tail.next = p2
p2 = p2.next
tail = tail.next
if p1:
tail.next = p1
if p2:
tail.next = p2
return head.next
方法二:递归
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution(object):
def mergeTwoLists(self, l1, l2):
if not l1: return l2
if not l2: 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
4、从有序链表中删除重复结点
方法:一次遍历
思路1:重复元素为一组,每组重复元素中只取第一个元素,cur 为当前组第一个,找下一组的第一个元素nex,另cur.next = nex
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution(object):
def deleteDuplicates(self, head):
if not head or not head.next:
return head
cur, nex = head, head.next
while cur:
while nex and cur.val == nex.val:
nex = nex.next
cur.next = nex
cur = nex
return head
思路2:每次只看下一个节点,如果当前 cur 与 cur.next 对应的元素相同,那么就将 cur.next 从链表中移除;否则说明链表中已经不存在其它与 cur 元素相同的节点,将 cur 向后移动一位
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution(object):
def deleteDuplicates(self, head):
if not head or not head.next:
return head
cur = head
while cur.next:
if cur.val == cur.next.val:
cur.next = cur.next.next
else:
cur = cur.next
return head
5、删除链表中倒数第 n 个结点
19. 删除链表的倒数第 N 个结点(Medium)
问题分析:
两个指针 fast,slow,先让 fast 走 n 步,让后二者一起走,直到 fast->next==NULL,此时 slow 指向倒数第 n+1个结点。
注意:如果 fast 先走 n 步后,发现 fast->next==NULL,表示删除头节点。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution(object):
def removeNthFromEnd(self, head, n):
slow, fast = head, head
for _ in range(n):
fast = fast.next
if not fast: # 删除的是第一个节点
return head.next
while fast.next:
fast = fast.next
slow = slow.next
slow.next = slow.next.next
return head
6、交换链表中相邻的结点
24. 两两交换链表中的节点(Medium)
方法一:递归
如果链表为空或者只有一个节点,直接返回
否则递归,递归过程如下:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def swapPairs(self, head):
if head == None or head.next == None:
return head
node = head.next
head.next = self.swapPairs(node.next)
node.next = head
return node
时间复杂度:O(N),N 指的是链表的节点数量。
空间复杂度:O(N),递归过程使用的堆栈空间。
方法二:迭代
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def swapPairs(self, head):
front = ListNode(-1)
pre_node = front
pre_node.next = head
while head and head.next:
first_node = head
second_node = head.next
# 交换两个节点
pre_node.next = second_node
first_node.next = second_node.next
second_node.next = first_node
# 改变head和pre_node指向,为下一轮交换做准备
head = first_node.next
pre_node = first_node
return front.next
时间复杂度:O(N),N 为链表的节点数量
空间复杂度:O(1)
7、两链表的和
方法1:翻转两链表,这样保证链表右端对齐,再相加。注意:这里相加之和大于 10 需要向该节点的前一结点进位。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next =
class Solution(object):
def addTwoNumbers(self, l1, l2):
def reverse_list(head):
pre = None
cur = head
while cur:
nex = cur.next
cur.next = pre
pre = cur
cur = nex
return pre
l1 = reverse_list(l1)
l2 = reverse_list(l2)
cur_val = 0
newhead = ListNode(-1)
tail = newhead
while l1 and l2:
cur_val += l1.val + l2.val
l1 = l1.next
l2 = l2.next
p = ListNode(cur_val % 10)
tail.next = p
tail = p
cur_val = cur_val / 10
while l1:
cur_val += l1.val
l1 = l1.next
p = ListNode(cur_val % 10)
tail.next = p
tail = p
cur_val = cur_val / 10
while l2:
cur_val += l2.val
l2 = l2.next
p = ListNode(cur_val % 10)
tail.next = p
tail = p
cur_val = cur_val / 10
while cur_val:
p = ListNode(cur_val % 10)
tail.next = p
tail = p
cur_val = cur_val / 10
p.next = None
return reverse_list(newhead.next)
方法2:使用栈,把所有数字压入栈中,再依次取出相加。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
s1, s2 = [], []
while l1:
s1.append(l1.val)
l1 = l1.next
while l2:
s2.append(l2.val)
l2 = l2.next
carry = 0
ans = None
while s1 or s2 or carry:
val1 = s1.pop() if s1 else 0
val2 = s2.pop() if s2 else 0
sum = val1 + val2 + carry
curnode = ListNode(sum%10)
carry = sum//10
curnode.next = ans
ans = curnode
return ans
8、回文链表
问题分析:
将链表的前一半反转,判断前一半与后一半是否相等,如:
1 -> 2 -> 2 -> 1 -> NULL 拆分为 NULL <- 1 <- 2 与 2 -> 1 -> NULL
1 -> 2 -> 1 -> NULL 拆分为 NULL <- 1 与 1 -> NULL
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution(object):
def isPalindrome(self, head):
len = 0
p = head
while p:
len += 1
p = p.next
odd = len % 2
pre = None
cur = head
for _ in range(len//2): #前一半反转
nex = cur.next
cur.next = pre
pre = cur
cur = nex
p1, p2 = pre, cur
if odd: #如果链表个数为奇数,中间一个数不比较
p2 = p2.next
while p1:
if p1.val != p2.val:
return False
p1 = p1.next
p2 = p2.next
return True
9、分隔链表
解题思路:根据总长度和分成多少段,可以求出短链表的长度(长度除以段数),长链表的个数(长度处于段数,取余),将原链表直接分割。这里需要注意,可能较长链表分割完之后,链表已经没有节点,短链表长度为0,直接返回即可。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def splitListToParts(self, head: ListNode, k: int) -> List[ListNode]:
len = 0
cur = head
while cur:
len += 1
cur = cur.next
business, remainder= len // k, len % k
res = [None] * k
for i in range(k):
if not head:
break
part_len = business + 1 if i < remainder else business
res[i] = head
for _ in range(part_len-1):
head = head.next
nex = head.next
head.next = None
head = nex
return res
10、链表元素按奇偶聚集
给一个链表,将奇数下表的元素连成链表,后面连接偶数下表的元素组成的链表。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def oddEvenList(self, head: ListNode) -> ListNode:
if not head or not head.next:
return head
odd, even = head, head.next
evenhead = even
while even and even.next:
odd.next = even.next
odd = even.next
even.next = odd.next
even = odd.next
# print_list(head)
# print_list(evenhead)
odd.next = evenhead
return head
11、分区链表
86. 分隔链表(Medium)
方法一(推荐方法):
维护两个链表,small_head 保存值小于 x 的节点,large_head 保存大于等于 x 的节点,遍历链表构建两链表后,将large_head 链表尾节点指向 large_head 链表的头节点。\
# 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:
small_head = small_tail = ListNode()
big_head = big_tail = ListNode()
cur = head
while cur:
if cur.val < x:
small_tail.next = cur
small_tail = cur
else:
big_tail.next = cur
big_tail = cur
cur = cur.next
big_tail.next = None
small_tail.next = big_head.next
return small_head.next
方法二:
统计大于等于目标值的元素个数,从前向后遍历每个元素,碰见大于等于目标值的元素就将该元素放置到链表末尾。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution(object):
def partition(self, head, x):
p = head
tail = head
n = 0
while p: # 统计大于等于x的元素个数
if p.val >= x:
n += 1
tail = p
p = p.next
newhead = ListNode(-1)
newhead.next = head
pre = newhead
cur = head
sum = 0
while cur and cur.next:
nex = cur.next
if cur.val >= x: # 大于等于x的元素,挪到尾部
pre.next = nex
tail.next = cur
tail = cur
cur.next = None
cur = nex
sum += 1
if sum >= n:
break
else:
pre = cur
cur = nex
return newhead.next
"""
:type head: ListNode
:type x: int
:rtype: ListNode
"""