今日学习的文章链接和视频链接
自己看到题目的第一想法
(203.移除链表元素)有思路,但不会写,,,缺乏代码敏感性。
(707.设计链表)了解逻辑,但不会写,,,麻了。
( 206.反转链表 )感觉很简单,但节点交换和指针转换很绕,没绕出来。
看完代码随想录之后的想法
(203.移除链表元素)常规思路:不加虚拟头节点。头节点是否=val,分等和不等两种情况。第二种方法:添加虚拟头节点。
(707.设计链表)声明初始化、增删改查。逻辑清晰
( 206.反转链表 )这么简洁,逻辑清晰。
自己实现过程中遇到哪些困难
(203.移除链表元素)代码块逻辑不清晰,双指针的作用及实现细节。
(707.设计链表)声明初始化不熟悉,到临界值不好确定,容易空想,画图解百忧。双向链表细节还有点迷。
( 206.反转链表 )应该定义几个节点?为什么?怎么保存节点?怎么调整指针?
今日收获,记录一下自己的学习时长
(203.移除链表元素)代码块逻辑梳理,链表双指针各自意义及遍历细节。4h只是理解的阶段。自己实现估计又是一堆细节问题。
203.移除链表元素
// 不设置虚拟头节点的方式
// 两种情况:
// 头节点等于val值:更新头节点为下一节点。
// 头节点不等于val值:定义两个指针进行遍历,当前节点指针负责判别是否等于val值,前一节点指针根据当前节点是否等于val确定指向下一节点的位置。
class Solution { public ListNode removeElements(ListNode head, int val) { // 头节点等于val值: while (head != null && head.val == val) { head = head.next; } // 为空 if (head == null) { return head; } // 头节点不等于val值 ListNode pre = head; // 记录当前节点前一指针,用于更新遍历 ListNode cur = head.next; // 记录当前节点,用于查找遍历 while (cur != null) { if (cur.val == val) { pre.next = cur.next; } else { pre = cur; } cur = cur.next; } return head; } }
设置虚拟头节点的方式
class Solution { public ListNode removeElements(ListNode head, int val) { if (head == null) { return head; } //这行代码的作用是创建一个名为dummy的新的链表节点,并将原链表的头节点head作为dummy节点的下一个节点。 //初始化值:新节点的值被设置为-1,这里的值可以是任意值,通常使用-1表示一个无效或占位的值。 ListNode dummy = new ListNode(-1, head); ListNode pre = dummy; ListNode cur = head; while (cur != null) { if (cur.val == val) { pre.next = cur.next; } else { pre = cur; } cur = cur.next; } return dummy.next; } }
707.设计链表
// 单链表 class ListNode { int val; ListNode next; ListNode(){} ListNode(int val) { this.val = val; } } class MyLinkedList { // size存储链表元素的个数 int size; // 虚拟头结点 ListNode head; // 初始化链表 public MyLinkedList() { size = 0; head = new ListNode(0); } // 获取第index个节点的数值,注意index是从0开始的,第0个节点就是头结点 public int get(int index) { //如果index非法,返回-1 if (index < 0 || index >= size) { return -1; } ListNode currentNode = head; // 包含一个虚拟头节点,所以查找第index + 1 个节点 for (int i = 0; i <= index; i++) { // currentNode = currentNode.next; } return currentNode.val; } public void addAtHead(int val) { addAtIndex(0, val); } public void addAtTail(int val) { addAtIndex(size, val); } public void addAtIndex(int index, int val) { if (index > size) { return; } if (index < 0) { index = 0; } size++; ListNode pred = head; for (int i = 0; i < index; i++) { pred = pred.next; } ListNode toAdd = new ListNode(val); toAdd.next = pred.next; pred.next = toAdd; } public void deleteAtIndex(int index) { if (index < 0 || index >= size) { return; } size--; if (index == 0) { head = head.next; return; } ListNode pred = head; for (int i = 0; i < index; i++) { pred = pred.next; // 记录即将删除的下一节点,方便获取该节点的下一节点pred.next.next } pred.next = pred.next.next; } }
206.反转链表
class Solution { public ListNode reverseList(ListNode head) { ListNode prev = null; ListNode cur = head; ListNode temp = null; while (cur != null) { temp = cur.next; // 保存下一个节点 cur.next = prev; // 改变指针方向 prev = cur; // 前驱指针向后移动 cur = temp; // 将cur改为下一节点 } return prev; } }