数据结构练习2

Task02 顺序表和链表

理论部分

理解线性表的定义与操作。
实现顺序表。
实现单链表、循环链表、双向链表。

练习部分

1、合并两个有序链表

将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:

输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
方法1 递归
思路:若l1和l2中两个都为null,则返回None,若其中一个为空,则返回另一个链表。之后先比较两个链表的头元素,看哪一个更小,递归地决定下一个添加到结果里的值。
1、基线条件(告诉函数不再调用自己,即递归如何终止,避免无限循环):
if l1=null:return l2 
if l2 = null:return l1
2、递归条件(函数调用自己):
					if l1.val < l2.val: 
						l1.next = self.mergeTwoLists(l1.next, l2)
            			return l1
			    	if l1.val >= l2.val: 
						l2.next = self.mergeTwoLists(l2.next, l1)
            			return l2
3、递归过程:输入:l1:1->2->4, l2:1->3->4
step 1:l1:1->2->4, l2:1->3->4  --> l2.next=self.mergeTwoLists(3->4,1->2->4 )
step 2:l1:1->2->4, l2:3->4 --> l1.next=self.mergeTwoLists(2->4,3->4 )
step 3:l1:2->4, l2:3->4  --> l1.next=self.mergeTwoLists(4,3->4 )
step 4:l1:4, l2:3->4  --> l2.next=self.mergeTwoLists(4,4)
step 5:l1:4, l2:4  --> l2.next=self.mergeTwoLists(4,null) 
step 6:l1:4, l2:null  -->return 4 
step 5:l1:4, l2:4  --> l2.next=self.mergeTwoLists(4,null) -->return 4->4
step 4:l1:4, l2:3->4  --> l2.next=self.mergeTwoLists(4,4) -->return 3->4->4
step 3:l1:2->4, l2:3->4  --> l1.next=self.mergeTwoLists(4,3->4 ) -->return 2->3->4->4
step 2:l1:1->2->4, l2:3->4 --> l1.next=self.mergeTwoLists(2->4,3->4 )-->return 1->2->3->4->4
step 1:l1:1->2->4, l2:1->3->4  --> l2.next=self.mergeTwoLists(3->4,1->2->4 )-->return 1->1->2->3->4->4
def mergetwoLists(self, l1, l2):
        if l1 is None:
            return l2
        elif l2 is None:
            return l1
        elif l1.val < l2.val:
            l1.next = self.mergeTwoLists(l1.next, l2)
            return l1
        else:
            l2.next = self.mergeTwoLists(l1, l2.next)
            return l2

在这里插入图片描述

方法2 迭代
建立一个虚拟节点:prehead,维护指针prev。比较l1和l2的头元素,将头元素更小的链表l1接在prev.next,prev指针后移一个单位,再用新的l1=l1.next与l2比较,以此类推,直到l1和l2其中一个链表为空,将不空的那个链表接到pre.next
class Solution(object):
    def mergeTwoLists(self, l1, l2):
        prehead = ListNode(-1)
        prev = prehead
        while l1 and l2:
            if l1.val <= l2.val:
               prev.next = l1
               l1 = l1.next
            else:
               prev.next = l2
               l2 = l2.next
            prev = prev.next

        prev.next = l1 if l1 is not None else l2
        return prehead.next

在这里插入图片描述
2、删除链表的倒数第N个节点

给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。

示例:

给定一个链表: 1->2->3->4->5, 和 n = 2.

当删除了倒数第二个节点后,链表变为 1->2->3->5.
方法1:二次遍历实现
一次遍历,求出链表的总长度k。
二次遍历,根据总长度k的值,求出k-n,将k-n的指针指向k-n+2,就将k-n+1的节点删除了
def removeNthFromEnd(self, head, n):
        if not head or n<=0: #链表为空或者n无效
            return head
        p = ListNode(-1) #建造一个虚拟节点,方便边界处理
        p.next = head 
        #一次遍历得到链表长度
        a = p
        k = 0
        while a.next: 
            a = a.next
            k = k+1
        if k<n: #n无效
            return head
        #二次遍历找到需要删除的节点
        b = p
        num = k-n #需删除的前一个节点位置
        while num > 0:
            b = b.next
            num = num-1
        b.next = b.next.next #将指针指向删除节点的后一位
        return p.next 

在这里插入图片描述

方法2:一次遍历实现
设置两个指针a和b,第一个指针b先走n步,然后a和b再同时走,b走到终点的时候,a就到被删除节点的前一位了。然后同方法一。
class Solution(object):  
    def removeNthFromEnd(self, head, n):
            p = ListNode(-1)
            p.next = head
            a = p
            b = p
            while n: #b先走n步
                b = b.next
                n = n-1
            if not b: #若n>链表长度,那么迭代n次后,b肯定为空
                return head
            while b.next: 
                a = a.next
                b = b.next
            a.next = a.next.next
            return p.next	

在这里插入图片描述
3、旋转链表

给定一个链表,旋转链表,将链表每个节点向右移动k个位置,其中k是非负数。

示例 1:

输入: 1->2->3->4->5->NULL, k = 2
输出: 4->5->1->2->3->NULL

解释:
向右旋转 1 步: 5->1->2->3->4->NULL
向右旋转 2 步: 4->5->1->2->3->NULL

示例 2:

输入: 0->1->2->NULL, k = 4
输出: 2->0->1->NULL

解释:
向右旋转 1 步: 2->0->1->NULL
向右旋转 2 步: 1->2->0->NULL
向右旋转 3 步: 0->1->2->NULL
向右旋转 4 步: 2->0->1->NULL
思路:
其实跟题目2有相似之处,即找到新的头结点和尾结点的位置,设链表长度为n,若k>n,则相当于右移 k%n 步。先计算链表长度。再将链表连接成环状,即用就得尾结点指向旧的头结点。之后计算新的新的头结点和尾结点,确定后在尾结点处切断,指向None即可。
def rotateRight(self, head, k):
        if not head:
            return None
        if not head.next:
            return head
        old_tail = head 
        n = 1
        while old_tail.next: #计算链表长度
            old_tail = old_tail.next
            n = n+1
        old_tail.next = head #构造成环状

        new_tail = head 
        m = n - k % n -1
        while m:
            new_tail = new_tail.next #新的尾结点的位置
            m = m-1
        new_head = new_tail.next #新的头结点的位置
        new_tail.next = None #切断这个环
        return new_head

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值