当前位置:   article > 正文

链表的常见面试题_链表面试题

链表面试题

先说下一个节点的结构:一个val域和一个next域

  1. public class ListNode {
  2. int val;
  3. ListNode next = null;
  4. public ListNode(int val) {
  5. this.val = val;
  6. }
  7. }

一、已知链表的头节点,将链表进行逆序。(不可以申请额外的空间)

  1. public static ListNode reverseList(ListNode node) {
  2. ListNode pre = null;
  3. ListNode pNext = null;
  4. while(node != null) {
  5. pNext = node.next;
  6. node.next = pre;
  7. pre = node;
  8. node = pNext;
  9. }
  10. return pre;
  11. }

二、已知链表的头节点,将链表从位置m到n逆序。注意:1<=m<=n<=链表长度(不允许申请额外空间)

思路:主要是要找到逆序的头节点和尾巴,以及头节点的前驱节点,和尾节点的后置节点

注意:如果m=1,说明是从第一个节点开始,那么就需要修改头节点

  1. public static ListNode reverseListBetween(ListNode node,int m,int n) {
  2. int index = 1;
  3. ListNode p = node;
  4. ListNode pre = null;
  5. while(index <= n) {
  6. if(index == m) {
  7. ListNode temp = p;
  8. ListNode tempPre = null;
  9. ListNode tempNext = null;
  10. for(int i = m;i <= n;i++) {//开始进行节点的逆序
  11. tempNext = temp.next;
  12. temp.next = tempPre;
  13. tempPre = temp;
  14. temp = tempNext;
  15. }
  16. if(pre == null) {//说明是从头节点就开始翻转
  17. p.next = temp;
  18. node = tempPre;//修改下头节点
  19. }else {
  20. pre.next = tempPre;
  21. p.next = temp;
  22. }
  23. index = n;
  24. }
  25. pre = p;
  26. p = p.next;
  27. index++;
  28. }
  29. return node;
  30. }

三、求两个链表公共的节点,若没有则返回null

解题思路:给个图就能知道!!!!从相同的位置开始判断。交点之后都是相同的。

  1. public static ListNode getIntersectionNode(ListNode node1,ListNode node2) {
  2. //先求两个链表的长度
  3. int len1 = getLengthOfList(node1);
  4. int len2 = getLengthOfList(node2);
  5. //将指针移动到相同的位置
  6. if(len1 > len2) {
  7. for(int i = 0; i < len1 - len2;i++)
  8. node1 = node1.next;
  9. }else {
  10. for(int i = 0; i < len2 - len1;i++)
  11. node2 = node2.next;
  12. }
  13. //找相同的节点
  14. while(node1 != null && node2 != null) {
  15. if(node1 == node2)
  16. return node1;
  17. node1 = node1.next;
  18. node2 = node2.next;
  19. }
  20. return null;
  21. }
  22. public static int getLengthOfList(ListNode node) {
  23. int len = 0;
  24. ListNode p = node;
  25. while(p != null) {
  26. len++;
  27. p = p.next;
  28. }
  29. return len;
  30. }

四、判断一个链表中是否有环,若有则返回环的入口,若没有则返回null

思路:设置快慢指针。

  1. public static ListNode detectCycle(ListNode node) {
  2. ListNode fast = node;
  3. ListNode low = node;
  4. while(low!=null && fast!=null && low.next != null && fast.next !=null) {
  5. low = low.next;
  6. fast = fast.next.next;
  7. if(low == fast) {
  8. //设置一个指针从头节点开始
  9. ListNode temp = node;
  10. while(temp != low) {
  11. temp = temp.next;
  12. low = low.next;
  13. }
  14. return temp;
  15. }
  16. }
  17. return null;
  18. }

五、链表划分:给定一个值x,将所有小于x的节点放在大于或等于x的节点前,且要保持这些节点原来的相对位置

解题思路:若是数组的话,实际上修改下排序的规则,并选择一种稳定的排序即可,但是链表采用排序的方式就会稍微复杂。实际上可以设置两个节点,遍历链表,将小于x的节点连接到一个节点,将大于或等于x的节点连接到另外一个节点,最后再将两个链表合并。

  1. public static ListNode partition(ListNode node,int val) {
  2. ListNode A = new ListNode(val);
  3. ListNode B = new ListNode(val);
  4. ListNode p1 = A;
  5. ListNode p2 = B;
  6. while(node != null) {
  7. if(node.val < val) {
  8. p1.next = node;
  9. p1 = p1.next;
  10. }else {
  11. p2.next = node;
  12. p2 = p2.next;
  13. }
  14. node = node.next;
  15. }
  16. p1.next = B.next;
  17. p2.next = null;
  18. return A.next;
  19. }

