Leetcode链表刷题二

2.链表操作相关二(反转链表,)

2.1 反转链表

/*
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
*/
public ListNode reverseList(ListNode head) {
    if(head==null||head.next==null) return head;
	ListNode dummy = new ListNode(-1);
    ListNode pre = dummy;
    dummy.next = head;
    ListNode cur = head;
    ListNode last =  cur.next;
    while(last!=null){
       cur.next = last.next;
       last.next = pre.next;
       pre.next = last;
       last = cur.next;  
    }
    return dummy.next;
}

2.2 反转链表II

/*
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表
输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]
*/
public ListNode reverseBetween(ListNode head, int left, int right) {
	 if(head==null||head.next==null) return head;
     if(left==right) return head;
     return reverseList(head,left,right);
}

public ListNode reverseList(ListNode head, int l, int r){
    ListNode dummy = new ListNode(-1);
    ListNode pre = dummy;
    dummy.next = head;
    for(int i=1;i<l;i++) pre = pre.next;
    ListNode cur = pre.next;
    ListNode last = cur.next;
    int count = 0;
    while(count<(r-l)&&last!=null){
       cur.next = last.next;
       last.next = pre.next;
       pre.next = last;
       last = cur.next; 
       count++;
    }
    return dummy.next;
}

2.3 分隔链表

/*
给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。
你应当 保留 两个分区中每个节点的初始相对位置。
*/
public ListNode partition(ListNode head, int x) {
         ListNode smallListNode = new ListNode(0);
		 ListNode largeListNode = new ListNode(0);
		 ListNode smallHead = smallListNode;
		 ListNode largeHead = largeListNode;
		 while (head!=null) {
			if(head.val<x) {
				smallHead.next = head;
				smallHead = smallHead.next;
			}else {
				largeHead.next = head;
				largeHead = largeHead.next;
			}
			head = head.next;
		}		 
		 largeHead.next = null;
		 smallHead.next = largeListNode.next;
		 
		 return smallListNode.next;
}

2.4 旋转链表

/*
给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。
输入:head = [1,2,3,4,5], k = 2
输出:[4,5,1,2,3]
*/

//解法一
public ListNode rotateRight(ListNode head, int k) {
	ListNode tmp = head;
	ListNode pre = head;
	int nodecount = 0;
	while(tmp!=null){
		nodecount++;
		tmp = tmp.next;
	}
	int val = k%nodecount;
	if(val==0) return head;
	int count = nodecount-val-1;
	while(count-->0) pre = pre.next;
	ListNode newHead = pre.next;
	pre.next = null;
	ListNode cur = newhead;
	while(cur.next!=null) cur = cur.next;
	cur.next = head;
	return newhead;
}
//解法二 闭合为环
 public ListNode rotateRight(ListNode head, int k) {
        if (k == 0 || head == null || head.next == null) {
            return head;
        }
        int n = 1;
        ListNode iter = head;
        while (iter.next != null) {
            iter = iter.next;
            n++;
        }
        int add = n - k % n;
        if (add == n) {
            return head;
        }
        iter.next = head;
        while (add-- > 0) {
            iter = iter.next;
        }
        ListNode ret = iter.next;
        iter.next = null;
        return ret;
}

2.5 重排链表

/*
给定一个单链表 L 的头节点 head ,单链表 L 表示为:
 L0 → L1 → … → Ln-1 → Ln 
请将其重新排列后变为:
L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → …
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
给定一个单链表 L 的头节点 head ,单链表 L 表示为:

 L0 → L1 → … → Ln-1 → Ln 
请将其重新排列后变为:

L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → …

不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
输入: head = [1,2,3,4]
输出: [1,4,2,3]
输入: head = [1,2,3,4,5]
输出: [1,5,2,4,3]
*/

//快慢指针+链表反转+链表操作
public void reorderList(ListNode head) {
   ListNode fast = head.next;
        ListNode slow = head;
        while(fast!=null&&fast.next!=null){
                slow = slow.next;
                fast = fast.next.next;
        }
        ListNode L2 = slow.next;
        slow.next = null;
        ListNode revL2 = Listreverse(L2);
        ListNode cur = head;
        ListNode cur2 = revL2;
        while(cur!=null&&cur2!=null){
            ListNode tmp1 = cur.next;
            ListNode tmp2 = cur2.next;
            cur.next = cur2;
            cur2.next = tmp1;
            cur = tmp1;
            cur2 = tmp2;
        }
   
}

public ListNode Listreverse(ListNode head){
	if(head==null||head.next==null) return head;
	ListNode dummy = new ListNode(-1);
	dummy.next = head;
	ListNode A = head;
	ListNode B = head.next;
	while(B!=null){
		A.next = B.next;
        B.next = dummy.next;
        dummy.next = B;
        B = A.next;
	}
	
    return dummy.next;
}

2.6 环形链表

/*
给定一个链表,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
如果链表中存在环,则返回 true 。 否则,返回 false 
*/
public boolean hasCycle(ListNode head) {
    if(head==null||head.next==null) return false; 
    ListNode slow = head;
    ListNode fast = head.next;
    while(fast!=null&&fast.next!=null){
        if(slow==fast) return true;
        slow = slow.next;
        fast = fast.next.next;
    }
    
    return false;
}

2.7 环形链表II

/*
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。
head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
*/

 public ListNode detectCycle(ListNode head) {
      if(head==null||head.next==null) return head; 
      ListNode slow = head, fast = head;
        while (fast!=null && fast.next!=null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) break;
        }
        if (fast ==null|| fast.next==null) return null;
        slow = head;
        while (slow != fast) {
            slow = slow.next;
            fast = fast.next;
        }
        return fast;
 }    
posted @ 2021-10-26 16:00  小猫妮  阅读(31)  评论(0)    收藏  举报