链表linkedlist系列

206. Reverse Linked List
Easy

Given the head of a singly linked list, reverse the list, and return the reversed list.

Example 1:

Input: head = [1,2,3,4,5]
Output: [5,4,3,2,1]

Example 2:

Input: head = [1,2]
Output: [2,1]

Example 3:

Input: head = []
Output: []

Constraints:

  • The number of nodes in the list is the range [0, 5000].
  • -5000 <= Node.val <= 5000
复制代码
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode front = null;
        ListNode back = head;
        while(back!=null){
            head = back.next;
            back.next=front;
            front=back;
            back=head;
        }
        return front;
    }
}
复制代码
复制代码
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode pre = new ListNode(1);
        while(head!=null){
            ListNode t = pre.next;
            pre.next=head;
            head=head.next;
            pre.next.next=t;
        }
        return pre.next;
    }
}
复制代码

 

92. Reverse Linked List II
Medium

Given the head of a singly linked list and two integers left and right where left <= right, reverse the nodes of the list from position left to position right, and return the reversed list.

Example 1:

Input: head = [1,2,3,4,5], left = 2, right = 4
Output: [1,4,3,2,5]

Example 2:

Input: head = [5], left = 1, right = 1
Output: [5] 

Constraints:

  • The number of nodes in the list is n.
  • 1 <= n <= 500
  • -500 <= Node.val <= 500
  • 1 <= left <= right <= n
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseBetween(ListNode head, int l, int r) {
        ListNode pre = new ListNode(0);
        pre.next = head;
        ListNode leftpre = pre,rightpre=pre;
        //leftpre指向left的前一个
        for(int i=1;i<l;i++)  leftpre=leftpre.next;
        //rightpre指向right当前,记住这里是当前,不是前一个!
        for(int i=1;i<=r;i++) rightpre=rightpre.next;
        //left指向要反转的第一个node
        ListNode left=leftpre.next;
        //right指向第一个不反转的node
        ListNode right = rightpre.next;
        //防止死循环
        rightpre.next=null;
        //反转前的第一个为反转后的最后一个
        ListNode lefttail = left;
        //进行反转,并将反转结果对接leftpre
        leftpre.next = reverse(left);
        //对接反转自后一个与未反转部分
        lefttail.next=right;
        return pre.next;
    }
    //简单的链表反转过程
    public ListNode reverse(ListNode head){
        ListNode pre = new ListNode(0);
        while(head!=null){
            ListNode temp=pre.next;
            pre.next=head;
            head=head.next;
            pre.next.next=temp;
        }
        return pre.next;
    }
}

 

25. Reverse Nodes in k-Group
Hard

Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.

k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes, in the end, should remain as it is.

You may not alter the values in the list's nodes, only nodes themselves may be changed.

Example 1:

Input: head = [1,2,3,4,5], k = 2
Output: [2,1,4,3,5]

Example 2:

Input: head = [1,2,3,4,5], k = 3
Output: [3,2,1,4,5]

Example 3:

Input: head = [1,2,3,4,5], k = 1
Output: [1,2,3,4,5]

Example 4:

Input: head = [1], k = 1
Output: [1] 

Constraints:

  • The number of nodes in the list is in the range sz.
  • 1 <= sz <= 5000
  • 0 <= Node.val <= 1000
  • 1 <= k <= sz
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode node = head;
        //1.找到第k+1个点的位置
        for(int i=0;i<k;i++) {
            if(node==null) return head;//如果不够k个点不需要反转
            node = node.next;
        }
        //对前k个点进行反转,反转后产生newHead,之前的head指向k个元素的末尾,下一步递归调用要用到
        ListNode newHead = reverse(head,k);
        //递归调用进行下一组k个元素的反转
        head.next = reverseKGroup(node,k);
        return newHead;
    }
    //用于反转一个数组的前k个元素
    private ListNode reverse(ListNode head, int k){
        ListNode pre = null,curr=head;
        for(int i=0;i<k;i++){
            ListNode next = curr.next;
            curr.next = pre;
            pre=curr;
            curr=next;
        }
        return pre;
    }
}

 2074. Reverse Nodes in Even Length Groups

Medium

You are given the head of a linked list.

The nodes in the linked list are sequentially assigned to non-empty groups whose lengths form the sequence of the natural numbers (1, 2, 3, 4, ...). The length of a group is the number of nodes assigned to it. In other words,

  • The 1st node is assigned to the first group.
  • The 2nd and the 3rd nodes are assigned to the second group.
  • The 4th5th, and 6th nodes are assigned to the third group, and so on.

Note that the length of the last group may be less than or equal to 1 + the length of the second to last group.

Reverse the nodes in each group with an even length, and return the head of the modified linked list.

 

Example 1:

Input: head = [5,2,6,3,9,1,7,3,8,4]
Output: [5,6,2,3,9,1,4,8,3,7]
Explanation:
- The length of the first group is 1, which is odd, hence no reversal occurrs.
- The length of the second group is 2, which is even, hence the nodes are reversed.
- The length of the third group is 3, which is odd, hence no reversal occurrs.
- The length of the last group is 4, which is even, hence the nodes are reversed.

Example 2:

Input: head = [1,1,0,6]
Output: [1,0,1,6]
Explanation:
- The length of the first group is 1. No reversal occurrs.
- The length of the second group is 2. The nodes are reversed.
- The length of the last group is 1. No reversal occurrs.

Example 3:

Input: head = [1,1,0,6,5]
Output: [1,0,1,5,6]
Explanation:
- The length of the first group is 1. No reversal occurrs.
- The length of the second group is 2. The nodes are reversed.
- The length of the last group is 2. The nodes are reversed.

Example 4:

