2.链表操作相关二(反转链表,)
/*
给你单链表的头节点 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;
}
/*
给你单链表的头指针 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;
}
/*
给你一个链表的头节点 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;
}
/*
给你一个链表的头节点 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;
}
/*
给定一个单链表 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;
}
/*
给定一个链表,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 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;
}
/*
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 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;
}