链表反转

本文参考博客http://blog.csdn.net/feliciafay/article/details/6841115,利用其方法并使用Java语言进行实现。

首先,给出链表节点定义,使用了leetcode的节点模型进行声明。

public class ListNode {
    int val;
    ListNode next;

    ListNode(int x) {
        val = x;
        next = null;
    }
}

常见的链表反转方法大约有以下三种:
一、使用3个指针遍历单链表,逐个链接点进行反转。
1 -> 2 -> 3 -> 4 -> 5
考虑这个链表,实现反转只需要逐步进行即可。
1 <- 2 -> 3 -> 4 -> 5
1 <- 2 <- 3 -> 4 -> 5
……
这是最容易直观的方法,实现的代码如下:

public class Solution {
    public ListNode reverse(ListNode head) {
        if (head == null)
            return head;

        ListNode prev = head, current = prev.next, last;
        head.next = null;

        while (current != null) {
            last = current.next;
            current.next = prev;
            prev = current;
            current = last;
        }

        return prev;
    }
}

二、从第2个节点到第N个节点,依次逐节点插入到第1个节点(head节点)之后,最后将第一个节点挪到新表的表尾。
1 -> 2 -> 3 -> 4 -> 5
1 -> 3 -> 2 -> 4 -> 5
1 -> 4 -> 3 -> 2 -> 5
……
当然,以上是大致过程,考虑到首节点也需要变化,我们可以为链表新加一个头,这也是处理链表问题常用的手段之一。

public class Solution {
    public ListNode reverse(ListNode head) {
        if (head == null)
            return head;

        ListNode prev = new ListNode(0);
        prev.next = head;
        ListNode current = prev.next, last;

        while (current.next != null) {
            last = current.next;
            current.next = last.next;
            last.next = prev.next;
            prev.next = last;
        }

        return prev.next;
    }
}

三、递归
树的很多问题都可以通过递归实现,对于单链表,可以看做是颗永远只有左(右)子树的树,因此可以考虑用递归来解决。
具体思路直接套用原作者的想法,如果需要把A->B->C->D进行反转,可以先假设B->C->D已经反转好,已经成为了D->C->B,那么接下来要做的事情就是将D->C->B看成一个整体,让这个整体的next指向A,所以问题转化了反转B->C->D。那么,可以先假设C->D已经反转好,已经成为了D->C,那么接下来要做的事情就是将D->C看成一个整体,让这个整体的next指向B,所以问题转化了反转C->D。那么,可以先假设D(其实是D->NULL)已经反转好,已经成为了D(其实是head->D),那么接下来要做的事情就是将D(其实head->D)看成一个整体,让这个整体的next指向C,所以问题转化了反转D。

public class Solution {
    public ListNode reverse(ListNode head) {
        if (head == null || head.next == null)
            return head;

        ListNode prev, last;
        prev = head.next;
        last = reverse(head.next);
        prev.next = head;
        head.next = null;

        return last;
    }
}

最后是测试代码:

public class Test {
    public static void main(String[] args) {
        int[] nums = {1, 2, 3, 4, 5, 6};
        ListNode head = createList(nums);
        Solution solution = new Solution();
        printList(solution.reverse(head));
    }

    private static ListNode createList(int[] nums) {
        ListNode head = new ListNode(0);
        ListNode result = head;

        for (int i : nums) {
            ListNode node = new ListNode(i);
            head.next = node;
            head = head.next;
        }

        return result.next;
    }

    private static void printList(ListNode head) {
        ListNode current = head;

        while (current != null) {
            System.out.print(current.val + " ");
            current = current.next;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值