141. 环形链表
https://leetcode-cn.com/problems/linked-list-cycle/
难度简单912
给定一个链表,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
如果链表中存在环,则返回 true 。 否则,返回 false 。
进阶:
你能用 O(1)(即,常量)内存解决此问题吗?
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1
输出:false
解释:链表中没有环。
快慢双指针解法:
/*** Definition for singly-linked list.* class ListNode {* int val;* ListNode next;* ListNode(int x) {* val = x;* next = null;* }* }*/public class Solution {public boolean hasCycle(ListNode head) {if(head == null || head.next == null){return false;}ListNode slow = head;ListNode fast = head.next;while( slow != fast){if(fast == null || fast.next == null){return false;}slow = slow.next;fast = fast.next.next;}return true;}}
解法2:
public class Solution {public boolean hasCycle(ListNode head) {if(head == null || head.next == null){return false;}ListNode l1 = head;ListNode l2 = head.next;while (l2 != null && l2.next != null){if(l1.val == l2.val){return true;}l1 = l1.next;l2 = l2.next.next;}return false;}}
142. 环形链表 II
难度中等828
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。
说明:不允许修改给定的链表。
进阶:
你是否可以使用
O(1)空间解决此题?
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。
/*** 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 l1 = head,l2 = head;while(true){if(l1 == null || l1.next == null){return null;}l1 = l1.next.next;l2 = l2.next;if(l1 == l2){break;}}l1 = head;while( l1 != l2){l1 = l1.next;l2 = l2.next;}return l1;}}
写法2:
public class Solution {public ListNode detectCycle(ListNode head) {ListNode l1=head,l2=head,l3=head;boolean flag = true;while (flag){if(l2 == null || l2.next == null){return null;}l1=l1.next;l2=l2.next.next;if(l1 == l2){flag=false;}}while (l3 != l2){l3=l3.next;l2=l2.next;}return l3;}}
写法3:do while
public class Solution {public ListNode detectCycle(ListNode head) {ListNode l1=head,l2=head,l3=head;do {if(l2 == null || l2.next == null){return null;}l1=l1.next;l2=l2.next.next;}while ( l1 != l2);while (l3 != l2){l3=l3.next;l2=l2.next;}return l3;}}
206. 反转链表
https://leetcode-cn.com/problems/reverse-linked-list/
难度简单1452收藏分享切换为英文接收动态反馈
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
/*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/class Solution {public ListNode reverseList(ListNode head) {ListNode cur = head;ListNode pre = null;ListNode temp = null;while (cur != null){temp = cur.next;cur.next = pre;pre = cur;cur = temp;}return pre;}}
24. 两两交换链表中的节点
难度中等788
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:
输入:head = [1,2,3,4]
输出:[2,1,4,3]
示例 2:
输入:head = []
输出:[]
示例 3:
输入:head = [1]
输出:[1]
递归解法:
/*** 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 swapPairs(ListNode head) {//递归法if(head == null || head.next == null){return head;}ListNode next = head.next;head.next = swapPairs(next.next);next.next = head;return next;}}
迭代解法:
//给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。//// 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。//////// 示例 1://////输入:head = [1,2,3,4]//输出:[2,1,4,3]////// 示例 2://////输入:head = []//输出:[]////// 示例 3://////输入:head = [1]//输出:[1]////////// 提示:////// 链表中节点的数目在范围 [0, 100] 内// 0 <= Node.val <= 100////////// 进阶:你能在不修改链表节点值的情况下解决这个问题吗?(也就是说,仅修改节点本身。)// Related Topics 递归 链表// 👍 793 👎 0//leetcode submit region begin(Prohibit modification and deletion)/*** 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 swapPairs(ListNode head) {ListNode newNode = new ListNode(0);newNode.next = head;ListNode temp = newNode;while (temp.next != null && temp.next.next != null){ListNode l1 = temp.next;ListNode l2 = temp.next.next;temp.next = l2;l1.next = l2.next;l2.next = l1;temp = l1;}return newNode.next;}}//leetcode submit region end(Prohibit modification and deletion)
25. K 个一组翻转链表
难度困难863
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例:
给你这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
说明:
- 你的算法只能使用常数的额外空间。
- 你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
/*** 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) {if (head == null || head.next == null){return head;}//定义一个假的节点。ListNode dummy=new ListNode(0);//假节点的next指向head。// dummy->1->2->3->4->5dummy.next=head;//初始化pre和end都指向dummy。pre指每次要翻转的链表的头结点的上一个节点。end指每次要翻转的链表的尾节点ListNode pre=dummy;ListNode end=dummy;while(end.next!=null){//循环k次,找到需要翻转的链表的结尾,这里每次循环要判断end是否等于空,因为如果为空,end.next会报空指针异常。//dummy->1->2->3->4->5 若k为2,循环2次,end指向2for(int i=0;i<k&&end != null;i++){end=end.next;}//如果end==null,即需要翻转的链表的节点数小于k,不执行翻转。if(end==null){break;}//先记录下end.next,方便后面链接链表ListNode next=end.next;//然后断开链表end.next=null;//记录下要翻转链表的头节点ListNode start=pre.next;//翻转链表,pre.next指向翻转后的链表。1->2 变成2->1。 dummy->2->1pre.next=reverse(start);//翻转后头节点变到最后。通过.next把断开的链表重新链接。start.next=next;//将pre换成下次要翻转的链表的头结点的上一个节点。即startpre=start;//翻转结束,将end置为下次要翻转的链表的头结点的上一个节点。即startend=start;}return dummy.next;}//链表翻转// 例子: head: 1->2->3->4public ListNode reverse(ListNode head) {//单链表为空或只有一个节点,直接返回原单链表if (head == null || head.next == null){return head;}//前一个节点指针ListNode preNode = null;//当前节点指针ListNode curNode = head;//下一个节点指针ListNode nextNode = null;while (curNode != null){nextNode = curNode.next;//nextNode 指向下一个节点,保存当前节点后面的链表。curNode.next=preNode;//将当前节点next域指向前一个节点 null<-1<-2<-3<-4preNode = curNode;//preNode 指针向后移动。preNode指向当前节点。curNode = nextNode;//curNode指针向后移动。下一个节点变成当前节点}return preNode;}}
21. 合并两个有序链表
难度简单1494
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例 1:
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
示例 2:
输入:l1 = [], l2 = []
输出:[]
示例 3:
输入:l1 = [], l2 = [0]
输出:[0]
/*** 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 mergeTwoLists(ListNode l1, ListNode l2) {if(l1==null) return l2;if(l2==null) return l1;int v1 = l1.val;int v2 = l2.val;if(v1<v2){l1.next = mergeTwoLists(l1.next,l2);return l1;}else{l2.next = mergeTwoLists(l1,l2.next);return l2;}}}
