从零开始的力扣(第十七天)~
1.设计链表
设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。
在链表类中实现这些功能:
get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。
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
提示:
所有值都在 [1, 1000] 之内。
操作次数将在 [1, 1000] 之内。
请不要使用内置的 LinkedList 库。
—————————————————————————————————————————
比原给出的函数自己多定义一个节点类与链表长度的函数,可以简化其他函数的操作
class Node(object):
def __init__(self,val):
self.val = val
self.next = None
class MyLinkedList(object):
def __init__(self, node = None):
"""
Initialize your data structure here.
"""
self.__head = node
def get(self, index):
"""
Get the value of the index-th node in the linked list. If the index is invalid, return -1.
:type index: int
:rtype: int
"""
cur = self.__head
if index >= self.length() or index < 0:
return -1
count = 0
while count != index:
cur = cur.next
count += 1
return cur.val
def addAtHead(self, 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.
:type val: int
:rtype: None
"""
node = Node(val)
node.next = self.__head
self.__head = node
def addAtTail(self, val):
"""
Append a node of value val to the last element of the linked list.
:type val: int
:rtype: None
"""
node = Node(val)
cur = self.__head
if self.length() == 0:
self.__head = node
return
while cur.next is not None:
cur = cur.next
cur.next = node
def addAtIndex(self, index, val):
"""
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.
:type index: int
:type val: int
:rtype: None
"""
node = Node(val)
if index > self.length():
return
if index == self.length():
self.addAtTail(val)
return
if index <= 0:
self.addAtHead(val)
return
pre = self.__head
count = 0
while count != index - 1:
pre = pre.next
count += 1
node.next = pre.next
pre.next = node
def deleteAtIndex(self, index):
"""
Delete the index-th node in the linked list, if the index is valid.
:type index: int
:rtype: None
"""
if index >= self.length() or index < 0:
return
cur = self.__head
count = 0
while count != index - 1:
if index == 0:
self.__head = cur.next
return
cur = cur.next
count += 1
cur.next = cur.next.next
def length(self):
cur = self.__head
count = 0
while cur is not None:
cur = cur.next
count += 1
return count
# 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)
2.环形链表
给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1
输出:false
解释:链表中没有环。
进阶:
你能用 O(1)(即,常量)内存解决此问题吗?
—————————————————————————————————————————
这道题的代码中是不会给出pos的,只会给出头节点,这里使用双指针遍历,慢指针一次走一步,快指针一次走两步,当快慢重合时说明有循环
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
cur1 = cur2 = head
while cur1 and cur2 and cur2.next:
cur1 = cur1.next
cur2 = cur2.next.next
if cur1 == cur2:
return True
return False
3.环形链表 II
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
说明:不允许修改给定的链表。
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:tail connects to node index 1
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:tail connects to node index 0
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1
输出:no cycle
解释:链表中没有环。
进阶:
你是否可以不用额外空间解决此题?
—————————————————————————————————————————
既然不是用额外空间,那么就只能使用指针解决,当快慢指针交汇时快指针比慢指针多走了一倍的长度,而环的起始点A与交汇点B之间长度设为b,而原点与环的起始点距离为a,那么快指针多走的a+b的长度就等于环的长度,这样,为了求a,只要让起始点与慢指针同时向前走,他们的交汇点就是环的起始点(这里要注意,最后的输出要是结点,不能是节点的位置数值,卡了我好久?)
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
slow = fast = cur = head
while slow and fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
while slow != cur:
slow = slow.next
cur = cur.next
return cur
return None
4.相交链表
编写一个程序,找到两个单链表相交的起始节点。
如下面的两个链表:
在节点 c1 开始相交。
示例 1:
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Reference of the node with value = 8
输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
示例 2:
输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Reference of the node with value = 2
输入解释:相交节点的值为 2 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。
示例 3:
输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
输入解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
解释:这两个链表不相交,因此返回 null。
注意:
如果两个链表没有交点,返回 null.
在返回结果后,两个链表仍须保持原有的结构。
可假定整个链表结构中没有循环。
程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。
—————————————————————————————————————————
先对两个链表的长度进行计算,对长的链表先补位,使得两个指针到交点的长度一致,再两指针同步运行
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def getIntersectionNode(self, headA, headB):
"""
:type head1, head1: ListNode
:rtype: ListNode
"""
if not headA or not headB:
return None
cur1 = headA
cur2 = headB
lenA = self.length(headA)
lenB = self.length(headB)
num = lenA - lenB if lenA > lenB else lenB - lenA
for i in range(num):
if lenA > lenB:
cur1 = cur1.next
else:
cur2 = cur2.next
while cur1:
if cur1 == cur2:
return cur1
cur1 = cur1.next
cur2 = cur2.next
return None
def length(self,head):
count = 0
while head is not None:
count += 1
head = head.next
return count
5.删除链表的倒数第N个节点
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
进阶:
你能尝试使用一趟扫描实现吗?
—————————————————————————————————————————
直接判断链表长度,指针走链表长度-n的长度,然后删除
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def removeNthFromEnd(self, head, n):
"""
:type head: ListNode
:type n: int
:rtype: ListNode
"""
cur = head
if n == self.length(head):
return head.next
for i in range(self.length(head) - n - 1):
cur = cur.next
cur.next = cur.next.next
return head
def length(self, head):
count = 0
while head:
head = head.next
count += 1
return count
快慢指针,先让快指针走n个长度,再两指针同时走,这样既能保证慢指针距离末尾为n了
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def removeNthFromEnd(self, head, n):
"""
:type head: ListNode
:type n: int
:rtype: ListNode
"""
tail = head
for i in range(n):
tail = tail.next
if not tail:
return head.next
po = head
while tail.next:
tail = tail.next
po = po.next
po.next = po.next.next
return head
以上就是今日经验!