算法3day|203,707,206

链表理论基础

 

定义:链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。

表示

下一个链表是:head.next

链表的值:head.value

数组和链表的区别

数组是在内存中是连续分布的,但是链表在内存中不是连续分布的。

链表的创建:dummy = ListNode(0)---python

 class ListNode(object):
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

链表的删除:

直接 只要将C节点的next指针 指向E节点就可以了

head.next = head.next.next

时间复杂度:O(1)

链表的增加:

时间复杂度:O(1)

数组和链表之间的对比:

203.移除链表元素

我的解法:

class Solution(object):
    def removeElements(self, head, val):
        """
        :type head: ListNode
        :type val: int
        :rtype: ListNode
        """
        if head is None:
            return 
        dummy = ListNode(0)
        dummy.next = head
        pre = dummy 
        while head is not None:
            if head.val == val:
                pre.next = head.next
            else:
                pre = pre.next
            head = head.next
        return dummy.next
                

疑问:head随着移动不懂断掉嘛?而且到底dummy指向的是head,但是移到了最后,head移到了最后,链表不是断掉了嘛?所以我的解法有很多问题,我自己都无法理解,然后就写出来了

题目题解:

(使用虚拟头节点)

class Solution(object):
    def removeElements(self, head, val):
        """
        :type head: ListNode
        :type val: int
        :rtype: ListNode
        """
        if head is None:
            return 
        dummy = ListNode(0) #dummy的作用:方便处理头节点
        dummy.next = head 
        cur = dummy #单向链表,删除的时候,需要找到前面(a),指向(c)
        #终止条件需要注意
        while cur.next is not None:
            if cur.next.val == val:
               #指针的指向要设置正确
                cur.next = cur.next.next
            #if语句的逻辑有问题,很有可能出错
            else:
                cur = cur.next
        return dummy.next #不直接return head 是因为head有可能被删除了

(原来链表的进行删除)

总结:

链表操作的两种方式:

  • 直接使用原来的链表来进行删除操作。
  • 设置一个虚拟头结点在进行删除操作。

二刷:

虽然是AC了,但是用一点时间

class Solution:
    def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
        dummy = ListNode(0)
        dummy.next = head
        pre = dummy
        while pre is not None and  pre.next is not None:
            while pre.next is not None and pre.next.val == val:
                pre.next = pre.next.next
            pre = pre.next
        return dummy.next

这个while就很灵魂,需要时刻注意,因为可能像[7,7,7,7]这种,就需要用到循环一直下去

var removeElements = function(head, val) {
    const dummy = new ListNode(0,head)
    let cur = dummy
    while(cur.next){
        if(cur.next.val === val){
            cur.next = cur.next.next
        }else{
        cur = cur.next}
    }
    return dummy.next
};

206.反转链表

我自己解法,我都绕不过来,设置了三个指针,非常复杂。

题目解法:

(双指针法)

class Solution(object):
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        pre = None
        cur = head
        while cur is not None: #遍历到null时跳出循环,因为不需要反转null的指针
            #保存节点,防止丢失。反转后会断掉
            temp = cur.next
            #反转节点
            cur.next = pre
            #pre 向前移动
            pre = cur
            #cur向前移动
            cur = temp
            #上面两步的顺序不能搞错,不然就是pre = temp了
        #终止条件是pre,不是cur,因为他还会移动一次
        return pre
            

(递归法)

class Solution(object):
    def reverseList(self, head):
        """
       根据双指针的题解来解的
        """
        def reverse(pre,cur):
            #终止条件,遍历到最后cur为空,不用反转了
            if cur is None:
                return pre
            #记录一下拉下的节点
            temp = cur.next
            #反转指针 
            cur.next = pre
            #这句话相当于pre = cur,cur = temp
            return reverse(cur,temp)
        return reverse(None,head)

递归要素:

接受的参数:reverse(pre,cur):

返回值:return reverse(cur,temp)

终止条件:if cur is None:
                        return pre

千万不要忘记

二刷

没有ac这道题

class Solution:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        pre = None 
        cur = head
        while cur is not None:
            temp = cur.next
            cur.next = pre
            pre = cur
            cur = temp
        return pre

具体的问题在,设置pre 的时候,我直接等于dummy节点了。应该设置他为None。然后反转指针的时候,不知道往下面移动。

