• 0707-leetcode算法实现之设计链表-design-linked-list-python&golang实现


    设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。

    在链表类中实现这些功能:

    get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
    addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
    addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
    addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val  的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
    deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。

    示例:

    MyLinkedList linkedList = new MyLinkedList();
    linkedList.addAtHead(1);
    linkedList.addAtTail(3);
    linkedList.addAtIndex(1,2); //链表变为1-> 2-> 3
    linkedList.get(1); //返回2
    linkedList.deleteAtIndex(1); //现在链表是1-> 3
    linkedList.get(1); //返回3

    提示:

    所有val值都在 [1, 1000] 之内。
    操作次数将在  [1, 1000] 之内。
    请不要使用内置的 LinkedList 库。

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/design-linked-list

    python

    # 0707.设计链表实现以下5中功能:
    # -根据索引获取值
    # -头插
    # -尾插
    # -根据索引插入
    # -根据索引删除
    
    # 单链表
    class Node:
        def __init__(self, val):
            self.val = val
            self.next = None
    
    class Mylinklist:
        def __init__(self, node=None):
            if node != None:
                # 当节点非空时,实例化节点,让头结点指向节点
                headNode = Node(node)
                self._head = headNode
            else:
                # 如果节点空,头结点指向None
                self._head = node
    
        def length(self):
            """
            初始化计数,当节点非空,不断右移,计数器++,重复,返回计数
            :return:
            """
            cnt = 0
            cur = self._head
            while cur:
                cur = cur.next
                cnt += 1
            return cnt
    
        def transverse(self):
            """
            当前节点即为头结点,非空即打印节点值,指针右移,重复
            :return:
            """
            cur = self._head
            while cur:
                print(cur.val)
                cur = cur.next
    
        def get(self, index: int) -> int:
            """
            初始化计数器,初始化从头结点开始,遍历节点,
            如果遍历到计数器等于index,即找到合适index的值返回,
            否则计数器++,链表指针右移,重复
            如果遍历链表没有index,即返回-1,表示index超出了链表范围
            :param index:
            :return:
            """
            cnt = 0
            cur =self._head
            while cur:
                if cnt == index:
                    return cur.val
                cnt += 1
                cur = cur.next
            return -1
    
        def addAtHead(self, val) -> None:
            """
            头部插入节点,根据节点值,生成节点对象,让该节点指向头结点,头结点指向node
            :param val:
            :return:
            """
            node = Node(val)
            node.next = self._head # 代表节点指向头结点的next对象
            self._head = node
    
        def addAtTail(self, val: int) -> None:
            node = Node(val)
            # 尾部插入判断当前链表是否空
            # 空链表时,头部指向为空,直接让头部指向节点
            if self._head == None:
                self._head = Node
            # 一般情况下,遍历到尾部,尾部节点指向插入节点,插入节点指向None
            else:
                cur = self._head
                # 遍历到最后一个节点时,next为None,即break循环
                while cur.next != None:
                    cur = cur.next
                # 尾部节点指向插入节点,完成尾部插入
                cur.next = node
    
        def addAtIndex(self, index: int, val: int) -> None:
            """
            给定插入位置,与插入的值,需要插入位置的前序节点pre, 和当前节点cur,
            pre指向node, node指向cur
            :param val:
            :return:
            """
            node = Node(val)
            # index < 0,头插
            if index < 0:
                self.addAtHead(val)
            # index越界,尾插
            elif index > self.length():
                self.addAtTail(val)
            # 一般情况,链表中插入
            # 通过遍历计数比较index获取index-1位置节点
            # 插入节点的next指针指向p先序节点的next
            # 先序节点指向插入节点,完成插入,且不断
            else:
                cnt = 0
                pre = self._head
                while cnt < index:
                    pre = pre.next
                    cnt += 1
                node.next = pre.next
                pre.next = node
    
        def deleteAtIndex(self, index: int) -> None:
            # 给定index<0,直接返回空
            if index < 0:
                return
            # index为0时,头部指向当前头部的next即可
            elif index == 0:
                self._head = self._head.next
            # 一般情况下index>0, 分链表长度内的或越界的,2种情况
            else:
                cnt = 0
                cur = self._head
                while cnt < index:
                    cur = cur.next
                    cnt += 1
                # 遍历结束后,index-1位置的元素的next指向其next的next
                if cur.next != None:
                    cur.next = cur.next.next
                # 否则,越界
                else:
                    return
    
    
    
    
    if __name__ == "__main__":
        node = Mylinklist()
        node.addAtHead(200)
        print(node.get(0))
        node.addAtHead(250)
        node.addAtTail(260)
        node.addAtIndex(2,251)
        print(node.get(0))
        node.transverse()
        print(node.length())
        node.deleteAtIndex(1)
        print(node.length())
        node.transverse()
    ---以下为官方
    class ListNode:
        def __init__(self, x):
            self.val = x
            self.next = None
    
    class MyLinkedList:
        def __init__(self):
            self.size = 0
            self.head = ListNode(0)  # sentinel node as pseudo-head
            
    
        def get(self, index: int) -> int:
            """
            Get the value of the index-th node in the linked list. If the index is invalid, return -1.
            """
            # if index is invalid
            if index < 0 or index >= self.size:
                return -1
            
            curr = self.head
            # index steps needed 
            # to move from sentinel node to wanted index
            for _ in range(index + 1):
                curr = curr.next
            return curr.val
                
    
        def addAtHead(self, val: int) -> None:
            """
            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.
            """
            self.addAtIndex(0, val)
            
    
        def addAtTail(self, val: int) -> None:
            """
            Append a node of value val to the last element of the linked list.
            """
            self.addAtIndex(self.size, val)
            
    
        def addAtIndex(self, index: int, val: int) -> None:
            """
            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.
            """
            # If index is greater than the length, 
            # the node will not be inserted.
            if index > self.size:
                return
            
            # [so weird] If index is negative, 
            # the node will be inserted at the head of the list.
            if index < 0:
                index = 0
            
            self.size += 1
            # find predecessor of the node to be added
            pred = self.head
            for _ in range(index):
                pred = pred.next
                
            # node to be added
            to_add = ListNode(val)
            # insertion itself
            to_add.next = pred.next
            pred.next = to_add
            
    
        def deleteAtIndex(self, index: int) -> None:
            """
            Delete the index-th node in the linked list, if the index is valid.
            """
            # if the index is invalid, do nothing
            if index < 0 or index >= self.size:
                return
            
            self.size -= 1
            # find predecessor of the node to be deleted
            pred = self.head
            for _ in range(index):
                pred = pred.next
                
            # delete pred.next 
            pred.next = pred.next.next
    ---双向链表
    # 双向链表
    class ListNode:
        def __init__(self, val):
            self.val = val
            self.next, self.prev = None, None
    
    
    class MyLinkerList:
        def __init__(self):
            self.size = 0
            # 哨兵作为虚拟头尾节点
            self.head, self.tail = ListNode(0), ListNode(0)
            self.head.next = self.tail
            self.tail.prev = self.head
    
        def get(self, index: int) -> int:
            if index < 0 or index >= self.size:
                return -1
            # 头部遍历
            if index + 1 < self.size - index:
                cur = self.head
                for _ in range(index+1):
                    cur = cur.next
            # 尾部遍历
            else:
                cur = self.tail
                for _ in range(self.size - index):
                    cur = cur.prev
            return cur.val
    
        def addAtHead(self, val: int) -> None:
            prev, next = self.head, self.head.next # 头部前2节点
            self.size += 1 # 新增加点,长度加1
            node = ListNode(val)
            node.prev = prev # 插入节点前序指针指向头1节点
            node.next = next # 插入节点后继指针指向原头二节点
            prev.next = node # 头1节点后继指针指向节点
            next.prev = node # 原头2节点的前序指针指向节点
    
        def addAtTail(self, val: int) -> None:
            # 与头插类似
            next, prev = self.tail, self.tail.prev
            self.size += 1
            node = ListNode(val)
            node.prev = prev
            node.next = next
            prev.next = node
            next.prev = node
    
        def addAtIndex(self, index: int, val: int) -> None:
            if index > self.size:
                return
            if index < 0:
                index = 0
            if index < self.size - index: # 头部插入,向后遍历
                prev = self.head
                for _ in range(index):
                    prev = prev.next
                next = prev.next
            else: # 尾部插入,向前遍历
                next = self.tail
                for _ in range(self.size-index):
                    next = next.prev
                prev = next.prev
            self.size += 1
            node = ListNode(val)
            node.prev = prev
            node.next = next
            prev.next = node
            next.prev = node
    
        def deleteAtIndex(self, index: int) -> None:
            if index < 0 or index > index.size:
                return
    
            if index < self.size - index:
                prev = self.head
                for _ in range(index):
                    prev = prev.next
                next = prev.next.next
            else:
                next = self.tail
                for _ in range(self.size-index):
                    next = next.prev
                prev = next.prev.prev
    
            # rm node
            self.size -= 1
            prev.next = next
            next.prev = prev
    
    
    
    

    golang

    # 单链表
    type ListNode struct {
    	Val  int
    	Next *ListNode
    }
    
    type MyLinkedList struct {
    	size int
    	head *ListNode
    }
    
    // initialize data structure
    func Constructor() MyLinkedList {
    	return MyLinkedList{
    		0,
    		&ListNode{},
    	}
    }
    
    func (this *MyLinkedList) Get(index int) int {
    	if index < 0 || index > this.size {
    		return -1
    	}
    	prev := this.head
    	for i := 0; i < index; i++ {
    		prev = prev.Next
    	}
    	return prev.Next.Val
    }
    
    func (this *MyLinkedList) AddAtHead(val int) {
    	this.AddAtIndex(0, val)
    }
    
    func (this *MyLinkedList) AddAtTail(val int) {
    	this.AddAtIndex(this.size, val)
    }
    
    func (this *MyLinkedList) AddAtIndex(index int, val int) {
    	if index < 0 || index > this.size {
    		return
    	}
    	pre := this.head
    	for i := 0; i < index; i++ {
    		pre = pre.Next
    	}
    	node := &ListNode{Val: val}
    	node.Next = pre.Next
    	pre.Next = node
    	this.size++
    }
    
    func (this *MyLinkedList) DeleteAtIndex(index int) {
    	if index < 0 || index > this.size {
    		return
    	}
    	prev := this.head
    	for i := 0; i < index; i++ {
    		prev = prev.Next
    	}
    	prev.Next = prev.Next.Next
    	this.size++
    }
    ---以下双链表
    
    // 定义链表节点
    type Node struct {
    	Next *Node
    	Prev *Node
    	Val  int
    }
    
    type MyLinkedList struct {
    	head *Node // 头结点
    	tail *Node // 尾结点
    	size int   // 链表的长度
    }
    
    /** Initialize your data structure here. */
    func Constructor() MyLinkedList {
    	return MyLinkedList{}
    }
    
    /** Get the value of the index-th node in the linked list. If the index is invalid, return -1. */
    func (this *MyLinkedList) Get(index int) int {
    	// index无效
    	if this.size == 0 || index < 0 || index >= this.size {
    		return -1
    	}
    	// index为头尾节点
    	if index == 0 {
    		return this.head.Val
    	}
    	if index == this.size-1 {
    		return this.tail.Val
    	}
    	// 下面选择更快的遍历方向, 查看index在偏头部还是偏尾部
    	cur := this.head
    	count := 0
    	for cur != nil {
    		if count == index {
    			break
    		}
    		count++
    		cur = cur.Next
    	}
    	return cur.Val
    }
    
    /** 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. */
    func (this *MyLinkedList) AddAtHead(val int) {
    	node := &Node{Val: val}
    	
    	if this.head != nil {
    		node.Next = this.head
    		this.head.Prev = node
    		this.head = node
    	} else {
    		this.head = node
    		this.tail = this.head
    	}
    	this.size++
    }
    
    /** Append a node of value val to the last element of the linked list. */
    func (this *MyLinkedList) AddAtTail(val int) {
    	node := &Node{Val: val}
    	
    	if this.tail != nil {
    		node.Prev = this.tail
    		this.tail.Next = node
    		this.tail = node
    	} else {
    		this.tail = node
    		this.head = this.tail
    	}
        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. */
    func (this *MyLinkedList) AddAtIndex(index int, val int) {
    	if index > this.size {
    		return
    	}
    	if index <= 0 {
    		this.AddAtHead(val)
    		return
    	}
    	if index == this.size {
    		this.AddAtTail(val)
    		return
    	}
    	cur := this.head
    	count := 0
    	for cur != nil && count < index {
    		count++
    		cur = cur.Next
    	}
    	// 在当前节点cur的前面插入
    	this.size++
    	node := &Node{Val: val, Next: cur, Prev: cur.Prev}
    	cur.Prev.Next = node
    	cur.Prev = node
    }
    
    /** Delete the index-th node in the linked list, if the index is valid. */
    func (this *MyLinkedList) DeleteAtIndex(index int) {
    	// 如果索引无效 || 链表为空
    	if this.size == 0 || index < 0 || index >= this.size {
    		return
    	}
    	if index == 0 {
    		// 如果删除的是头结点
    		this.head = this.head.Next
    	} else if index == this.size-1 {
    		// 如果删除的是尾结点
    		this.tail = this.tail.Prev
    	} else {
    		cur := this.head
    		count := 0
    		for cur != nil && count < index {
    			count++
    			cur = cur.Next
    		}
    		// 找到要删除的节点cur了
    		cur.Next.Prev = cur.Prev
    		cur.Prev.Next = cur.Next
    	}
    	this.size--
    }
    
    
    
  • 相关阅读:
    安卓开发学习日记 DAY1
    安卓开发学习日记 DAY5——监听事件onClick的实现方法
    安卓开发学习日记 DAY3——TextView,EditView,ImageView
    [原] XAF Try an XAF application that uses the Entity Framework as an ORM layer
    [原] XAF 如何使用Top
    [原] Sql Server 获取某年某月有多少个工作日(仅不包含星期日)
    [原] XAF Split View (aka MasterDetailMode=ListViewAndDetailView) improvements
    Sql Server 问题之between and 使用注意事项
    [原] XAF ListView 粘贴行或单元格
    [原] XAF How to see and edit the time part in the DatePropertyEditor for the System.DateTime property
  • 原文地址:https://www.cnblogs.com/davis12/p/15483969.html
Copyright © 2020-2023  润新知