轻松搞定链表面试题

淩亂°似流年 2022-04-12 05:21 329阅读 0赞

前言

检查链表代码是否正确的边界条件:

  1. 若链表为 null,代码是否正常运行?
  2. 若链表只有一个结点,代码是否正常运行?
  3. 若链表只有两个结点,代码是否正常运行?
  4. 代码逻辑在处理头结点和尾结点的时候,代码是否正常运行?

链表的构造及打印

  1. private static class Node {
  2. int value;
  3. Node next;
  4. Node(int value) {
  5. this.value = value;
  6. }
  7. }
  8. public static void main(String[] args) {
  9. Node head = init(1, 6);
  10. // Node head1 = init(8, 20);
  11. // display(head);
  12. // display(head);
  13. display(reverse(head));
  14. // display(mergeTwoSortList(head, head1));
  15. // display(removeInverseNode(head, 4));
  16. }
  17. public static void display(Node head) {
  18. Node p = head;
  19. while (p != null) {
  20. System.out.print(" " + p.value);
  21. p = p.next;
  22. }
  23. System.out.println();
  24. }
  25. public static Node init(int start, int exclusive) {
  26. // 设置一个哨兵节点
  27. Node head = new Node(-1);
  28. Node p = head;
  29. for (int i = start; i < exclusive; i++) {
  30. Node node = new Node(i);
  31. p.next = node;
  32. p = node;
  33. }
  34. return head.next;
  35. }

单链表逆序

  1. /** * 单链表逆序 * * @param head */
  2. public Node reverse(Node head) {
  3. Node p = head;
  4. Node prev = null;
  5. while (p != null) {
  6. Node temp = p.next;
  7. p.next = prev;
  8. prev = p;
  9. p = temp;
  10. }
  11. return prev;
  12. }

合并两个有序链表

  1. // 合并两个有序链表
  2. public static Node mergeTwoSortList(Node head1, Node head2) {
  3. if (head1 == null) {
  4. return head2;
  5. }
  6. if (head2 == null) {
  7. return head1;
  8. }
  9. // 哨兵节点
  10. Node head = new Node(-1);
  11. Node p = head;
  12. Node h1 = head1;
  13. Node h2 = head2;
  14. while (h1 != null && h2 != null) {
  15. if (h1.value < h2.value) {
  16. p.next = h1;
  17. h1 = h1.next;
  18. p = p.next;
  19. } else {
  20. p.next = h2;
  21. h2 = h2.next;
  22. p = p.next;
  23. }
  24. }
  25. if (h1 != null) {
  26. p.next = h1;
  27. }
  28. if (h2 != null) {
  29. p.next = h2;
  30. }
  31. return head.next;
  32. }

删除链表倒数第 n 个结点

声明快慢两个指针,让快指针走 n 步,再让两个指针同时后移,直到快指针到指向最后一个结点时,慢指针的下一个结点就是要删除的结点。

  1. public static Node removeInverseNode(Node head, int n) {
  2. if (head == null || n < 1) {
  3. return null;
  4. }
  5. Node p = head;
  6. Node prev = head;
  7. // 先让 p 指针走 n 步
  8. int i = 0;
  9. while (i < n) {
  10. p = p.next;
  11. if (p == null) {
  12. // 到终点了
  13. break;
  14. }
  15. i++;
  16. }
  17. // 刚好走了 n - 1 步,说明链表只有 n 个节点
  18. if (i == n - 1) {
  19. // 删除第一个节点就好
  20. return head.next;
  21. }
  22. // n 大于链表长度的情况
  23. if (p == null) {
  24. return head;
  25. }
  26. // 这个时候让 p 和 prev 一起走
  27. while (p.next != null) {
  28. p = p.next;
  29. prev = prev.next;
  30. }
  31. // p 和 prev 就是差 n 步的距离,这个时候 prev.next 正好是要被删除的节点
  32. prev.next = prev.next.next;
  33. return head;
  34. }

找出链表的中间结点

声明快慢指针,慢指针只遍历一个结点,快指针速度为 2 倍,当快指针指向链表最后一个结点,慢指针指向的即是链表的中间结点。

  1. public static Node findMiddleNode(Node head) {
  2. if (head == null) {
  3. return null;
  4. }
  5. Node prev = head;
  6. Node p = head;
  7. while (p != null && p.next != null) {
  8. p = p.next.next;
  9. prev = prev.next;
  10. }
  11. return prev;
  12. }

交换链表相邻元素

  1. public static void main(String[] args) {
  2. Node head1 = init(8, 20);
  3. display(swap(head1).next);
  4. }
  5. // 交换相邻链表元素值
  6. public static Node swap(Node head) {
  7. // 创建哨兵节点,使用哨兵节点节点会使解题容易,就不给自己找麻烦了
  8. Node node = new Node(0);
  9. node.next = head;
  10. head = node;
  11. // 初始化最初指针指向
  12. Node cur = node.next;
  13. Node prev = head;
  14. while (cur != null && cur.next != null) {
  15. // 标记除当前交换的两个节点的下一个节点
  16. Node next = cur.next.next;
  17. // 交换两个元素指针指向
  18. prev.next = cur.next;
  19. prev.next.next = cur;
  20. cur.next = next;
  21. // 重新调整指向开始下一轮循环
  22. prev = cur;
  23. cur = next;
  24. }
  25. return head;
  26. }

可参考:7把链表相邻元素翻转(交换值法、就地逆序)

链表中环的检测

参考:链表中环的检测

发表评论

表情:
评论列表 (有 0 条评论,329人围观)

还没有评论,来说两句吧...

相关阅读

    相关 轻松EasyUI

            最近在学习easyUI,顾名思义easyUI很简单,总结一下我在学习EasyUI的时候是怎么学习的,学习的时候主要从四个方面入手:         ①什么是

    相关 【C++】单表面试题

    链表是非常重要的内容,在面试时也是非常喜欢问的,下面是几个常见的面试题。 说明:这些题目中的链表都是指无头单链表。 代码的实现涉及到部分C++的语法。 typed