用虚拟头结点+precNode+curNode
class Node:
def __init__(self, val):
self.val = val
self.Next = None
class MyLinkedList:
def __init__(self):
self.head = Node(0)
self.counter = 0
def get(self, index: int) -> int:
if index < 0 or index >= self.counter:
return -1
else:
node = self.head
for i in range(index + 1):
node = node.Next
return node.val
def addAtHead(self, val: int) -> None:
self.addAtIndex(0, val)
def addAtTail(self, val: int) -> None:
self.addAtIndex(self.counter, val)
def addAtIndex(self, index: int, val: int) -> None:
if index < 0:
index = 0
elif index > self.counter:
return
self.counter += 1
pre_node = None
cur_node = self.head
add_node = Node(val)
for i in range(index + 1):
pre_node, cur_node = cur_node, cur_node.Next
else:
pre_node.Next,add_node.Next = add_node, cur_node
def deleteAtIndex(self, index: int) -> None:
if 0 <= index < self.counter:
self.counter -= 1
pre_node = None
cur_node = self.head
for i in range(index + 1):
pre_node, cur_node = cur_node, cur_node.Next
else:
pre_node.Next, cur_node.Next = cur_node.Next, None
自定义_get_node()函数与_update()函数,减少代码量,调用方便
class Node:
def __init__(self, val):
self.val = val
self.next = None
self.prev = None
class MyLinkedList:
def __init__(self):
self.head = Node(0)
self.tail = Node(0)
self.head.next = self.tail
self.tail.prev = self.head
self.count = 0
def _get_node(self, index: int) -> Node:
# 当index小于_count//2时, 使用_head查找更快, 反之_tail更快
if index >= self.count // 2:
# 使用prev往前找
node = self.tail
for _ in range(self.count - index):
node = node.prev
else:
# 使用next往后找
node = self.head
for _ in range(index + 1):
node = node.next
return node
def get(self, index: int) -> int:
if 0 <= index < self.count:
node = self._get_node(index)
return node.val
else:
return -1
def addAtHead(self, val: int) -> None:
self._update(self.head, self.head.next, val)
def addAtTail(self, val: int) -> None:
self._update(self.tail.prev, self.tail, val)
def addAtIndex(self, index: int, val: int) -> None:
if index < 0:
index = 0
elif index > self.count:
return
node = self._get_node(index)
self._update(node.prev, node, val)
def _update(self, prev, next, val):
self.count += 1
node = Node(val)
prev.next, next.prev = node, node
node.prev, node.next = prev, next
def deleteAtIndex(self, index: int) -> None:
if 0 <= index < self.count:
node = self._get_node(index)
self.count -= 1
node.prev.next, node.next.prev = node.next, node.prev
else:
return
# Your MyLinkedList object will be instantiated and called as such:
# obj = MyLinkedList()
# param_1 = obj.get(index)
# obj.addAtHead(val)
# obj.addAtTail(val)
# obj.addAtIndex(index,val)
# obj.deleteAtIndex(index)
用虚拟头结点非常方便,且逻辑清晰
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeElements(self, head: ListNode, val: int) -> ListNode:
prev = ListNode(next = head)
dummyhead = prev
cur = head
while cur != None:
if cur.val == val:
prev.next, cur = cur.next, cur.next
else:
prev, cur = prev.next, cur.next
return dummyhead.next
需要一个cur指针,一个prev指针,prev初始化为None,cur初始化为head,循环过程中还需要一个tmp指针保存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 reverseList(self, head: ListNode) -> ListNode:
pre = None
cur = head
while cur != None:
cnext = cur.next
cur.next = pre
cur, pre = cnext, cur
return pre
把节点前后位置都保存下来,加上虚拟头结点,思路会更加清晰。
一定要画图辅助理清思路
# 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:
dummyhead = ListNode(next = head)
prev = dummyhead
# 必须有pre的下一个和下下个才能交换,否则说明已经交换结束了
while prev.next != None and prev.next.next != None:
cur = prev.next #给两个指针赋值
cnext = prev.next.next
prev.next = cur.next
cur.next = cnext.next
cnext.next = cur
prev = prev.next.next
return dummyhead.next
用快慢双指针,快指针先走N步,慢指针再开始跟快指针一起走。
当快指针到尾节点的时候,慢指针则位于倒数第N个节点处。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
dummyhead = ListNode(next = head)
slow, fast = dummyhead, dummyhead
for i in range(n):
fast = fast.next
while fast.next != None:#为了方便删除,定位到的其实是要删除节点的前一个
fast = fast.next
slow = slow.next
slow.next = slow.next.next
return dummyhead.next
两个单链表相交的起始节点,即找到链表交点节点的指针。
先求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到和curB离末尾相同距离的位置。此时就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB;如果遇到curA == curB,则找到交点;否则循环退出返回空指针
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
lenA, lenB = 0, 0
curA, curB = headA, headB
#得到A,B的长度
while curA:
lenA += 1
curA = curA.next
while curB:
lenB += 1
curB = curB.next
curA = headA
curB = headB
#保证A为较长链表
if lenA < lenB:
lenA, lenB = lenB, lenA
curA, curB = curB, curA
#两链表尾部对齐
for i in range(lenA - lenB):
curA = curA.next
while curA:
if curA == curB:
return curA
curA = curA.next
curB = curB.next
return None
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
判断链表是否有环:
设定快慢指针,快指针每次走两步,慢指针每次走一步,如果快慢指针相遇了,则说明有环存在。
有环,如何找到这个环的入口:
从头结点和快慢指针相遇结点处分别出发一个指针,两个指针相遇的地方即为入口处
# 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 fast and fast.next:
fast = fast.next.next
slow = slow.next
if fast == slow:#证明有环
p = head
q = fast
while p != q:
p = p.next
q = q.next
return p
return None