链表
创建链表
class ListNode:
def __init__(self, val, next = None):
self.val = val
self.next = next
# [1, 2, 3] => 1->2->3
def gen_list(nums):
if not nums:
return None
head = ListNode(nums[0])
pre = head
for i in range(1, len(nums)):
node = ListNode(nums[i])
pre.next = node
pre = node
return node
反转链表
链表的通用解法,先存、后断
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
pre = None
cur = head
while cur:
nextnode = cur.next
cur.next = pre
pre = cur
cur = nextnode
return pre
合并两个有序链表
# 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):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
per = ListNode(0)
cur = pre
while l1 and l2:
if le.val <= l2.val:
cur.next = l1
l1 = l1.next
else:
cur.next = l2
l2 = l2.next
cur = cur.next
cur.next = l1 or l2
return pre.next
相交链表
编写一个程序,找到两个单链表相交的起始节点。
如下面的两个链表
思想:两个指针,分别从头开始遍历,两个链表,找到值相等,切后续节点都相等的点。但问题是两个链表长度不一样。所以有一下步骤
1、求两个链表长度插值idff
2、较长的链表先走diff 步
3、两个链表一起移动,找到交点(只需找到整个node 完全相等的点)
# 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
"""
if headA is None or headB is None:
return None
# 计算长度
len1 = 0
cura = headA
while cura:
len1 += 1
cura = cura.next
len2 = 0
curb = headB
while curB:
len2 += 1
curb = curb.next
diff = abs(len1 - len2)
if len1 > len2:
for _ in range(diff):
headA = headA.next
else:
for _ in range(diff):
headB = headB.next
while headA and headB:
if headA == headB:
return headA
headA = headA.next
headB = headB.next
return None
环形链表
给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/linked-list-cycle
思想1:快慢指针,指针 i 每次移动1, 指针 j 每次移动2。若无环,指针2 会先一步None。若有环,指针2则会和指针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 head.next == None:
return False
i, j = head, head
while j:
if j.next:
j = j.next.next
i = i.next
if i == j:
return True
else:
return False
两数相加
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/add-two-numbers
思想1:只需考虑两种异常情况。第一种。l1 ,l2 长度不一样,第二种l1 , l2 之间发生了进位。
那么可以将两个链表中的值取出,放到数组里,然后对数组进行按位相加。
这里用了https://leetcode-cn.com/problems/add-two-numbers/solution/zui-zhi-bai-de-xie-fa-by-meng-zhi-hen-n-2/这里的想法。用s存储每一个节点相加的结果,通过取余和 取整 来实现进为操作。
# 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:
head = ListNode(None)
num1 = []
s = 0
while l1 or l2 or s:
s += (l1.val if l1 else 0) + (l2.val if l2 else 0)
num1.append(s % 10)
s //= 10
l1 = l1.next if l1 else None
l2 = l2.next if l2 else None
head = ListNode(num1[0])
pre = head
for i in range(1, len(num1)):
node = ListNode(num1[i])
pre.next = node
pre = node
return head
思想2:同上,只不过直接将l1 l2 的val相加,存到新的链表中。同样用梦之痕大佬的进位思想。
class Solution(object):
def addTwoNumbers(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
head = ListNode(None)
pre = head
s = 0
while l1 or l2 or s:
s += (l1.val if l1 else 0) + (l2.val if l2 else 0)
pre.next = ListNode(s % 10)
pre = pre.next
s //= 10
l1 = l1.next if l1 else None
l2 = l2.next if l2 else None
return head.next