LeetCode 203. 移除链表元素
链表和数组的最大区别,就是前者内存分布是不连续的,后者内存分布连续
题目链接:203. 移除链表元素
思路:根据链表的特性,移除链表元素并不是像数组一样让后面的元素覆盖被移除的元素,而是修改next指针指向。至于被“移除”的元素,在Python、Java、Go中都有垃圾回收机制,会自动帮我们清除(如果该元素的引用计数为0的话)。
Python版本:
# 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: Optional[ListNode], val: int) -> Optional[ListNode]:
dummy = ListNode()
dummy.next = head
cur = dummy
while cur.next != None:
if cur.next.val == val:
cur.next = cur.next.next
else:
cur = cur.next
# 此处不能返回head, 要考虑原head可能被删除的情况
return dummy.next
时间复杂度: O ( n ) O(n) O(n),空间复杂度: O ( 1 ) O(1) O(1)
go版本:
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func removeElements(head *ListNode, val int) *ListNode {
dummy := &ListNode{}
dummy.Next = head
for cur := dummy; cur.Next != nil; {
if cur.Next.Val == val {
cur.Next = cur.Next.Next
} else {
cur = cur.Next
}
}
return dummy.Next
}
LeetCode 707. 设计链表
题目链接:707. 设计链表
思路:设置了一个虚拟头节点进行链表操作,在一开始写的时候一直有bug,排查后发现是get函数的循环体写的不对,应该循环index+1次而不是循环index次,因为虚拟头节点的下一个节点才是实际意义上的头节点。
Python版本:
class ListNode:
def __init__(self, val):
self.val = val
self.next = None
class MyLinkedList:
def __init__(self):
self.len = 0
self.dummy = ListNode(0)
def get(self, index: int) -> int:
if index < 0 or index >= self.len:
return -1
cur = self.dummy
# 此处要遍历index+1次, 因为虚拟头节点的下一个节点才是真正链表的头节点
for _ in range(index+1):
cur = cur.next
return cur.val
def addAtHead(self, val: int) -> None:
newNode = ListNode(val)
# 此处的顺序不能反
newNode.next = self.dummy.next
self.dummy.next = newNode
self.len += 1
def addAtTail(self, val: int) -> None:
newNode = ListNode(val)
cur = self.dummy
while(cur.next != None):
cur = cur.next
cur.next = newNode
self.len += 1
def addAtIndex(self, index: int, val: int) -> None:
if index > self.len:
return
# 注意是第index个节点之前
newNode = ListNode(val)
cur = self.dummy
for _ in range(index):
cur = cur.next
newNode.next = cur.next
cur.next = newNode
self.len += 1
def deleteAtIndex(self, index: int) -> None:
if index >= self.len:
return
cur = self.dummy
for _ in range(index):
cur = cur.next
cur.next = cur.next.next
self.len -= 1
go版本:
type MyLinkedList struct {
dummy *ListNode
len int
}
func Constructor() MyLinkedList {
return MyLinkedList{&ListNode{}, 0}
}
func (this *MyLinkedList) Get(index int) int {
if index >= this.len {
return -1
}
cur := this.dummy
for i := 0; i <= index; i++ {
cur = cur.Next
}
return cur.Val
}
func (this *MyLinkedList) AddAtHead(val int) {
this.AddAtIndex(0, val)
}
func (this *MyLinkedList) AddAtTail(val int) {
this.AddAtIndex(this.len, val)
}
func (this *MyLinkedList) AddAtIndex(index int, val int) {
if index > this.len {
return
}
pre := this.dummy
for ; index > 0; index-- {
pre = pre.Next
}
pre.Next = &ListNode{val, pre.Next}
this.len++
}
func (this *MyLinkedList) DeleteAtIndex(index int) {
if index >= this.len {
return
}
pre := this.dummy
for ; index > 0; index-- {
pre = pre.Next
}
pre.Next = pre.Next.Next
this.len--
}
LeetCode 206. 反转链表
题目链接:206. 反转链表
思路:首先想到的是使用双指针,后面看了代码随想录,学习了一下递归的写法 ヽ(✿゚▽゚)ノ
Python版本:
# 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: Optional[ListNode]) -> Optional[ListNode]:
cur = head
pre = None
while cur != None:
temp = cur.next
cur.next = pre
pre = cur
cur = temp
return pre
时间复杂度: O ( n ) O(n) O(n),空间复杂度: O ( 1 ) O(1) O(1)
go版本(递归):
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func reverseList(head *ListNode) *ListNode {
return reverseL(head, nil)
}
func reverseL(cur *ListNode, pre *ListNode) *ListNode {
if cur == nil {
return pre
}
temp := cur.Next
cur.Next = pre
return reverseL(temp, cur)
}
————————分割线————————
20220510:脑子完全转不动了 _(: 」∠) _