代码训练营 Day3 | 203.移除链表元素 | 707.设计链表 | 206.反转链表

链表的类型:

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

双链表: 每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点。 双链表 既可以向前查询也可以向后查询

循环链表: 链表首尾相连

链表的存储:

数组是在内存中是连续分布的,但是链表在内存中可不是连续分布的;链表是通过指针域指针链接在内存中各个节点

性能分析:

插入/删除(时间复杂度)查询(时间复杂度)试用场景
数组O(n)O(1)数据量固定,频繁查询,较少更改
链表O(1)O(n)数据量不固定,频繁增删,较少查询

203. 移除链表元素

1. 设置一个虚拟头节点,这样可以避免遍历链表时,头节点被更改

2. 链表中是不存在完全删除一个节点的,而是让删除节点的前一个节点指向删除节点后面的一个节点,如果试用的是C++ 记得手动释放内存

3. 最后返回头节点时,return dummy_head -> 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)
        # set a temp pointer, to help iterate the linklist
        cur = dummy_head

        # find remove element position; cur.next != None is aviod we are acees a empty Node
        while cur.next != None:
            # if we find the element we want to remove
            if cur.next.val == val:
                # remove the address, let cur point to next next
                cur.next = cur.next.next
            else:
                cur = cur.next
        
        return dummy_head.next     

707. 设计链表

  1.  使用虚拟头节点能很好的帮助实现每一个函数功能
  2. get函数: 判断index是否在valid的区域;current  = dummy_head.next 因为我们for循环出来current的下一个值才是我们获取的目标值
  3. addAtHead函数: 让新头节点指向之前的头节点,让dummy_head指向新头节点;记得linklist的size + 1因为我们添加了新的节点进入链表当中
  4. addAtTail函数:跟上面一个实现方法相同,不过我们需要先遍历到链表尾部
  5. addAtIndex函数: 这里对于index合法边界的判断要注意 index > size 即可,因为这样可以保证我们可以在链表尾部插入元素
  6. deleteAtIndex函数: 先检查index合法性,再去遍历到index位置通过操作链表节点的地址从而让需要删除节点跟前节点失去链接,达到删除的目的 

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

    def __init__(self):
        self.dummy_head = ListNode()    # create a vitrual head
        self.size = 0       # define linklist size

    def get(self, index):
        """
        :type index: int
        :rtype: int
        """
        # makesure is not empty linklist
        if index < 0 or index >= self.size:
            return -1
        
        current = self.dummy_head.next
        # iterate the linklist,find which element we want
        for _ in range(index):
            current = current.next
        
        # after the for loop we find index element, return it
        return current.val

    def addAtHead(self, val):
        """
        :type val: int
        :rtype: None
        """
        # create a new node
        newNode = ListNode(val=val)
        # temp head
        current = self.dummy_head

        # add new head
        newNode.next = current.next
        current.next = newNode
        
        # since we add a node into our linklist
        self.size += 1


    def addAtTail(self, val):
        """
        :type val: int
        :rtype: None
        """
        # creat dummy head
        current = self.dummy_head
        newNode = ListNode(val=val)

        # find the tail
        while current.next is not None:
            current = current.next
        
        # find the correct position to insert new Node
        current.next = newNode
        # add node into our linklist size += 1
        self.size += 1

    def addAtIndex(self, index, val):
        """
        :type index: int
        :type val: int
        :rtype: None
        """
        # determine the index is correct range
        if index < 0 or index > self.size:
            return 

        # create dummy head
        current = self.dummy_head
        # creat new node
        newNode = ListNode(val=val)

        # find index position
        for _ in range(index):
            current = current.next
        
        # add index element
        newNode.next = current.next
        current.next = newNode
        
        self.size += 1
        

    def deleteAtIndex(self, index):
        """
        :type index: int
        :rtype: None
        """
        # detemine index is valid range
        if index < 0 or index >= self.size:
            return

        # create dummyhead
        current = self.dummy_head

        # find the element we want to remove
        for _ in range(index):
            current = current.next
        
        # delet the node
        current.next = current.next.next

        self.size -= 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)

206. 反转列表(面试高频)

  1. 定义一个prev指针存储为None
  2. 创建虚拟头节点,避免在遍历的时候修改我们原始头节点
  3. 在遍历中使用temp去保存current的下一个节点地址
  4. 改变链表方向时,先让current.next 指向我们prev指针,也就是上一个节点元素
  5. 移动指针一定是要prev先走,如果current指针先移动的话会导致prev和current都指向同一个节点,从而导致失去前一个节点的地址从而无法顺利反转列表

最后返回一定是返回prev指针,因为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
        """
        dummy_head = ListNode(next=head)
        current = dummy_head.next

        # create prev pointer to save the previous node
        prev = None

        # iterate the linklist
        while current:
            # save current.next node addres
            temp = current.next

            current.next = prev
            # move prev first; if we move current first, then prev will point to same node as current
            prev = current
            # move current
            current = temp
        
        # return prev, this is our new head node
        return prev

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值