141. 环形链表

https://leetcode-cn.com/problems/linked-list-cycle/

难度简单912
给定一个链表,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos-1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
如果链表中存在环,则返回 true 。 否则,返回 false

进阶:
你能用 O(1)(即,常量)内存解决此问题吗?

示例 1:
2、链表 - 图1
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:
2、链表 - 图2
输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:
2、链表 - 图3
输入:head = [1], pos = -1
输出:false
解释:链表中没有环。

快慢双指针解法:

  1. /**
  2. * Definition for singly-linked list.
  3. * class ListNode {
  4. * int val;
  5. * ListNode next;
  6. * ListNode(int x) {
  7. * val = x;
  8. * next = null;
  9. * }
  10. * }
  11. */
  12. public class Solution {
  13. public boolean hasCycle(ListNode head) {
  14. if(head == null || head.next == null){
  15. return false;
  16. }
  17. ListNode slow = head;
  18. ListNode fast = head.next;
  19. while( slow != fast){
  20. if(fast == null || fast.next == null){
  21. return false;
  22. }
  23. slow = slow.next;
  24. fast = fast.next.next;
  25. }
  26. return true;
  27. }
  28. }

解法2:

  1. public class Solution {
  2. public boolean hasCycle(ListNode head) {
  3. if(head == null || head.next == null){
  4. return false;
  5. }
  6. ListNode l1 = head;
  7. ListNode l2 = head.next;
  8. while (l2 != null && l2.next != null){
  9. if(l1.val == l2.val){
  10. return true;
  11. }
  12. l1 = l1.next;
  13. l2 = l2.next.next;
  14. }
  15. return false;
  16. }
  17. }

142. 环形链表 II

难度中等828
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos-1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。
说明:不允许修改给定的链表。
进阶:

  • 你是否可以使用 O(1) 空间解决此题?


    示例 1:
    2、链表 - 图4
    输入:head = [3,2,0,-4], pos = 1
    输出:返回索引为 1 的链表节点
    解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:
2、链表 - 图5
输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:
2、链表 - 图6
输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。

  1. /**
  2. * Definition for singly-linked list.
  3. * class ListNode {
  4. * int val;
  5. * ListNode next;
  6. * ListNode(int x) {
  7. * val = x;
  8. * next = null;
  9. * }
  10. * }
  11. */
  12. public class Solution {
  13. public ListNode detectCycle(ListNode head) {
  14. ListNode l1 = head,l2 = head;
  15. while(true){
  16. if(l1 == null || l1.next == null){
  17. return null;
  18. }
  19. l1 = l1.next.next;
  20. l2 = l2.next;
  21. if(l1 == l2){
  22. break;
  23. }
  24. }
  25. l1 = head;
  26. while( l1 != l2){
  27. l1 = l1.next;
  28. l2 = l2.next;
  29. }
  30. return l1;
  31. }
  32. }

写法2:

  1. public class Solution {
  2. public ListNode detectCycle(ListNode head) {
  3. ListNode l1=head,l2=head,l3=head;
  4. boolean flag = true;
  5. while (flag){
  6. if(l2 == null || l2.next == null){
  7. return null;
  8. }
  9. l1=l1.next;
  10. l2=l2.next.next;
  11. if(l1 == l2){
  12. flag=false;
  13. }
  14. }
  15. while (l3 != l2){
  16. l3=l3.next;
  17. l2=l2.next;
  18. }
  19. return l3;
  20. }
  21. }

写法3:do while

  1. public class Solution {
  2. public ListNode detectCycle(ListNode head) {
  3. ListNode l1=head,l2=head,l3=head;
  4. do {
  5. if(l2 == null || l2.next == null){
  6. return null;
  7. }
  8. l1=l1.next;
  9. l2=l2.next.next;
  10. }while ( l1 != l2);
  11. while (l3 != l2){
  12. l3=l3.next;
  13. l2=l2.next;
  14. }
  15. return l3;
  16. }
  17. }

206. 反转链表

https://leetcode-cn.com/problems/reverse-linked-list/

难度简单1452收藏分享切换为英文接收动态反馈
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

  1. /**
  2. * Definition for singly-linked list.
  3. * public class ListNode {
  4. * int val;
  5. * ListNode next;
  6. * ListNode(int x) { val = x; }
  7. * }
  8. */
  9. class Solution {
  10. public ListNode reverseList(ListNode head) {
  11. ListNode cur = head;
  12. ListNode pre = null;
  13. ListNode temp = null;
  14. while (cur != null){
  15. temp = cur.next;
  16. cur.next = pre;
  17. pre = cur;
  18. cur = temp;
  19. }
  20. return pre;
  21. }
  22. }

24. 两两交换链表中的节点

难度中等788
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

示例 1:
2、链表 - 图7
输入:head = [1,2,3,4]
输出:[2,1,4,3]

示例 2:
输入:head = []
输出:[]

示例 3:
输入:head = [1]
输出:[1]

递归解法:

  1. /**
  2. * Definition for singly-linked list.
  3. * public class ListNode {
  4. * int val;
  5. * ListNode next;
  6. * ListNode() {}
  7. * ListNode(int val) { this.val = val; }
  8. * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
  9. * }
  10. */
  11. class Solution {
  12. public ListNode swapPairs(ListNode head) {
  13. //递归法
  14. if(head == null || head.next == null){
  15. return head;
  16. }
  17. ListNode next = head.next;
  18. head.next = swapPairs(next.next);
  19. next.next = head;
  20. return next;
  21. }
  22. }

