6. LeetCode 203. 移除链表元素
给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点 。
示例 1:
输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]
示例 2:
输入:head = [], val = 1
输出:[]
示例 3:
输入:head = [7,7,7,7], val = 7
输出:[]
提示:
- 列表中的节点数目在范围
[0, 104]
内 1 <= Node.val <= 50
0 <= val <= 50
解法:
-
构造头结点,因为每个链表节点都是一个对象,浅拷贝的占用同一个内存地址。
class ListNode: def __init__(self, val): self.val = val self.next = None def remove_elements(head: Optional[ListNode], val: int) -> Optional[ListNode]: dummy_node = ListNode(0) dummy_node.next = head cur = dummy_node while cur.next: if cur.next.val == val: cur.next = cur.next.next else: cur = cur.next return dummy_node.next
测试用例:
-
def base_test_case() -> ListNode: node1 = ListNode(1) node2 = ListNode(2) node3 = ListNode(3) node4 = ListNode(4) node5 = ListNode(5) node6 = ListNode(6) node1.next = node2 node2.next = node3 node3.next = node4 node4.next = node5 node5.next = node6 return node1 if __name__ == '__main__': test_object = remove_elements(base_test_case(), 6) print(test_object)
7. LeetCode 707. 设计链表
设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val
和 next
。val
是当前节点的值,next
是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev
以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。
在链表类中实现这些功能:
- get(index):获取链表中第
index
个节点的值。如果索引无效,则返回-1
。 - addAtHead(val):在链表的第一个元素之前添加一个值为
val
的节点。插入后,新节点将成为链表的第一个节点。 - addAtTail(val):将值为
val
的节点追加到链表的最后一个元素。 - addAtIndex(index,val):在链表中的第
index
个节点之前添加值为val
的节点。如果index
等于链表的长度,则该节点将附加到链表的末尾。如果index
大于链表长度,则不会插入节点。如果index
小于0
,则在头部插入节点。 - deleteAtIndex(index):如果索引
index
有效,则删除链表中的第index
个节点。
示例:
MyLinkedList linkedList = new MyLinkedList();
linkedList.addAtHead(1);
linkedList.addAtTail(3);
linkedList.addAtIndex(1,2); //链表变为1-> 2-> 3
linkedList.get(1); //返回2
linkedList.deleteAtIndex(1); //现在链表是1-> 3
linkedList.get(1); //返回3
提示:
-
0 <= index, val <= 1000
-
请不要使用内置的 LinkedList 库。
-
get
,addAtHead
,addAtTail
,addAtIndex
和deleteAtIndex
的操作次数不超过2000
。 -
class MyLinkedList: def __init__(self): pass def get(self, index: int) -> int: pass def addAtHead(self, val: int) -> None: pass def addAtTail(self, val: int) -> None: pass def addAtIndex(self, index: int, val: int) -> None: pass def deleteAtIndex(self, index: int) -> None: pass
解法:
-
- 对于初始化属性,需要考虑链表的节点个数
- 对于头部和尾部添加:都可以采用插入的方法(头部和尾部的索引已知)
- 添加和删除链表节点的时候,要对链表节点个数进行相应的加减
class MyLinkedList: """ 设计链表的实现。 """ def __init__(self): self.dummy_node = ListNode(0) self.count = 0 def get(self, index: int) -> int: """get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。""" if index >= self.count or index < 0: return -1 else: cur = self.dummy_node for _ in range(index + 1): cur = cur.next return cur.val def addAtHead(self, val: int) -> None: """在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。""" self.addAtIndex(0, val) def addAtTail(self, val: int) -> None: """值为 val 的节点追加到链表的最后一个元素。""" self.addAtIndex(self.count, val) def addAtIndex(self, index: int, val: int) -> None: """ 在链表中的第 index 个节点之前添加值为 val 的节点。 如果 index 等于链表的长度,则该节点将附加到链表的末尾。 如果 index 大于链表长度,则不会插入节点。如果 index 小于 0,则在头部插入节点。 """ if index < 0: index = 0 elif index > self.count: return self.count += 1 add_node = ListNode(val) pre = None cur = self.dummy_node for _ in range(index + 1): pre = cur cur = cur.next pre.next = add_node add_node.next = cur def deleteAtIndex(self, index: int) -> None: """如果索引 index 有效,则删除链表中的第 index 个节点。""" if 0 <= index < self.count: self.count -= 1 pre = None cur = self.dummy_node for _ in range(index + 1): pre = cur cur = cur.next pre.next = cur.next cur.next = None
测试用例:
my_linked_list = MyLinkedList()
my_linked_list.dummy_node.next = base_test_case()
my_linked_list.count = 6
result_val = my_linked_list.get(6)
print(result_val)
my_linked_list.addAtHead(4)
my_linked_list.addAtTail(10)
result_add = my_linked_list.dummy_node.next
print(result_add)
my_linked_list.deleteAtIndex(5)
result_del = my_linked_list.dummy_node.next
print(result_del)
8. 206. 反转链表
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
示例 1:
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
示例 2:
输入:head = [1,2]
输出:[2,1]
示例3:
输入:head = []
输出:[]
提示:
- 链表中节点的数目范围是
[0, 5000]
-5000 <= Node.val <= 5000
解法:
-
双指针法
def reverseList(head: Optional[ListNode]) -> Optional[ListNode]: pre = None # 左指针 cur = head # 右指针 while cur: tmp = cur.next # 第一个节点的next赋值为tmp(后面的一串节点) cur.next = pre # pre赋值为第一个节点的next(此时pre为None,反转后的尾节点的next为None) pre = cur # 移动右指针 cur = tmp # 移动左指针 return pre
-
测试用例:
node1 = ListNode(1) node2 = ListNode(2) node3 = ListNode(3) node4 = ListNode(4) node5 = ListNode(5) node6 = ListNode(6) node1.next = node2 node2.next = node3 node3.next = node4 node4.next = node5 node5.next = node6 reverse_list(node1)