LeetCode:206. 反转链表(Java & Python)

题目:

反转一个单链表。

示例:

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

进阶:
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

 

解答:

迭代方式:

首先判断链表是不是空的,如果是空的,直接返回null;

对于链表:

放两个指针p1, p2:

不能直接将p2 -> next指向p1,否则链表会断掉。

可以设置一个tmp指针,指向 p2 -> next,保证后续的操作:

然后将p1,p2往前挪动,当然还有tmp,直到p2为空,这时p1指向反转后链表的头结点。

 

最后一次:

刚好结束的时候:

完成了?

不。好像有一点不对劲儿,还多了一个1 -> 2的指针,少了一个null(1 -> null)。正巧head还在,通过head -> next访问多余的指针,指向null(其实一开始就可以这么干的。)

实现代码:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        if (head == null) { //先考虑链表是否为空
            return null;
        }
        ListNode p1 = head;
        ListNode p2 = head.next;
        p1.next = null;
        while (p2 != null) {
            ListNode temp = p2.next;
            p2.next = p1;
            p1 = p2;
            p2 = temp;            
        }
        return p1;
    }
}

递归方式:

我们可以从另一个角度考虑这件事:

同样地,对于这样一个链表:

我们要反转它,其实可以

然后我们当作这个子链表已经反转完成:

而我们需要的是:

于是我们可以将上上张图的head.next.next = head:像是这样:

然而仅仅这样是不够的,链表到现在有一个明显的环,我们要把这个环去掉:

令head.next = null即可。

完成。

接下来考虑递归结束的条件:非常显然,子链表只有一个节点是递归结束,直接返回该节点。

当然,这个可以和一开始的空值处理(空链表的处理)写到一起。

下面是具体实现:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode subListHead = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return subListHead;
    }
}

—————————————————————————————————————————————————————————

2019.8.27更新

重新用Python刷了第二遍这个题.

同样的写两种方法.

迭代方法一遍写过, 递归方法想了老半天然而并没有写出来.

然后翻自己上次写的博客, 重新整理&记录一下递归的核心思路:

题目说了用递归做,那么首先我想到的就应该是reverseList(head.next),因为真的没有其他的任何写法了.

写出了递归调用,那么终止条件其实也好判断,括号里是空的自然就要终止了.

再然后就是画个图(如上),考虑用什么方式能让自己的链表和目标链表一模一样了.

据说写熟练了图都不用画可以直接写?还是贴一下实现代码吧,其实刷链表题啥语言都差不多.

迭代解法:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        if head == None:
            return head
        p1 = head
        p2 = head.next
        while p2 != None:
            temp = p2.next
            p2.next = p1
            p1 = p2
            p2 = temp
        head.next = None
        return p1

递归解法:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        if head == None or head.next == None:
            return head
        newNode = self.reverseList(head.next)
        head.next.next = head
        head.next = None
        return newNode
        

 

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
给定一个整数数组 nums 和一个目标值 target,要求在数组中找出两个数的和等于目标值,并返回这两个数的索引。 思路1:暴力法 最简单的思路是使用两层循环遍历数组的所有组合,判断两个数的和是否等于目标值。如果等于目标值,则返回这两个数的索引。 此方法的时间复杂度为O(n^2),空间复杂度为O(1)。 思路2:哈希表 为了优化时间复杂度,可以使用哈希表来存储数组中的元素和对应的索引。遍历数组,对于每个元素nums[i],我们可以通过计算target - nums[i]的值,查找哈希表中是否存在这个差值。 如果存在,则说明找到了两个数的和等于目标值,返回它们的索引。如果不存在,将当前元素nums[i]和它的索引存入哈希表中。 此方法的时间复杂度为O(n),空间复杂度为O(n)。 思路3:双指针 如果数组已经排序,可以使用双指针的方法来求解。假设数组从小到大排序,定义左指针left指向数组的第一个元素,右指针right指向数组的最后一个元素。 如果当前两个指针指向的数的和等于目标值,则返回它们的索引。如果和小于目标值,则将左指针右移一位,使得和增大;如果和大于目标值,则将右指针左移一位,使得和减小。 继续移动指针,直到找到两个数的和等于目标值或者左指针超过了右指针。 此方法的时间复杂度为O(nlogn),空间复杂度为O(1)。 以上三种方法都可以解决问题,选择合适的方法取决于具体的应用场景和要求。如果数组规模较小并且不需要考虑额外的空间使用,则暴力法是最简单的方法。如果数组较大或者需要优化时间复杂度,则哈希表或双指针方法更合适。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值