赞
踩
提示:本篇共7道力扣题目供大家食用,时间自行把控~
1、本篇是算法刷题系列文章的第 2
篇,写此系列的目的是为了让自己对题目的理解更加深刻。
2、本系列博客主要参考了卡哥的 代码随想录博客 以及 卡哥本人B站讲解的视频 代码随想录B站视频 ,强烈推荐给大家,因为本人学习中 Python为主
,因此博客主要由 Python
代码呈现给大家,需要其他语言的版本,卡哥博客链接自取。
链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成
,一个是 数据域
一个是 指针域
(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。
链表在内存中不是连续分布的。
head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点 。dummy_head
,使得删除头节点和其他节点的规则一致。class Solution:
def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
# 设置虚拟头节点
dummy_head = ListNode(next=head)
curNode = dummy_head
while(curNode.next!=None):
if(curNode.next.val == val):
# 找到后,删除cur.next节点
curNode.next = curNode.next.next
else:
# 没找到,更新curNode
curNode = curNode.next
return dummy_head.next
get(index)
获取链表中第index
个节点的值;addAtHead(val)
在链表的第一个元素之前添加一个值为val
的节点;addAtTail(val)
将值为val
的节点追加到链表的最后一个元素;addAtIndex(index,val)
在链表中的第index
个节点之前添加值为val
的节点;deleteAtIndex(index)
如果索引index
有效,则删除链表中的第index
个节点。
单链表:
class Node: def __init__(self, val): self.val = val self.next = None class MyLinkedList: def __init__(self): self._head = Node(0) self._count = 0 def get(self, index: int) -> int: if 0 <= index <self._count: temp = self._head for i in range(index + 1): temp = temp.next return temp.val else: return -1 def addAtHead(self, val: int) -> None: self.addAtIndex(0, val) def addAtTail(self, val: int) -> None: self.addAtIndex(self._count, val) def addAtIndex(self, index: int, val: int) -> None: if index < 0: index =0 elif index > self._count: return add_node = Node(val) curNode = self._head while index: curNode = curNode.next index -= 1 else: add_node.next, curNode.next = curNode.next, add_node # 计数累加 self._count += 1 def deleteAtIndex(self, index: int) -> None: if 0 <= index < self._count: curNode = self._head while index: curNode = curNode.next index -= 1 curNode.next = curNode.next.next self._count -= 1
双链表: 相对于单链表,Node
新增了prev
属性
class Node: def __init__(self, val): self.val = val self.prev = None self.next = None class MyLinkedList: def __init__(self): # 虚拟节点 self._head, self._tail = Node(0), Node(0) self._head.next, self._tail.prev = self._tail, 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: Node, next: Node, val: int) -> None: # 计数累加 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) # 计数-1 self._count -= 1 node.prev.next, node.next.prev = node.next, node.prev
head
,请你反转链表,并返回反转后的链表。prev
和 cur
,prev=None
(空指针),cur=head
(指向头节点);temp=cur.next
保存 cur
后面的节点,pre、cur
向后移动;2
步,直到 cur=None
时结束,完成链表翻转;prev
,即新链表的头节点。法一:双指针
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
cur = head
pre = None
while(cur!=None):
# 保存一下 cur 的下一个节点
temp = cur.next
cur.next = pre #反转
#更新pre、cur指针
pre = cur
cur = temp
return pre
法二:递归
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
def reverse(prev, cur):
if not cur:
return prev;
temp = cur.next
# 翻转操作
cur.next = prev
# 下一轮反转操作
return reverse(cur, temp)
return reverse(None, head)
整个节点
去做交换操作。具体交换见图解。class Solution: def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]: dummy_head = ListNode(next=head) prev = dummy_head # 交换 while prev.next and prev.next.next: cur = prev.next post = prev.next.next # prev,cur,post对应最左,中间的,最右边的节点 cur.next = post.next post.next = cur prev.next = post prev = prev.next.next return dummy_head.next
n
个结点,并且返回链表的头结点。fast指针
和 slow指针
,初始值为虚拟头结点;fast
首先走 n + 1
步 ,为什么是 n+1
呢,因为只有这样同时移动的时候 slow
才能指向删除节点的上一个节点(方便做删除操作);fast
和 slow
同时移动,直到 fast
指向末尾,删除 slow
指向的下一个节点。class Solution: def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]: dummy_head = ListNode() dummy_head.next = head # 第 1 步:初始化 slow, fast = dummy_head, dummy_head # 第 2 步: fast先往前走n步 while(n!=0): fast = fast.next n -= 1 # 第 3 步: fast 走到结尾后,slow 的下一个节点为倒数第N个节点 while(fast.next!=None): slow = slow.next fast = fast.next # 删除节点 slow.next = slow.next.next return dummy_head.next
headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null
。快慢法则
,走的快的一定会追上走得慢的。在这道题里,有的链表短,他走完了就去走另一条链表,我们可以理解为走的快的指针。那么,只要其中一个链表走完了,就去走另一条链表的路。如果有交点,他们最终一定会在同一个位置相遇。class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
if headA is None or headB is None:
return None
cur_a, cur_b = headA, headB # 用两个指针代替a和b
while cur_a != cur_b:
# 如果a走完了,那么就切换到b走
cur_a = cur_a.next if cur_a else headB
# 同理,b走完了就切换到a
cur_b = cur_b.next if cur_b else headA
return cur_a
head
,返回链表开始 入环的第一个节点
。 如果链表无环,则返回 null
。如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0
开始)。如果 pos
是 -1
,则在该链表中没有环。注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。 不允许修改链表。class Solution: def detectCycle(self, head: ListNode) -> ListNode: slow, fast = head, head while fast and fast.next: slow = slow.next fast = fast.next.next # 如果相遇 if slow == fast: p = head q = slow while p!=q: p = p.next q = q.next return p return None
链表篇到这里就结束了,若文章中有表述不当的地方还望大家多多指出,哈希表篇见吧。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。