链表之反转链表专题

链表之反转链表专题

如题,LeetCode 206

链表之反转链表专题_第1张图片

看到反转链表,我们要思考的核心点在于如何让链表的结点指针指向的方向反转

对于反转链表,一般有迭代或者递归两种思考方向

第一种:迭代

在这种方案中,做题总结出了双指针迭代比较高效,同时有一种双指针的迭代公式

具体的动画效果可以参考LeetCode官方题解

题解动画

while(cur!=null) {
	//记录当前节点的下一个节点
	tmp = cur.next;
	//然后将当前节点指向pre
	cur.next = pre;
	//pre和cur节点都前进一位
	pre = cur;
	cur = tmp;
}

比如,在这个题当中,

step1:使用临时节点 tmp 记录当前节点的下一个结点(和我们常用的借用第三个数交换另外两个数的值思想一致)

step2:控制下一个结点的方向反转

step3:移动当前节点和前驱节点

起始状态为下图所示,那么,我们肯定要记录当前节点的下一个结点,我们使用一个临时的指针用于存储达到交换的目的,这里的思想和常用的交换两个数借用第三个数的思想一致。

链表之反转链表专题_第2张图片

class Solution {
	public ListNode reverseList(ListNode head) {
		//申请节点,pre和 cur,pre指向null
		ListNode pre = null;
		ListNode cur = head;
		ListNode tmp = null;
		while(cur!=null) {
			//记录当前节点的下一个节点
			tmp = cur.next;
			//然后将当前节点指向pre
			cur.next = pre;
			//pre和cur节点都前进一位
			pre = cur;
			cur = tmp;
		}
		return pre;
	}
}

第二种:递归

首先,我们看到这种题肯定会下意识的思考:

step1: 将头结点先移动到最后

链表之反转链表专题_第3张图片

step2: 将节点指针的顺序反过来(在这里还要注意防止循环链表的出现,所以要让head.next = null)

链表之反转链表专题_第4张图片

step3: 递归调用,返回当前的结点

class Solution {
	public ListNode reverseList(ListNode head) {
		//递归终止条件是当前为空,或者下一个节点为空
		if(head==null || head.next==null) {
			return head;
		}
		//step1:递归调用,将头结点移动到最后,这里的cur就是最后一个节点
		ListNode cur = reverseList(head.next);
        //step2:控制结点指针方向反转
		//所以head.next.next 此时的head为4的结点,head.next为5的结点,head.next.next指向head就是5->4
		head.next.next = head;
		//此时的head还是为4,如果设置这个的话,那么head.next指向的是5,此时结点4和结点5之间时双向链表,为了防止链表循环,需要将head.next设置为空
		head.next = null;
		//每层递归函数都返回cur,也就是最后一个节点
		return cur;
	}
}

Leetcode 92 反转链表

这个题就更加能让我们弄懂了

迭代的解法

class ListNode{
    int val;
    ListNode listNode;
    public ListNode(int x){
        val = x;
    }
}
public class Solution {
    public ListNode reverseBetween(ListNode head, int m, int n) {
        //初始化一个节点值为0的空节点
        ListNode dummy = new ListNode(0);
        //让该结点指向头结点
        dummy.next = head;
        //构建一个prev结点为当前空节点
        ListNode prev = dummy;
        //迭代调用,记录当前prev节点的移动
        while (m > 1) {
            prev = prev.next;
            m--;
            n--;
        }
        //结束上述while循环的条件是prev结点已经指向了要交换的结点的起始结点
        head = prev.next;
        // 这里假设第m个结点到第n个结点以5->3->4为例
        while (n > 1) {
            //next -> 3
            ListNode next = head.next;
            //将头结点下一个结点指向紧挨着头结点的下一个结点的下一个结点 比如 5->3->4 ,此时5->4
            head.next = head.next.next;
            // 3 -> 5
            next.next = prev.next;
            // 此时将第m-1个结点指向 3,这个时候相当于 head -> 3 -> 5 ->4,相当于交换了第m个和第m+1个结点的位置,再迭代,直到n为0
            prev.next = next;
            n--;
        }
        return dummy.next;
    }
}

你可能感兴趣的:(数据结构和算法,#,链表,链表,指针,java,算法)