2.两数相加
19.删除链表的倒数第N个节点
21.合并两个有序链表
23. 合并K个排序链表
92. 反转链表 II
138. 复制带随机指针的链表
141. 环形链表
143. 重排链表
148. 排序链表
160. 相交链表
206. 反转链表
237. 删除链表中的节点
234. 回文链表
328. 奇偶链表
426. 将二叉搜索树转化为排序的双向链表
445. 两数相加 II
2.两数相加
题目描述:给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
代码:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
if not l1:return l2
if not l2:return l1
tmp=ListNode(0)
res=tmp
flag=0
while l1 or l2:
tmpsum=0
if l1:
tmpsum+=l1.val
l1=l1.next
if l2:
tmpsum+=l2.val
l2=l2.next
tmpres=(tmpsum+flag)%10
res.next=ListNode(tmpres)
flag=(tmpsum+flag)//10
res=res.next
if flag:
res.next=ListNode(1)
res=tmp.next
return res
19.删除链表的倒数第N个节点
题目描述:给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
进阶:
你能尝试使用一趟扫描实现吗?
两遍扫描:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
m=0
p=head
q=head
while p:
m+=1
p=p.next
if m==1 and n==1:
head=None
elif m==n:
head=head.next
else:
for i in range(1,m-n):
q=q.next
if n==1:
q.next=None
else:
q.next=q.next.next
return head
进阶(一遍扫描):
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
L=[]
count=0
while head:
L.append(head)
count+=1
head=head.next
if count==1:return None
if L[-n].next==None:
L[-n-1].next=None
return L[0]
else:
L[-n].val=L[-n].next.val
L[-n].next=L[-n].next.next
return L[0]
21.合并两个有序链表
题目描述:将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
代码:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
if not l1:return l2
if not l2:return l1
if l1.val<=l2.val:
res=l1
res.next=self.mergeTwoLists(l1.next,l2)
else:
res=l2
res.next=self.mergeTwoLists(l1,l2.next)
return res
迭代解法:
# 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 not l1:return l2
if not l2:return l1
tmp=ListNode(0)
res=tmp
while l1 and l2:
if l1.val<=l2.val:
tmp.next=l1
l1=l1.next
else:
tmp.next=l2
l2=l2.next
tmp=tmp.next
if l1:
tmp.next=l1
if l2:
tmp.next=l2
return res.next
23.合并K个排序链表
题目描述:合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
代码:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
L=[]
res=tmp=ListNode(0)
for l in lists:
while l:
L.append(l.val)
l=l.next
for x in sorted(L):
tmp.next=ListNode(x)
tmp=tmp.next
return res.next
141.环形链表
题目描述:给定一个链表,判断链表中是否有环。为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
代码:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
if not head or not head.next:
return False
fast=head
slow=head
while fast and fast.next:
fast=fast.next.next
slow=slow.next
if fast==slow:
return True
return False
148. 排序链表
题目描述:在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
代码:
这里的空间复杂度不是常数级的,常数级的解法后面在排序模块中列出
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def sortList(self, head: ListNode) -> ListNode:
if not head:return None
new=ListNode(0)
res=new
L=[]
while head:
L.append(head.val)
head=head.next
L.sort()
while L:
new.next=ListNode(L.pop(0))
new=new.next
return res.next
234. 回文链表
题目描述:请判断一个链表是否为回文链表。
思路:快慢指针找中点,然后翻转后半部分链表,判断前后是否一致,时间复杂度O(N),空间复杂度O(1).
代码:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def isPalindrome(self, head):
"""
:type head: ListNode
:rtype: bool
"""
if not head or not head.next:return True
fast,slow=head,head
while fast and fast.next:
fast=fast.next.next
slow=slow.next
cur=slow
pre=None
while cur:
nex=cur.next
cur.next=pre
pre=cur
cur=nex
while pre and head:
if pre.val!=head.val:
return False
pre=pre.next
head=head.next
return True
206. 反转链表
题目描述:反转一个单链表。
代码:
感动哭了,这道题当初去刷剑指的时候怎刷都不会,复习了一下数据结构,终于可以独立写出来了,菜鸡感极而泣o(╥﹏╥)o
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head or not head.next:return head
pre=head
cur=head.next
while cur:
nex=cur.next
cur.next=pre
pre=cur
cur=nex
head.next=None
return pre
138. 复制带随机指针的链表
题目描述:给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。
要求返回这个链表的深拷贝。
思路:这道题剑指里面也有,还是不会,太惨了, 都得重新刷一遍,为什么我这么菜o(╥﹏╥)o
代码:
"""
# Definition for a Node.
class Node(object):
def __init__(self, val, next, random):
self.val = val
self.next = next
self.random = random
"""
class Solution(object):
def copyRandomList(self, head):
"""
:type head: Node
:rtype: Node
"""
if not head:return None
clone=head
while clone:
node=Node(clone.val,None,None)
node.next=clone.next
clone.next=node
clone=node.next
clone=head
while clone:
node=clone.next
if clone.random:
node.random=clone.random.next
clone=node.next
clone=head
new=head.next
while clone.next:
node=clone.next
clone.next=node.next
clone=node
return new
92. 反转链表 II
题目描述:反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
代码:
哭了,这道题我花了一个多小时debug,结果还是看答案才会了,自己有想法,可是一直有bug,基础太菜,哭唧唧。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def reverseBetween(self, head, m, n):
"""
:type head: ListNode
:type m: int
:type n: int
:rtype: ListNode
"""
if not head:return
new=ListNode(-1)
new.next=head
pre=new
for _ in range(m-1):
pre=pre.next
start=pre.next
tail=start.next
for _ in range(n-m):
start.next=tail.next
tail.next=pre.next
pre.next=tail
tail=start.next
return new.next
237. 删除链表中的节点
题目描述:请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。
现有一个链表 – head = [4,5,1,9],它可以表示为:
思路:将当前节点的值和指针都修改为下一个节点的值和指针即可,相当于让当前节点冒充下一个节点,那么原来的当前节点被修改消除,原来节点的下一位节点因为没有被指针连接而失去意义
代码:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def deleteNode(self, node):
"""
:type node: ListNode
:rtype: void Do not return anything, modify node in-place instead.
"""
node.val,node.next=node.next.val,node.next.next
328. 奇偶链表
题目描述:给定一个单链表,把所有的奇数节点和偶数节点分别排在一起。请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性。请尝试使用原地算法完成。你的算法的空间复杂度应为 O(1),时间复杂度应为 O(nodes),nodes 为节点总数。
思路:
代码:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def oddEvenList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head:return head
odd=head
even=head.next
evenHead=even
while even and even.next:
odd.next=even.next
odd=odd.next
even.next=odd.next
even=even.next
odd.next=evenHead
return head
-
时间复杂度: O(n)O(n) 。总共有 nn 个节点,我们每个遍历一次。
-
空间复杂度: O(1)O(1) 。我们只需要 4 个指针。
160. 相交链表
题目描述:编写一个程序,找到两个单链表相交的起始节点。
如下面的两个链表:
代码:
# 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):
"""
:type head1, head1: ListNode
:rtype: ListNode
"""
ha,hb=headA,headB
while ha!=hb:
if ha:
ha=ha.next
else:
ha=headB
if hb:
hb=hb.next
else:
hb=headA
return ha
426. 将二叉搜索树转化为排序的双向链表
题目描述:将一个二叉搜索树就地转化为一个已排序的双向循环链表。可以将左右孩子指针作为双向循环链表的前驱和后继指针。
为了让您更好地理解问题,以下面的二叉搜索树为例:
我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。
下图展示了上面的二叉搜索树转化成的链表。“head” 表示指向链表中有最小元素的节点。
特别地,我们希望可以就地完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中的第一个节点的指针。
下图显示了转化后的二叉搜索树,实线表示后继关系,虚线表示前驱关系。
代码:
"""
# Definition for a Node.
class Node:
def __init__(self, val, left, right):
self.val = val
self.left = left
self.right = right
"""
class Solution:
def treeToDoublyList(self, root: 'Node') -> 'Node':
def helper(node):
nonlocal last, first
if node:
helper(node.left)
if last:
last.right = node
node.left = last
else:
first = node
last = node
helper(node.right)
if not root:
return None
first, last = None, None
helper(root)
last.right = first
first.left = last
return first
445. 两数相加 II
题目描述:给定两个非空链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储单个数字。将这两数相加会返回一个新的链表。
你可以假设除了数字 0 之外,这两个数字都不会以零开头。
进阶:
如果输入链表不能修改该如何处理?换句话说,你不能对列表中的节点进行翻转。
代码:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
if not l1:return l2
if not l2:return l1
def helper(root):
T=root
pre=root
cur=pre.next
while cur:
nex=cur.next
cur.next=pre
pre=cur
cur=nex
T.next=None
return pre
l1=helper(l1)
l2=helper(l2)
flag=0
new=ListNode(-1)
new_head=new
while l1 or l2:
cur_sum=0
if l1:
cur_sum+=l1.val
l1=l1.next
if l2:
cur_sum+=l2.val
l2=l2.next
cur_val=(cur_sum+flag)%10
flag=(cur_sum+flag)//10
new.next=ListNode(cur_val)
new=new.next
if flag:
new.next=ListNode(flag)
return helper(new_head.next)
143. 重排链表
题目描述:给定一个单链表 L:L0→L1→…→Ln-1→Ln ,将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→…
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
代码:
在这里插入代码片
24. 两两交换链表中的节点
题目描述:给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例:
给定 1->2->3->4, 你应该返回 2->1->4->3.
代码:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def swapPairs(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
dummy = ListNode(-1)
dummy.next, curr = head, dummy
while curr.next and curr.next.next:
first, second = curr.next, curr.next.next
# swap two nodes
first.next, second.next, curr.next = second.next, first, second
# update to next iteration
curr = curr.next.next
return dummy.next
25.K个一组翻转链表
题目描述:给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
说明 :
你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
代码:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
dummy = ListNode(0)
dummy.next = head
pre = dummy
tail = dummy
while True:
count = k
while count and tail:
count -= 1
tail = tail.next
if not tail: break
head = pre.next
while pre.next != tail:
cur = pre.next # 获取下一个元素
# pre与cur.next连接起来,此时cur(孤单)掉了出来
pre.next = cur.next
cur.next = tail.next # 和剩余的链表连接起来
tail.next = cur #插在tail后面
# 改变 pre tail 的值
pre = head
tail = head
return dummy.next
61.旋转链表
题目描述:给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。
代码:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def rotateRight(self, head: ListNode, k: int) -> ListNode:
if not head or not head.next:return head
n=1
old_tail=head
while old_tail.next:
old_tail=old_tail.next
n+=1
old_tail.next=head #先生成一个环
new_tail=head
for i in range(n-k%n-1):
new_tail=new_tail.next
new_head=new_tail.next
new_tail.next=None
return new_head
82. 删除排序链表中的重复元素 II
题目描述:给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现的数字。
代码:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def deleteDuplicates(self, head: ListNode) -> ListNode:
if not head:return None
if head.next and head.next.val==head.val:
while head.next and head.next.val==head.val:
head=head.next
return self.deleteDuplicates(head.next)
else:
head.next=self.deleteDuplicates(head.next)
return head
83.删除排序链表中的重复元素
题目描述:给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。
示例 1:
输入: 1->1->2
输出: 1->2
示例 2:
输入: 1->1->2->3->3
输出: 1->2->3
代码:
# 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
"""
if not head:return None
p=head
while p and p.next:
while p and p.next and p.val==p.next.val:
p.next=p.next.next
p=p.next
return head
86.分隔链表
题目描述:给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。
你应当保留两个分区中每个节点的初始相对位置。
代码:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def partition(self, head: ListNode, x: int) -> ListNode:
if not head or not head.next:return head
before=before_head=ListNode(0)
after=after_head=ListNode(-1)
while head:
if head.val<x:
before.next=ListNode(head.val)
before=before.next
else:
after.next=ListNode(head.val)
after=after.next
head=head.next
before.next=after_head.next
after.next=None
return before_head.next
92. 反转链表 II
题目描述:反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
代码:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:
if not head:return None
stack=[]
new=ListNode(0)
res=new
while head:
stack.append(head.val)
head=head.next
stack[m-1:n]=reversed(stack[m-1:n])
while stack:
new.next=ListNode(stack.pop(0))
new=new.next
return res.next
142.环形链表 Ⅱ
题目描述:给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
代码:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head or not head.next or not head.next.next:
return None
slow=head.next
fast=head.next.next
while fast and fast.next and fast!=slow:
fast=fast.next.next
slow=slow.next
if fast==slow:
fast=head
while fast!=slow:
fast=fast.next
slow=slow.next
return fast
return None