迭代解法:

  1. //给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
  2. //
  3. // 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
  4. //
  5. //
  6. //
  7. // 示例 1:
  8. //
  9. //
  10. //输入:head = [1,2,3,4]
  11. //输出:[2,1,4,3]
  12. //
  13. //
  14. // 示例 2:
  15. //
  16. //
  17. //输入:head = []
  18. //输出:[]
  19. //
  20. //
  21. // 示例 3:
  22. //
  23. //
  24. //输入:head = [1]
  25. //输出:[1]
  26. //
  27. //
  28. //
  29. //
  30. // 提示:
  31. //
  32. //
  33. // 链表中节点的数目在范围 [0, 100] 内
  34. // 0 <= Node.val <= 100
  35. //
  36. //
  37. //
  38. //
  39. // 进阶:你能在不修改链表节点值的情况下解决这个问题吗?(也就是说,仅修改节点本身。)
  40. // Related Topics 递归 链表
  41. // 👍 793 👎 0
  42. //leetcode submit region begin(Prohibit modification and deletion)
  43. /**
  44. * Definition for singly-linked list.
  45. * public class ListNode {
  46. * int val;
  47. * ListNode next;
  48. * ListNode() {}
  49. * ListNode(int val) { this.val = val; }
  50. * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
  51. * }
  52. */
  53. class Solution {
  54. public ListNode swapPairs(ListNode head) {
  55. ListNode newNode = new ListNode(0);
  56. newNode.next = head;
  57. ListNode temp = newNode;
  58. while (temp.next != null && temp.next.next != null){
  59. ListNode l1 = temp.next;
  60. ListNode l2 = temp.next.next;
  61. temp.next = l2;
  62. l1.next = l2.next;
  63. l2.next = l1;
  64. temp = l1;
  65. }
  66. return newNode.next;
  67. }
  68. }
  69. //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

说明:

  • 你的算法只能使用常数的额外空间。
  • 你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
  1. /**
  2. * Definition for singly-linked list.
  3. * public class ListNode {
  4. * int val;
  5. * ListNode next;
  6. * ListNode() {}
  7. * ListNode(int val) { this.val = val; }
  8. * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
  9. * }
  10. */
  11. class Solution {
  12. public ListNode reverseKGroup(ListNode head, int k) {
  13. if (head == null || head.next == null){
  14. return head;
  15. }
  16. //定义一个假的节点。
  17. ListNode dummy=new ListNode(0);
  18. //假节点的next指向head。
  19. // dummy->1->2->3->4->5
  20. dummy.next=head;
  21. //初始化pre和end都指向dummy。pre指每次要翻转的链表的头结点的上一个节点。end指每次要翻转的链表的尾节点
  22. ListNode pre=dummy;
  23. ListNode end=dummy;
  24. while(end.next!=null){
  25. //循环k次,找到需要翻转的链表的结尾,这里每次循环要判断end是否等于空,因为如果为空,end.next会报空指针异常。
  26. //dummy->1->2->3->4->5 若k为2,循环2次,end指向2
  27. for(int i=0;i<k&&end != null;i++){
  28. end=end.next;
  29. }
  30. //如果end==null,即需要翻转的链表的节点数小于k,不执行翻转。
  31. if(end==null){
  32. break;
  33. }
  34. //先记录下end.next,方便后面链接链表
  35. ListNode next=end.next;
  36. //然后断开链表
  37. end.next=null;
  38. //记录下要翻转链表的头节点
  39. ListNode start=pre.next;
  40. //翻转链表,pre.next指向翻转后的链表。1->2 变成2->1。 dummy->2->1
  41. pre.next=reverse(start);
  42. //翻转后头节点变到最后。通过.next把断开的链表重新链接。
  43. start.next=next;
  44. //将pre换成下次要翻转的链表的头结点的上一个节点。即start
  45. pre=start;
  46. //翻转结束,将end置为下次要翻转的链表的头结点的上一个节点。即start
  47. end=start;
  48. }
  49. return dummy.next;
  50. }
  51. //链表翻转
  52. // 例子: head: 1->2->3->4
  53. public ListNode reverse(ListNode head) {
  54. //单链表为空或只有一个节点,直接返回原单链表
  55. if (head == null || head.next == null){
  56. return head;
  57. }
  58. //前一个节点指针
  59. ListNode preNode = null;
  60. //当前节点指针
  61. ListNode curNode = head;
  62. //下一个节点指针
  63. ListNode nextNode = null;
  64. while (curNode != null){
  65. nextNode = curNode.next;//nextNode 指向下一个节点,保存当前节点后面的链表。
  66. curNode.next=preNode;//将当前节点next域指向前一个节点 null<-1<-2<-3<-4
  67. preNode = curNode;//preNode 指针向后移动。preNode指向当前节点。
  68. curNode = nextNode;//curNode指针向后移动。下一个节点变成当前节点
  69. }
  70. return preNode;
  71. }
  72. }

21. 合并两个有序链表

难度简单1494
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例 1:
2、链表 - 图8
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

示例 2:
输入:l1 = [], l2 = []
输出:[]

示例 3:
输入:l1 = [], l2 = [0]
输出:[0]

  1. /**
  2. * Definition for singly-linked list.
  3. * public class ListNode {
  4. * int val;
  5. * ListNode next;
  6. * ListNode() {}
  7. * ListNode(int val) { this.val = val; }
  8. * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
  9. * }
  10. */
  11. class Solution {
  12. public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
  13. if(l1==null) return l2;
  14. if(l2==null) return l1;
  15. int v1 = l1.val;
  16. int v2 = l2.val;
  17. if(v1<v2){
  18. l1.next = mergeTwoLists(l1.next,l2);
  19. return l1;
  20. }else{
  21. l2.next = mergeTwoLists(l1,l2.next);
  22. return l2;
  23. }
  24. }
  25. }