算法训练Day 3

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:脑子完全转不动了 _(: 」∠) _

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值