Input: head = [2,1]
Output: [2,1]
Explanation:
- The length of the first group is 1. No reversal occurrs.
- The length of the last group is 1. No reversal occurrs.

Example 5:

Input: head = [8]
Output: [8]
Explanation: There is only one group whose length is 1. No reversal occurrs. 

Constraints:

  • The number of nodes in the list is in the range [1, 105].
  • 0 <= Node.val <= 105
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseEvenLengthGroups(ListNode head) {
        if(head==null) return null;        
        return reverseK(head,1,countList(head));
    }
    private int countList(ListNode head){
        int count = 0;
        while(head!=null) {
            head=head.next;
            count++;
        }
        return count;
    }
    private ListNode reverseK(ListNode head,int k,int remain){
        if(head==null) return null;
        ListNode node = head;
        if((remain>=k && k%2==0) || (remain<k && remain%2==0)){ //坑点:剩余不够k的情况下,要以剩余的节点数量来判定是否要反转
            for(int i=0;i<k&&node!=null;i++) //要反转的情况下,直接将node指向下一轮反转的第一个点
                node=node.next;
            ListNode newHead = reverse(head,Math.min(k,remain));
            head.next = reverseK(node,k+1,remain-k);
            return newHead;
        }
        else{
            for(int i=0;i<k-1 && node!=null&&node.next!=null;i++) //不反转的情况下,直接将node指向本轮反转的最后一个点,因为要与下一轮反转衔接
                node=node.next;
            node.next = reverseK(node.next,k+1,remain-k);
            return head;
        }
    }
    private ListNode reverse(ListNode head,int k){
        ListNode pre = null,curr=head;
        for(int i=0;i<k;i++){
            if(curr==null) return pre;
            ListNode next = curr.next;
            curr.next = pre;
            pre=curr;
            curr=next;
        }
        return pre;
    }
}

 

287. Find the Duplicate Number
Medium

Given an array of integers nums containing n + 1 integers where each integer is in the range [1, n] inclusive.

There is only one repeated number in nums, return this repeated number.

You must solve the problem without modifying the array nums and uses only constant extra space.

Example 1:

Input: nums = [1,3,4,2,2]
Output: 2

Example 2:

Input: nums = [3,1,3,4,2]
Output: 3

Example 3:

Input: nums = [1,1]
Output: 1

Example 4:

Input: nums = [1,1,2]
Output: 1

Constraints:

  • 1 <= n <= 105
  • nums.length == n + 1
  • 1 <= nums[i] <= n
  • All the integers in nums appear only once except for precisely one integer which appears two or more times. 

Follow up:

  • How can we prove that at least one duplicate number must exist in nums?
  • Can you solve the problem in linear runtime complexity?
class Solution {
    public int findDuplicate(int[] nums) {
        //1.快慢指针赛跑,快指针speed=2*慢指针speed
        int slow = nums[0];
        int fast = nums[0];
        do{
            slow=nums[slow];
            fast=nums[nums[fast]];
        } while(slow!=fast);
        //2.快慢指针相遇后,第3个指针从开头与慢指针以相同速度跑,相遇点即为相交点
        int temp = nums[0];
        while(temp!=slow){
            slow=nums[slow];
            temp=nums[temp];
        }
        return temp;
    }
}

 

class Solution {
    public int findDuplicate(int[] nums) {
        for(int i=0;i<nums.length;i++){
            int index = Math.abs(nums[i])-1;
            if(nums[index]<0) return index+1;
            nums[index]=-1*nums[index];
        }
        return -1;
    }
}

 

142. Linked List Cycle II
Medium

Given the head of a linked list, return the node where the cycle begins. If there is no cycle, return null.

There is a cycle in a linked list if there is some node in the list that can be reached again by continuously following the next pointer. Internally, pos is used to denote the index of the node that tail's next pointer is connected to (0-indexed). It is -1 if there is no cycle. Note that pos is not passed as a parameter.

Do not modify the linked list.

Example 1:

Input: head = [3,2,0,-4], pos = 1
Output: tail connects to node index 1
Explanation: There is a cycle in the linked list, where tail connects to the second node.

Example 2:

Input: head = [1,2], pos = 0
Output: tail connects to node index 0
Explanation: There is a cycle in the linked list, where tail connects to the first node.

Example 3:

Input: head = [1], pos = -1
Output: no cycle
Explanation: There is no cycle in the linked list. 

Constraints:

  • The number of the nodes in the list is in the range [0, 104].
  • -105 <= Node.val <= 105
  • pos is -1 or a valid index in the linked-list.

Follow up: Can you solve it using O(1) (i.e. constant) memory?

通过fast 和 slow 移动直到相遇,我们可以知道fast和slow分别走了距离 fast_d 和 slow_d

而fast_d = 2 * slow_d.

假设环的起始点在s, fast和slow相遇点在x.

fast_d 在下图中即为: a+b+c+b,  slow_d 在下图中即为:a+b

最终可以得出:a=c

那么fast和slow在x点相遇后,让fast回到原点,以与slow相同的速度继续走,最终它们就会在s点相遇

 

 

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode slow = head,fast=head;
        //快指针以2倍速度与慢指针赛跑
        while(fast!=null && fast.next!=null){
            slow = slow.next;
            fast=fast.next.next;
            //快慢指针相遇
            if(slow==fast){
                //相遇后使用第3根指针与slow指针同样速度行进
                ListNode start = head;
                int ind=0;
                while(slow!=start){
                    slow=slow.next;
                    start=start.next;
                }
                return start;
            }
        }
        return null;
    }
}

 

 

posted @ 2021-11-24 11:46  xiaoyongyong  阅读(43)  评论(0)    收藏  举报