算法通关村第二关--链表反转进阶

1. 指定区间反转链表(left-right)

这里有两个思路:

第一个是直接在链表上进行反转,确定好需要反转的区间里面的第一个元素(cur)和反转区间前的那个元素(pre)后,不停的把cur后面那个元素放到pre后面,循环right-left次,即可实现反转。

第二个是将原来的链表进行拆分,反转区间前的那一段,需要反转的那一段,反转区间后面的那一段(请注意,记的把前两段最后一个元素的next指向None来切断链表);接着用上一篇文章里的反转链表把需要反转的那部分反转;最后处理完把这三部分再拼接起来,实现链表指定区间的反转。

 2. 两两交换链表元素

实现原理为找到pre节点 (从新设置的dummy开始),对pre.next和pre.next.next进行反转操作,之后推进pre节点。相关代码实现如下:

另外,在代码实现过程中出现了下面的错误,在此总结原因 :我把cur放到了循环外层导致了一些问题,假设我在反转1,2,3,4,5,在完成了第一次循环后我的cur为2,但是原链表变成了2,1,3,4,5, 导致2的下一个元素又变成了1 而不是我希望的3,因此陷入了死循环,右图为改正过后的代码。

 ---->  

3. 链表加一

要实现链表加一有两种方法:

第一种不需要反转链表, 思路是先遍历链表找到最右边的那个非9的数字,然后把它加一,之后把它后面的数字归零(因为满9进1),要注意处理一下边界情况(999),代码和解释如下:

 

第二种是先反转链表,然后从左往右遍历,如果是9就变0,然后进入下一位,直到不是9的时候,下一位加一,注意边界情况(999).

    def plusOne2(self, head):
        def reverse(head):
            dummy = ListNode(-1)
            cur = head
            while cur:
                next = cur.next
                cur.next = dummy.next
                dummy.next = cur
                cur = next
            return dummy.next
        head = reverse(head)
        curr = head
        while curr and curr.val == 9:
            curr.val = 0
            curr = curr.next
        if curr:
            curr.val += 1
            ans = reverse(head)
            return ans
        else:
            head = ListNode(1, head)
            return head

3. 链表相加

链表相加相当于是链表加一的进阶版,实现链表相加也有两种方法

第一种是使用栈,把链表的数据append到列表中,然后依次pop出来,进行相加(注意:这里还需要引入一个参数来代表是否有进1,如下面代码中的carry)

第二种使用链表反转,反转后按位依次相加计算,最后再把得到的结果反转回来。

    def reverseList(self, head):
        prev = None
        curr = head
        while curr:
            nextTemp = curr.next
            curr.next = prev
            prev = curr
            curr = nextTemp
        return prev

    def addTwoNumbersI(self, l1, l2):
        ans = ListNode(0, None)
        DUMMY_HEAD, res = ans, 0
        p1, p2 = l1, l2

        while p1 != None or p2 != None or res == 1:

            ans.next = ListNode(0, None)
            ans = ans.next

            if p1 != None and p2 != None:
                sums = p1.val + p2.val
                if sums + res < 10:
                    ans.val = sums + res
                    res = 0
                else:
                    ans.val = sums + res - 10
                    res = 1
                p1, p2 = p1.next, p2.next

            elif p1 == None and p2 != None:
                sums = p2.val
                if sums + res < 10:
                    ans.val = sums + res
                    res = 0
                else:
                    ans.val = sums + res - 10
                    res = 1
                p2 = p2.next

            elif p2 == None and p1 != None:
                sums = p1.val
                if sums + res < 10:
                    ans.val = sums + res
                    res = 0
                else:
                    ans.val = sums + res - 10
                    res = 1
                p1 = p1.next

            else:
                ans.val = res
                res = 0
        return DUMMY_HEAD.next

    # 调用入口
    def addTwoNumbers2(self, l1, l2):
        return self.reverseList(self.addTwoNumbersI(self.reverseList(l1), self.reverseList(l2)))

4. 回文序列(1,2,3,2,1) 

在学完链表反转之后可以使用 快慢指针法 (准确找到中间点然后切段)+ 链表反转法(把后半段反转),实现从头开始比较两端链表。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值