当前位置:   article > 正文

代码随想录LeetCode | 链表问题总结

代码随想录LeetCode | 链表问题总结

前沿:撰写博客的目的是为了再刷时回顾和进一步完善,其次才是以教为学,所以如果有些博客写的较简陋,是为了保持进度不得已而为之,还请大家多多见谅。

预:看到题目后的思路和实现的代码。

见:参考答案展示。

感思:对比答案后的思考,与之前做过的题目是否有关联。

行:

(1)对于没做出来的题目,阅读答案后重新做一遍;

(2)下次做题可以尝试改善的方向;

(3)有助于理解的相关的题目

优先级:做题进度>学习&总结>默写回顾>做题数量

链表基础

为什么使用链表?

链表相对于数组的优势在于其便于插入和删除,而数组存储在连续的地址中,全部替换才能达到“删除”效果。

为什么链表便于插入和删除/时间复杂度n(1)?

与链表的存储和获取下一链表的方式有关。因为链表的存储是不连续的,而数组则是连续存储,链表其通过指针来获取下个节点的位置,所以只需要直接修改指针域则能够插入和删除指针。

链表的定义:链表结构中有指针域和val,val存储对于值,通过指针域来连接下个节点,单链表只有next,而双链表的指针域还有pre。

如何使用链表?

类似数组的创建形式:ListNode 名称 = new ListNode();

203. 移除链表元素

题目链接: 203. 移除链表元素

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]

提示:

  • 列表中的节点数目在范围 [0, 104] 内
  • 1 <= Node.val <= 50
  • 0 <= val <= 50

实现代码

  1. class Solution {
  2. public ListNode removeElements(ListNode head, int val) {
  3. ListNode dummyNode = new ListNode();
  4. dummyNode.next = head;
  5. ListNode pre = dummyNode;
  6. ListNode cur = dummyNode.next;
  7. while(cur != null){
  8. if(cur.val == val){
  9. pre.next = cur.next; // pre.next.next = pre.next;
  10. }else{ // 没有否定,直接后面增加pre = pre.next;
  11. pre = cur;
  12. }
  13. cur = cur.next;
  14. }
  15. return dummyNode.next;
  16. }
  17. }

与题解区别

  1. ListNode dummyNode = new ListNode();
  2. dummyNode.next = head;

上面的代码块能够通过直接调用构造函数实现

        ListNode dummyNode = new ListNode(-1,head);

707. 设计链表

思路图

实现代码

链表的定义+链表实现相关操作类

  1. class ListNode{
  2. int val;
  3. ListNode next;
  4. public ListNode(){
  5. }
  6. public ListNode(int val){
  7. this.val = val;
  8. }
  9. }
  10. class MyLinkedList {
  11. ListNode head = new ListNode();
  12. int len = 0;
  13. public MyLinkedList() {
  14. }
  15. public int get(int index) {
  16. if(index < 0 || index >= len){
  17. return -1;
  18. }
  19. ListNode cur = head.next;
  20. while(index != 0 && cur != null){
  21. cur = cur.next;
  22. index--;
  23. }
  24. return cur.val;
  25. }
  26. public void addAtHead(int val) {
  27. addAtIndex(0,val);
  28. }
  29. public void addAtTail(int val) {
  30. addAtIndex(len,val);
  31. }
  32. public void addAtIndex(int index, int val) {
  33. if(index < 0){
  34. index = 0;
  35. }else if(index > len){
  36. return;
  37. }
  38. ListNode cur = head.next;
  39. ListNode pre = head;
  40. ListNode temp = new ListNode(val);
  41. while(index != 0 && cur != null){
  42. cur = cur.next;
  43. pre = pre.next;
  44. index--;
  45. }
  46. temp.next = cur;
  47. pre.next = temp;
  48. len++;
  49. }
  50. public void deleteAtIndex(int index) {
  51. if(index < 0 || index >= len){
  52. return;
  53. }
  54. ListNode cur = head;
  55. while(index != 0 && cur.next != null){
  56. cur = cur.next;
  57. index--;
  58. }
  59. cur.next = cur.next.next;
  60. len--;
  61. }
  62. }

与题解的区别

1.定义中少了构造器初始多属性的方法

  • 无参构造器为属性设置默认初始值
  1. class ListNode{
  2. public ListNode(int val,ListNode next}{
  3. this.val = val;
  4. this.next = next;
  5. }
  6. }
  7. class MyLinkedList {
  8. int len;
  9. ListNode head;
  10. public MyLinkedList() {
  11. head = new ListNode(0);
  12. len = 0;
  13. }

2. 能够直接通过改动变量+前节点变量直接添加新变量

  1. public void addAtIndex(int index, int val) {
  2. ListNode pre = head;
  3. for(int i = 0;i < index;i++){
  4. pre = pre.next;
  5. }
  6. ListNode toAdd = new ListNode(val);
  7. toAdd.next = pre.next; //可能会空指针报错
  8. pre.next = toAdd;
  9. len++;
  10. }

206. 反转链表

思路图

  题解代码

  1. class Solution {
  2. public ListNode reverseList(ListNode head) {
  3. // ListNode dummyNode = new ListNode(-1,head);
  4. ListNode pre = null;
  5. ListNode cur = head;
  6. ListNode temp = null;
  7. while(cur != null){
  8. temp = cur.next;
  9. cur.next = pre;
  10. pre = cur;
  11. cur = temp;
  12. }
  13. return pre;
  14. }
  15. }

为什么二刷时仍然画不出来呢?

二刷:思考10分钟,感觉总是画不出循环遍历的闭环。

看完题解总结后,重新思考一下子就顺着题解写出来,但对于当时为什么画不出来就想不到了。

所以,当思考后做不出来时,要将画的思路图拍照或写下来的形式记录下来,因为问题是顽固的。

为什么三刷时画出来了还做不出来?

三刷:

看到这题就想到要画出来再实现,前面10分钟画出来的有问题,之后找到的正确画法(如下图),但仍实现有问题,就在纠结是否是顺序问题。

 有问题代码如下

  1. class Solution {
  2. public ListNode reverseList(ListNode head) {
  3. ListNode dummyNode = new ListNode();
  4. dummyNode.next = head;
  5. ListNode pre = dummyNode;
  6. ListNode cur = head;
  7. ListNode temp = head;
  8. while(temp.next != null){
  9. temp = temp.next;
  10. cur.next = pre;
  11. pre = cur;
  12. cur = temp;
  13. }
  14. return cur;
  15. }
  16. }

代码实现与画图不一致

实现代码中是dummyNode指向head,并不是如图上面的head指向dummyNode;

  • cur.next = pre→导致dummyNode和cur成环了;

刷题模式优化:记录做不出来时想的思路

刷题记录

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

闽ICP备14008679号