递归法,直接就反转了,没有那么多事情

class Solution:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        #递归法

        def reverse(pre,cur):
            if cur is None:
                return pre
            temp = cur.next
            cur.next = pre
            return reverse(cur,temp)
        return reverse(None,head)

三刷

var reverseList = function(head) {
    let pre = null
    let cur = head
    while(cur){
        let temp = cur.next
        cur.next = pre
        pre = cur 
        cur = temp
    }
    return pre  
};

707.设计链表

class ListNode(object):
    #创建不要忘记写初始化的函数名
    def __init__(self,val):
        self.val = val
        self.next = None
class MyLinkedList(object):

    def __init__(self):
        #链表长度
        self.size = 0
        #创建虚拟头节点
        self.head = ListNode(0)
    def get(self, index):
        #这个临界条件不要忘记写了
        #不可以等于size,因为index从0 开始
        if index < 0 or index >= self.size:
            return -1
        cur = self.head
        for i in range(index+1):
            cur = cur.next
        return cur.val
    
    def addAtHead(self, val):
        self.addAtIndex(0,val)
        
    def addAtTail(self, val):
        self.addAtIndex(self.size,val)
        
        
    def addAtIndex(self, index, val):
        #临界条件要记得写,不等于size是因为可能插在最后
        if index > self.size:
            return
        cur = self.head
        newNode = ListNode(val)
        for i in range(index):
            cur = cur.next
        newNode.next = cur.next
        cur.next = newNode
        self.size += 1
        
    def deleteAtIndex(self, index):
        #可能链表中没有节点
        if index <0 or index >= self.size:
            return
        cur = self.head
        for i in range(index):
            cur = cur.next
        cur.next = cur.next.next
        self.size -= 1

总结:

临界条件不要忘记写,可能超出范围了呢!!!!!!!!

二刷:

这个临界条件没有写!

 if index < 0 or index >= self.size:
            return -1

这个循环遍历的写错了

for i in range(index+1):

self没加

self.size += 1
self.dummy = 0

class ListNode {
  constructor(val, next) {
    this.val = val == undefined ? 0 : val;
    this.next = next == undefined ? null : next;
  }
}

/**
 * Initialize your data structure here.
 */
var MyLinkedList = function() {
    this.head = null;
    this.size = 0
};

/**
 * Get the value of the index-th node in the linked list. If the index is invalid, return -1. 
 * @param {number} index
 * @return {number}
 */
MyLinkedList.prototype.get = function(index) {
    if (index < 0 || index >=this.size) return -1;
    let cur = this.head;
    for (let i = 0; i < index; i++) {
        cur = cur.next;
    }
    if(cur !== null){
        return cur.val;
    }else{
        return -1
    }
    
};

/**
 * Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. 
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtHead = function(val) {
    let node = new ListNode(val);
    node.next = this.head;
    this.head = node;
    this.size ++
};

/**
 * Append a node of value val to the last element of the linked list. 
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtTail = function(val) {
    if (this.head == null) {
        this.addAtHead(val);
        return;
    }
    let node = new ListNode(val);
    let cur = this.head;
    while (cur.next !== null) {
        cur = cur.next;
    }
    cur.next = node;
    this.size ++
};

/**
 * Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. 
 * @param {number} index 
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtIndex = function(index, val) {
    if (index === 0) {
        this.addAtHead(val);
        return;
    }
    if (index === this.size) {
        this.addAtTail(val);
        return;
    }
    if (index > this.size) return;
        
    let cur = this.head;
    let node = new ListNode(val);
    for (let i = 0; i < index-1; i++) {
        cur = cur.next;
    }
    let next = cur.next;
    cur.next = node;
    node.next = next;
    this.size ++
};

/**
 * Delete the index-th node in the linked list, if the index is valid. 
 * @param {number} index
 * @return {void}
 */
MyLinkedList.prototype.deleteAtIndex = function(index) {
    if (index < 0 || index >= this.size) return;
    if (index == 0) {
        this.head = this.head.next;
        return;
    }

    let cur = this.head;
    for (let i = 0; i < index-1; i++) {
        cur = cur.next;
    }
    cur.next = cur.next.next;
    this.size --
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值