剑指 Offer 06. 从尾到头打印链表

输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)

image.png
image.png

  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 int[] reversePrint(ListNode head) {
  11. if(head == null) return new int[]{};
  12. ListNode cur = head;
  13. int size = 0;
  14. while(cur != null){
  15. size++;
  16. cur = cur.next;
  17. }
  18. cur = head;
  19. int[] res = new int[size];
  20. for(int i = size - 1; i >= 0; i--){
  21. res[i] = cur.val;
  22. cur = cur.next;
  23. }
  24. return res;
  25. }
  26. }

image.png

  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 int[] reversePrint(ListNode head) {
  11. LinkedList<Integer> stack = new LinkedList<>();
  12. ListNode cur = head;
  13. while(cur != null){
  14. stack.push(cur.val);
  15. cur = cur.next;
  16. }
  17. int[] res = new int[stack.size()];
  18. int index = 0;
  19. while(!stack.isEmpty()){
  20. res[index++] = stack.pop();
  21. }
  22. return res;
  23. }
  24. }

剑指 Offer 18. 删除链表的节点

image.png

  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 deleteNode(ListNode head, int val) {
  11. ListNode domp = new ListNode(-1);
  12. domp.next = head;
  13. ListNode tem = domp;
  14. while(tem.next != null){
  15. if(tem.next.val == val){
  16. tem.next = tem.next.next;
  17. break;
  18. }
  19. tem = tem.next;
  20. }
  21. return domp.next;
  22. }
  23. }

剑指 Offer 22. 链表中倒数第k个节点

输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。 例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。 示例: 给定一个链表: 1->2->3->4->5, 和 k = 2. 返回链表 4->5.

image.png
image.png
image.png

image.png

  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 getKthFromEnd(ListNode head, int k) {
  11. ListNode fir = head;
  12. ListNode sec = head;
  13. for(int i = 0; i < k; i++){
  14. fir = fir.next;
  15. }
  16. while(fir != null){
  17. fir = fir.next;
  18. sec = sec.next;
  19. }
  20. return sec;
  21. }
  22. }

剑指 Offer 24. 反转链表

双指针法

剑指offer--链表相关 - 图10
image.png
image.png

  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 pre = null;
  12. ListNode cur = head;
  13. while(cur != null){
  14. ListNode next = cur.next;
  15. cur.next = pre;
  16. pre = cur;
  17. cur = next;
  18. }
  19. return pre;
  20. }
  21. }

image.png
image.png

  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 reverseList(ListNode head){
  13. //if(head == null) return null;
  14. return reverse(null,head);
  15. }
  16. public ListNode reverse(ListNode pre,ListNode cur) {
  17. if(cur == null) return pre;
  18. ListNode temp = cur.next;
  19. cur.next = pre;
  20. return reverse(cur,temp);
  21. }
  22. }

剑指 Offer 25. 合并两个排序的链表

image.png

  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 mergeTwoLists(ListNode l1, ListNode l2) {
  11. ListNode pom = new ListNode(0);
  12. ListNode cur = pom;
  13. while(l1 != null && l2 != null){
  14. if(l1.val < l2.val){
  15. cur.next =l1;
  16. l1 = l1.next;
  17. }else{
  18. cur.next = l2;
  19. l2 = l2.next;
  20. }
  21. cur = cur.next;
  22. }
  23. cur.next = l1 != null ? l1 : l2;
  24. return pom.next;
  25. }
  26. }

剑指 Offer 35. 复杂链表的复制

请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。

image.png
image.png
image.png
image.png

  1. /*
  2. // Definition for a Node.
  3. class Node {
  4. int val;
  5. Node next;
  6. Node random;
  7. public Node(int val) {
  8. this.val = val;
  9. this.next = null;
  10. this.random = null;
  11. }
  12. }
  13. */
  14. class Solution {
  15. public Node copyRandomList(Node head) {
  16. if(head == null) return null;
  17. //1.复制节点
  18. Node cur = head;
  19. while(cur != null){
  20. Node copy = new Node(cur.val);
  21. copy.next = cur.next;
  22. cur.next = copy;
  23. cur = cur.next.next;
  24. }
  25. //2.复制random节点
  26. cur = head;
  27. while(cur != null){
  28. if(cur.random != null){
  29. cur.next.random = cur.random.next;
  30. }
  31. cur = cur.next.next;
  32. }
  33. //3.分开链表
  34. Node dummy = new Node(-1);
  35. Node help = dummy;
  36. cur = head;
  37. while(cur != null){
  38. help.next = cur.next;
  39. help = help.next;
  40. cur.next = cur.next.next;
  41. cur = cur.next;
  42. }
  43. return dummy.next;
  44. }
  45. }

