5.27 力扣链表

581. 最短无序连续子数组
在这里插入图片描述
排序后比较两个数组最左边和最右边不一致的元素

超时

class Solution:
    def findUnsortedSubarray(self, nums: List[int]) -> int:
        l,r=len(nums),0
        for i in range(len(nums)-1):
            for j in range(i,len(nums)):
                if nums[i]>nums[j]:
                    l=min(l,i)
                    r=max(r,j)
        return r-l+1 if r-l+1>0 else 0

使用两次栈

class Solution:
    def findUnsortedSubarray(self, nums: List[int]) -> int:
        stack=[]
        r=float('-inf')
        l=float('inf')
        #单调递增栈,找到最左边的边界
        for i in range(len(nums)):
            while stack and  nums[i]<nums[stack[-1]]:
                l=min(l,stack.pop())
            stack.append(i)
        stack=[]
        #从后往前构造单调递减栈,找到最右边的边界
        for i in range(len(nums)-1,-1,-1):
            while stack and nums[i]>nums[stack[-1]]:
                r=max(stack.pop(),r)
            stack.append(i)
        return r-l+1 if r-l>0 else 0

链表

快慢指针,用于定位节点
巧用dummpy,在头结点发生改变时,不需要考虑头结点的特殊处理,只要返回dummpy->next作为头结点即可
160. 相交链表
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        pre1,pre2=headA,headB
        while pre1!=pre2 :
            pre1=pre1.next if pre1 else headB
            pre2=pre2.next if pre2 else headA
            
        return pre1

重排链表:需要用到分治和 递归
143. 重排链表
在这里插入图片描述

class Solution:
    def reverseList(self, head):
        pre = None
        cur = head
        while cur:
            tmp=cur.next
            cur.next=pre
            pre=cur
            cur=tmp
        return pre
    def reorderList(self, head: ListNode) -> None:
        """
        Do not return anything, modify head in-place instead.
        """
        if not head:
            return head
        slow, fast = head, head
        #快慢指针分为前后两端
        while fast and fast.next:
            slow, fast = slow.next, fast.next.next
        p = slow.next
        slow.next = None
        #翻转后半段链表
        p = self.reverseList(p)
        m = head
        while p:
        #将后半段链表接到前半段
            m.next,p.next,m,p=p,m.next,m.next,p.next
        return head

61. 旋转链表
在这里插入图片描述
先将链表闭合成环,在合适的地方断开

class Solution:
    def rotateRight(self, head: ListNode, k: int) -> ListNode:
        if not head:
            return 
        if not head.next:
            return head
        count=1
        #原链表闭合成环
        old_tail=head
        while old_tail.next:
            old_tail=old_tail.next
            count+=1
        old_tail.next=head
        #找到新的断开点
        m=count-k%count-1
        new_tail=head
        for i in range(m):
            new_tail=new_tail.next
        head=new_tail.next
        new_tail.next=None
        return head

707. 设计链表
在这里插入图片描述
单向链表

class listnode:
    def __init__(self,val):
        self.val=val
        self.next=None
class MyLinkedList:

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.head=listnode(0)
        self.size=0
        

    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<0 or index>=self.size:
            return -1
        cur=self.head
        for _ in range(index+1):
            cur=cur.next
        return cur.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.
        """
        return self.addAtIndex(0,val)

    def addAtTail(self, val: int) -> None:
        """
        Append a node of value val to the last element of the linked list.
        """
        return 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>self.size:
            return 
        if index<0:
            index=0
        self.size+=1
        pre=self.head
        for _ in range(index):
            pre=pre.next
        newnode=listnode(val)
        newnode.next=pre.next
        pre.next=newnode
        

    def deleteAtIndex(self, index: int) -> None:
        """
        Delete the index-th node in the linked list, if the index is valid.
        """
        if index<0 or index>=self.size:
            return
        self.size-=1
        pre=self.head
        for _ in range(index):
            pre=pre.next
        pre.next=pre.next.next

817. 链表组件
在这里插入图片描述
在这里插入图片描述

class Solution:
    def numComponents(self, head: ListNode, G: List[int]) -> int:
        count=0
        cur=head
        stack=[]
        #直接用列表G很慢,换成set(G)就很快
        G=set(G)
        while cur:
            if cur.val in G:
                stack.append(cur.val)
            else:
                if stack:
                    count+=1
                    stack=[]
            cur=cur.next
        if stack:
            count+=1
        return count

189 旋转数组
在这里插入图片描述
原地算法:python的切片实现开销了额外空间。O(N)的复杂度

class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        n=len(nums)
        m=n-k%n
        nums[m:],nums[:m]=nums[:m],nums[m:]

旋转算法:
先选数组第一项,找到它应该存放的位置。接着选中这个位置上的数,移动到它适合的位置,需要记录已经处理过的序号,遇到死循环的,变为处理下一项
每一次将idx的数据放置到target的位置上,同时将target的位置上的数据存到tmp中
tmp存储下一个应该变动的数据,即这个位置上的数,tmp是一个临时位置
例如 nums=[1,2,3,4],k=2,第一次1挪到3的位置,tmp=3,第二次将3挪到1的位置,此时Target=0已经处理过了,接着处理下一项,即index=target+1,tmp=nums[target+1]

class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        n=len(nums)
        count=0
        idx,tmp=0,nums[0]
        hash=[0]
        while count<n:
        #计算tmp应该挪到的位置target
            count,target=count+1,(idx+k)%n
            tmp,nums[target]=nums[target],tmp
            if target not in hash :
                idx=target
            elif target+1<n:
                idx=target+1
                tmp=nums[idx]
            hash.append(idx)

328. 奇偶链表
在这里插入图片描述

class Solution:
    def oddEvenList(self, head: ListNode) -> ListNode:
        if not head:
            return head
        h1,h2=head,head.next
        slow,fast=head,head.next
        while fast and fast.next:
            slow.next=slow.next.next
            fast.next=fast.next.next
            slow=slow.next
            fast=fast.next
        slow.next=h2
        return head

725. 分隔链表
在这里插入图片描述
在这里插入图片描述

class Solution:
    def splitListToParts(self, root: ListNode, k: int) -> List[ListNode]:
        count=0
        s1=root
        while s1:
            count+=1
            s1=s1.next
        #m个链表应该多1
        m=count%k
        #每个链表的长度
        n=count//k
        ans=[]
        cur=root
        for i in range(k):
            #每一段的头结点
            head=cur
            #找到分割点断开
            for j in range(n+(1 if i<m else 0)-1):
                if cur:
                    cur=cur.next
            if cur:
                cur.next,cur=None,cur.next
            ans.append(head)
        return ans

面试题18. 删除链表的节点
在这里插入图片描述

class Solution:
    def deleteNode(self, head: ListNode, val: int) -> ListNode:
        dummy=ListNode(0)
        dummy.next=head
        cur=dummy
        while cur.next.val!=val:
            cur=cur.next
        cur.next=cur.next.next
        return dummy.next
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值