六、复杂链表的复制。

结点结构有三部分:一个值域 一个next域,一个随即域 ,指向任意节点。

  1. public class RandomListNode {
  2. int val;
  3. RandomListNode next = null;
  4. RandomListNode random = null;
  5. public RandomListNode(int val) {
  6. this.val = val;
  7. }
  8. }

 

  1. public static RandomListNode copyRandomListNode(RandomListNode node) {
  2. if(node == null)
  3. return null;
  4. //先复制节点
  5. RandomListNode p = node;
  6. while(p != null) {
  7. RandomListNode temp = new RandomListNode(p.val);
  8. temp.next = p.next;
  9. p.next = temp;
  10. p = p.next.next;
  11. }
  12. //复制节点的指向
  13. p = node;
  14. while(p != null) {
  15. if(p.random != null) {
  16. p.next.random = p.random.next;
  17. }
  18. p = p.next.next;
  19. }
  20. //拆分
  21. p = node;
  22. RandomListNode head = p.next;
  23. RandomListNode t = head;
  24. while(t.next != null) {
  25. p.next = t.next;
  26. t.next = t.next.next;
  27. p = p.next;
  28. t = t.next;
  29. }
  30. p.next = null;
  31. return head;
  32. }

七、两个排序链表的合并,合并后任然是有序的

  1. public static ListNode mergeTwoLists(ListNode node1,ListNode node2) {
  2. if(node1 == null)
  3. return node2;
  4. if(node2 == null)
  5. return node2;
  6. ListNode p = null;
  7. if(node1.val < node2.val) {
  8. p = node1;
  9. node1 = node1.next;
  10. }else {
  11. p = node2;
  12. node2 = node2.next;
  13. }
  14. ListNode t = p;
  15. while(node1 != null && node2 != null) {
  16. if(node1.val < node2.val) {
  17. t.next = node1;
  18. node1 = node1.next;
  19. }else {
  20. t.next = node2;
  21. node2 = node2.next;
  22. }
  23. t = t.next;
  24. }
  25. //退出时,至少有一个链表结束遍历了
  26. if(node1 != null) {
  27. t.next = node1;
  28. }
  29. if(node2 != null) {
  30. t.next = node2;
  31. }
  32. return p;
  33. }

八、链表的k逆序问题:每k个节点之间进行逆序,最后不足k个节点不逆序

  1. public static ListNode reverseK(ListNode node,int k) {
  2. //判断是否有k个节点,不足k个节点 直接返回头节点
  3. int index = 0;
  4. ListNode p = node;
  5. while(p != null) {
  6. index++;
  7. p = p.next;
  8. }
  9. if(index < k)
  10. return node;
  11. p = node;
  12. ListNode temp = p;//保存下当前的头节点
  13. ListNode pre = null;
  14. ListNode pNext = null;
  15. for(int i = 0; i < k;i++) {
  16. pNext = p.next;
  17. p.next = pre;
  18. pre = p;
  19. p = pNext;
  20. }
  21. //新的头节点为pre;
  22. temp.next = reverseK(p,k);//当前k个节点的尾节点的下一个为下k个节点逆序后的头节点
  23. return pre;
  24. }

九、删除链表中指定的值,返回清除后的头节点

注意:是否删除的头节点

  1. public static ListNode clearList(ListNode node,int val) {
  2. ListNode p = node;
  3. ListNode pre = null;
  4. while(p != null) {
  5. if(p.val == val) {
  6. //判断是否是头节点
  7. if(p == node) {
  8. node = p.next;
  9. p = node;
  10. }else {
  11. pre.next = p.next;
  12. p = p.next;
  13. }
  14. }else {
  15. pre = p;
  16. p = p.next;
  17. }
  18. }
  19. return node;
  20. }

十、判断链表是否是回文

  1. public static boolean isPalindrome(ListNode node) {
  2. ArrayList<ListNode> list = new ArrayList<>();
  3. ListNode p = node;
  4. while(p != null) {
  5. list.add(p);
  6. p = p.next;
  7. }
  8. for(int i = 0; i < list.size()/2;i++) {
  9. if(list.get(i).val != list.get(list.size()-1-i).val)
  10. return false;
  11. }
  12. return true;
  13. }

感觉差不多了   反正链表很简单  就这样吧

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/670154
推荐阅读
相关标签
  

闽ICP备14008679号