剑指 Offer 52. 两个链表的第一个公共节点

输入两个链表,找出它们的第一个公共节点。

image.png
image.png
image.png

  1. /**
  2. * Definition for singly-linked list.
  3. * public 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 getIntersectionNode(ListNode headA, ListNode headB) {
  14. ListNode idxA = headA;
  15. ListNode idxB = headB;
  16. while(idxA != idxB){
  17. if(idxA == null){
  18. idxA =headB;
  19. }else{
  20. idxA = idxA.next;
  21. }
  22. if(idxB == null){
  23. idxB = headA;
  24. }else{
  25. idxB = idxB.next;
  26. }
  27. }
  28. return idxA;
  29. }
  30. }

707. 设计链表

image.png
image.png
image.png

  1. public class ListNode {
  2. int val;
  3. ListNode next;
  4. ListNode(int x) { val = x; }
  5. };
  6. class MyLinkedList {
  7. int length;
  8. ListNode head;
  9. /** 初始化构造器*/
  10. public MyLinkedList() {
  11. this.head=new ListNode(0);
  12. this.length=0;
  13. }
  14. /**获取索引值对应的节点值 */
  15. public int get(int index) {
  16. if(index<0||index>=length) return -1;
  17. ListNode p = head;
  18. for(int i=0;i<=index;i++) {//index=0,对应第1个节点,第一个节点即为head.next
  19. p=p.next;
  20. }
  21. return p.val;
  22. }
  23. /**在链表头添加节点 */
  24. public void addAtHead(int val) {
  25. ListNode first=new ListNode(val);
  26. first.next=head.next;
  27. head.next=first;
  28. length++;
  29. //addAtIndex(0,val);
  30. }
  31. /** 在链表尾部添加节点 */
  32. public void addAtTail(int val) {
  33. ListNode p=head;
  34. while(p.next!=null){
  35. p=p.next;
  36. }
  37. p.next=new ListNode(val);
  38. length++;
  39. }
  40. /**在索引值为index的节点之前插入节点 */
  41. public void addAtIndex(int index, int val) {
  42. if(index < 0) index = 0;//addAtHead(val); return;
  43. if(index > length) return;
  44. /*if(index==length) { addAtTail(val); return; }*/
  45. length++;
  46. ListNode pre = head;
  47. for(int i = 0;i < index; i++){
  48. pre = pre.next;
  49. }
  50. ListNode temp=new ListNode(val);
  51. temp.next=pre.next;
  52. pre.next=temp;
  53. }
  54. /** 如果索引 index 有效,则删除链表索引值为 index的节点。 */
  55. public void deleteAtIndex(int index) {
  56. if(index < 0 || index >= length) return;
  57. length--;
  58. ListNode pre=head;
  59. for(int i = 0; i < index; i++) {
  60. pre = pre.next;
  61. }
  62. pre.next = pre.next.next;
  63. }
  64. }

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

给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。

image.png
image.png

  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. if(head == null || head.next == null) return head;
  14. //获取当前节点的下一个节点
  15. ListNode next = head.next;
  16. //进行递归
  17. ListNode newNode = swapPairs(next.next);
  18. //进行交换
  19. next.next = head;
  20. head.next = newNode;
  21. return next;
  22. }
  23. }

image.png

  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. ListNode dummyNode = new ListNode(0);
  14. dummyNode.next = head;
  15. ListNode prev = dummyNode;
  16. while(prev.next != null && prev.next.next != null){
  17. ListNode temp = head.next.next; //缓存next
  18. prev.next = head.next; //将prev 的 next 改为 head 的next
  19. head.next.next = head; //将head.next(prev.next) 的next 指向 head
  20. head.next = temp; //将 head 的 next 接上缓存的temp
  21. prev = head; //步进1位
  22. head = head.next; //步进1位
  23. }
  24. return dummyNode.next;
  25. }
  26. }

141. 环形链表

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

