leetcode92. Reverse Linked List II

本文介绍了一种链表区间反转算法的实现思路及代码细节,通过定义四个辅助节点简化问题,实现了原地反转指定区间的链表节点。此外,还对比了另一种生成新链表的算法实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

某位大牛写的算法,简直五体投体,里面灵活地运用了简单逆序链表的思想,为啥我就想不到呢,真的比较笨,要多体会

【解析】

consider m,n as the cutting point ,and cut the linklist to three parts. The first  and third part is just  marked as the same of  original link list,and the second part should be reversed and we should notice to save the node in m to let it connect with the third part.

public ListNode reverseBetween(ListNode head, int m, int n) {
	ListNode dummyhead = new ListNode(0);
	dummyhead.next = head;
	ListNode sublisthead = new ListNode(0);
	ListNode sublisttail = new ListNode(0);
	int count = 1;
	ListNode pre_cur = dummyhead, cur = head;
	while(count <=n){
		ListNode temp = cur.next;
		if (count < m)
			pre_cur = cur;
		else if (count == m){
			sublisttail = cur;
			sublisthead.next = cur;
		}else if (count > m){
			cur.next = sublisthead.next;
			sublisthead.next = cur;
		}
		cur = temp;
		++count;
	}
	pre_cur.next = sublisthead.next;
	sublisttail.next = cur;
	return dummyhead.next;
}

做这个算法深刻理解了对象引用的问题,

对于listNode里面的next操作,改变的是内部的值,会有链式反应。(内部值发生改变)

对于listNode对应的整个变量操作,则不会产生链式反应。(引用发生改变)

例如:cur.next会改变head;但是cur不会改变head


对以上算法进行了修改,便于理解

public class Solution {
   public ListNode reverseBetween(ListNode head, int m, int n) {
	ListNode dummyhead = new ListNode(0);
	dummyhead.next = head;
	ListNode sublisthead = new ListNode(0);
	ListNode sublisttail = new ListNode(0);
	int count = 1;
	ListNode pre_cur = dummyhead, cur = head;
	while(count <=n){
		ListNode temp = cur.next;
		if (count < m)
			pre_cur = cur;
		else if (count == m){
			sublisttail = cur;
			sublisthead.next = sublisttail;//连接sublisttail
		}else if (count > m){
			cur.next = sublisthead.next;
			sublisthead.next = cur;
		}
		cur = temp;
		++count;
	}
	pre_cur.next = sublisthead.next;
	sublisttail.next = cur;
	return dummyhead.next;
}


 public ListNode reverseBetween(ListNode head, int m, int n) {
           ListNode dummyhead = new ListNode(0);
        dummyhead.next = head;
        ListNode sublisthead =new ListNode(0);
        ListNode sublisttail =new ListNode(0);
        int count = 1;
        ListNode pre_cur = dummyhead, cur = head;
        while(count <=n){
            ListNode temp = cur.next;
            if (count < m)
                pre_cur = cur;
            else if (count == m){
                sublisttail = cur;
//                sublisthead = cur;
            }else if (count > m){
                cur.next = sublisthead.next;
                sublisthead.next = cur;
            }
            cur = temp;
            ++count;
        }
       ListNode p=sublisthead;
        while(p.next!=null){
            p=p.next;
        }
        p.next=sublisttail;//连接sublisttail
        sublisttail.next = cur;
        pre_cur.next = sublisthead.next;
        return dummyhead.next;
    }


总结:

上述是in-place algorithm 需要四个标志:1、本身链表  2、链表的游标 3、临时链表:保存游标之后的结点  4、翻转链表:返回用,保存游标之前的结点

还有一种是重新生成一个链表的相关算法,也需要三个标志:1、本身链表:返回用 2、链表的游标  3、新建结点:创建新的结点用.

如:两数相加算法

Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8

 public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
       ListNode result=new ListNode(0);  //1
       ListNode p1=l1,p2=l2;
       ListNode r=result;                //2
       int mode=0;
       while(p1!=null||p2!=null||mode!=0){
           ListNode temp=new ListNode(0);//3
           int val=((p1==null)?0:p1.val)+((p2==null)?0:p2.val)+mode;
           temp.val=val%10;
           mode=val/10;
           r.next=temp;
           r=r.next;
           p1=(p1==null)?p1:p1.next;
           p2=(p2==null)?p2:p2.next;
       }
    //   if(mode!=0){
    //       r.next=new ListNode(mode);
    //   }
       return result.next;
    }




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值