目录
一、Leetcode203(移除链表元素)
题目描述
给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]
输入:head = [], val = 1
输出:[]
输入:head = [7,7,7,7], val = 7
输出:[]
题目链接:力扣题目链接
解题思路
- 删除:cur.next = cur.next.next
- 注意删除头节点比较特殊!
方法:虚拟头节点
- 删除头节点需要找到上一个元素的指针
- 虚拟头节点就是头指针的上一个元素

# 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 removeElements(self, head, val):
"""
:type head: ListNode
:type val: int
:rtype: ListNode
"""
# 虚拟头节点法
dummy_head = ListNode(next = head)
cur = dummy_head
while cur.next != None:
if cur.next.val == val:
cur.next = cur.next.next
else:
cur = cur.next
return dummy_head.next
总结
- dummy_head = ListNode(next = head)新建虚拟头节点
- 因为单链找不到上一个,删的只能是cur.next
- return的是dummy_head.next,因为头节点可能被删了
二、Leetcode707(设计链表)
题目描述
你可以选择使用单链表或者双链表,设计并实现自己的链表。
单链表中的节点应该具备两个属性:val 和 next 。val 是当前节点的值,next 是指向下一个节点的指针/引用。
如果是双向链表,则还需要属性 prev 以指示链表中的上一个节点。假设链表中的所有节点下标从 0 开始。
实现 MyLinkedList 类:
MyLinkedList() 初始化 MyLinkedList 对象。
int get(int index) 获取链表中下标为 index 的节点的值。如果下标无效,则返回 -1 。
void addAtHead(int val) 将一个值为 val 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。
void addAtTail(int val) 将一个值为 val 的节点追加到链表中作为链表的最后一个元素。
void addAtIndex(int index, int val) 将一个值为 val 的节点插入到链表中下标为 index 的节点之前。如果 index 等于链表的长度,那么该节点会被追加到链表的末尾。如果 index 比长度更大,该节点将 不会插入 到链表中。
void deleteAtIndex(int index) 如果下标有效,则删除链表中下标为 index 的节点。
输入
["MyLinkedList", "addAtHead", "addAtTail", "addAtIndex", "get", "deleteAtIndex", "get"]
[[], [1], [3], [1, 2], [1], [1], [1]]
输出
[null, null, null, null, 2, null, 3]
解释
MyLinkedList myLinkedList = new MyLinkedList();
myLinkedList.addAtHead(1);
myLinkedList.addAtTail(3);
myLinkedList.addAtIndex(1, 2); // 链表变为 1->2->3
myLinkedList.get(1); // 返回 2
myLinkedList.deleteAtIndex(1); // 现在,链表变为 1->3
myLinkedList.get(1); // 返回 3
题目链接:力扣题目链接
解题思路
- 链表基本操作
方法:链表基操
- get(self, index):判断index是否有效,index控制循环次数(检查return的值对不对,可以带入index=0,此时跳过while循环)
- addAtHead(self, val):newnode.next = self.dummy_head.next, self.dummy_head.next = newnode,链表长度+1
- addAtTail(self, val):cur.next = newnode,链表长度+1
- addAtIndex(self, index, val):判断index是否有效,index控制循环次数
newnode.next = cur.next,cur.next = newnode,链表长度+1 - deleteAtIndex(self, index):判断index是否有效,index控制循环次数,
cur.next = cur.next.next,链表长度-1
class Node(object):
def __init__(self, x=0, next=None):
self.val = x
self.next = next
class MyLinkedList(object):
def __init__(self):
self.dummy_head = Node()
self.len = 0
def get(self, index):
"""
:type index: int
:rtype: int
"""
if index < 0 or index > self.len - 1:
return -1
cur = self.dummy_head # 这里的dummy_head要加self(实例变量)
while index:
cur = cur.next
index -= 1
return cur.next.val
def addAtHead(self, val):
"""
:type val: int
:rtype: None
"""
# 这样写只是将新节点接在dummy_head后面,后面的链表会消失
# newnode = Node(val)
# self.dummy_head.next = newnode
# self.len += 1
newnode = Node(val) # 要新建一个节点!
newnode.next = self.dummy_head.next
self.dummy_head.next = newnode
self.len += 1
def addAtTail(self, val):
"""
:type val: int
:rtype: None
"""
newnode = Node(val)
cur = self.dummy_head
while cur.next: # 注意尾插的循环条件!!(while cur.next != None)
cur = cur.next
cur.next = newnode
self.len += 1
def addAtIndex(self, index, val):
"""
:type index: int
:type val: int
:rtype: None
"""
if index < 0 or index > self.len: # 注意不是>len-1!!
return
cur = self.dummy_head
newnode = Node(val)
while index:
cur = cur.next
index -= 1
newnode.next = cur.next
cur.next = newnode
self.len += 1
def deleteAtIndex(self, index):
"""
:type index: int
:rtype: None
"""
if index < 0 or index > self.len - 1:
return
cur = self.dummy_head
while index:
cur = cur.next
index -= 1
cur.next = cur.next.next
self.len -= 1
# 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)
总结
- 判断while的循环条件是否正确,可以带入极端值(0),while 0不执行
- cur = self.dummy_head # 这里的dummy_head要加self(实例变量)
- 添加链表节点:
newnode.next = cur.next
cur.next = newnode

头插:不能只写self.dummy_head.next = newnode,这样后面的链表会消失
尾插:循环条件是while cur.next != None
index插:index非法条件是index < 0 or index > self.len(注意不是len-1了!!等于len的时候插在尾部!!) - 删除链表节点:
cur.next = cur.next.next

三、Leetcode206(反转链表)
题目描述
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
输入:head = [1,2]
输出:[2,1]
输入:head = []
输出:[]
题目链接:力扣题目链接
解题思路
- 遍历链表,改变每个指针的方向
- 双指针思想

方法一:双指针
- pre为null,cur为head开始,将cur.next存于newnode
- 改变指针方向:cur.next=prev,prev=cur,cur=newnode,循环条件为cur不为None
- cur为None停止循环,返回新的头指针prev

# 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 reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
cur = head
prev = None
while cur:
nextnode = cur.next # 要新建一个指针!(拿cur.next操作会乱)
cur.next = prev
prev = cur
cur = nextnode
# 返回反转后的头指针
return prev
方法二:递归
- 递归的是pre和cur的移动变化,cur.next=pre的操作不变
- 只用改变pre和cur的传参
# 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 reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
def reverse(cur, prev):
if cur == None:
return prev
nextnode = cur.next
cur.next = prev
return reverse(nextnode, cur)
# 调用递归函数
return reverse(head, None)
总结
- 改变cur的指针方向,要先将cur.next存好!!
心得:坚持到Day3,链表操作很基础,但是有很多坑orz,希望下次不要犯同样错误!
本文详细介绍了LeetCode上的三个链表相关问题:203题(移除链表元素)采用虚拟头节点的方法,707题(设计链表)实现了链表的基本操作,以及206题(反转链表)通过双指针和递归的解法。每道题都提供了代码实现和解题总结,强调了链表操作的关键点。
1314

被折叠的 条评论
为什么被折叠?