image.png

  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) return false;
  15. ListNode slow = head;
  16. ListNode fast = head;
  17. while(fast != null && fast.next != null){
  18. fast = fast.next.next;
  19. slow = slow.next;
  20. if(slow == fast) return true;
  21. }
  22. return false;
  23. }
  24. }

142. 环形链表 II

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

image.png
image.png
image.png

  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 fast = head;
  15. ListNode slow = head;
  16. while(fast != null && fast.next != null){
  17. slow = slow.next;
  18. fast = fast.next.next;
  19. //块慢指针相遇 从head和相遇点,同时查找直到相遇
  20. if(slow == fast){
  21. ListNode index1 = fast;
  22. ListNode index2 = head;
  23. while(index1 != index2){
  24. index1 = index1.next;
  25. index2 = index2.next;
  26. }
  27. return index2;//返回环的入口
  28. }
  29. }
  30. return null;
  31. }
  32. }

83. 删除排序链表中的重复元素

image.png
image.png
image.png

  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 deleteDuplicates(ListNode head) {
  13. if(head == null || head.next == null) return head;
  14. head.next = deleteDuplicates(head.next);
  15. return head.val == head.next.val ? head.next : head;
  16. }
  17. }

image.png

  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 deleteDuplicates(ListNode head) {
  13. ListNode current = head;
  14. while(current != null && current.next != null){
  15. if(current.val == current.next.val){
  16. current.next = current.next.next;
  17. }else{
  18. current = current.next;
  19. }
  20. }
  21. return head;
  22. }
  23. }

234. 回文链表

image.png
image.png
image.png

  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 boolean isPalindrome(ListNode head) {
  11. List<Integer> list = new ArrayList<>();
  12. ListNode current = head;
  13. while(current != null){
  14. list.add(current.val);
  15. current = current.next;
  16. }
  17. int first = 0;
  18. int last = list.size()-1;
  19. while(first < last){
  20. if(!list.get(first).equals(list.get(last))){
  21. return false;
  22. }
  23. first++;
  24. last--;
  25. }
  26. return true;
  27. }
  28. }

image.png

image.png
image.png
image.png

  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 boolean isPalindrome(ListNode head) {
  13. if (head == null) {
  14. return true;
  15. }
  16. // 找到前半部分链表的尾节点并反转后半部分链表
  17. ListNode firstHalfEnd = endOfFirstHalf(head);
  18. ListNode secondHalfStart = reverseList(firstHalfEnd.next);
  19. // 判断是否回文
  20. ListNode p1 = head;
  21. ListNode p2 = secondHalfStart;
  22. boolean result = true;
  23. while (result && p2 != null) {
  24. if (p1.val != p2.val) {
  25. result = false;
  26. }
  27. p1 = p1.next;
  28. p2 = p2.next;
  29. }
  30. // 还原链表并返回结果
  31. firstHalfEnd.next = reverseList(secondHalfStart);
  32. return result;
  33. }
  34. private ListNode reverseList(ListNode head) {
  35. ListNode prev = null;
  36. ListNode curr = head;
  37. while (curr != null) {
  38. ListNode nextTemp = curr.next;
  39. curr.next = prev;
  40. prev = curr;
  41. curr = nextTemp;
  42. }
  43. return prev;
  44. }
  45. private ListNode endOfFirstHalf(ListNode head) {
  46. ListNode fast = head;
  47. ListNode slow = head;
  48. while (fast.next != null && fast.next.next != null) {
  49. fast = fast.next.next;
  50. slow = slow.next;
  51. }
  52. return slow;
  53. }
  54. }

92. 反转链表 II

给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。

image.pngimage.png

image.png

82. 删除排序链表中的重复元素 II

存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除链表中所有存在数字重复情况的节点,只保留原始链表中 没有重复出现 的数字。 返回同样按升序排列的结果链表。

image.png
image.png
image.png

  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 deleteDuplicates(ListNode head) {
  13. if (head == null) {
  14. return head;
  15. }
  16. ListNode dummy = new ListNode(0, head);
  17. ListNode cur = dummy;
  18. while (cur.next != null && cur.next.next != null) {
  19. if (cur.next.val == cur.next.next.val) {
  20. int x = cur.next.val;
  21. while (cur.next != null && cur.next.val == x) {
  22. cur.next = cur.next.next;
  23. }
  24. } else {
  25. cur = cur.next;
  26. }
  27. }
  28. return dummy.next;
  29. }
  30. }

划分链表

image.png
image.png
image.png