前言
这是我参加的第二次训练营!!!爽!这次我将更加细致的写清每一道难题,不仅是提升自己,也希望我自己的写的文章对读者有一定的帮助!
打卡代码随想录算法训练营第55期第三天(づ ̄3 ̄)づ╭❤~
首先十分推荐学算法的同学可以先了解一下代码随想录,可以在B站卡哥B站账号、代码随想录官方网站代码随想录了解,卡哥清晰易懂的算法教学让我直接果断关注,也十分有缘和第55期的训练营大家庭一起进步。
今日题目
在学习今天题目之前,可以先去学习一下:链表理论基础
LeetCode 203 移除链表元素
题目链接:203 移除链表元素
文章讲解:移除链表元素
视频讲解:卡哥讲解 —— 移除链表元素
本题看过链表理论基础的小伙伴们也可能有点苦恼。因为可能忽视头节点问题,且链表的特殊之处在于要删除链表必须是删除节点的前一个节点来操作,所以可能有些许头疼,此时我们需要用两个循环来分别处理头节点和非头节点,写while循环的时候注意判空问题。
public class Solution {
public ListNode RemoveElements(ListNode head, int val) {
//确保头节点不为目标值
while(head != null/*使用while就要注意判空问题*/ && head.val == val)
head = head.next;
ListNode cur = head;//设置临时节点
while(cur != null && cur.next != null)
{
if(cur.next.val == val)//如果节点的下个节点为目标节点
cur.next = cur.next.next;//则让下一个节点改为下一个节点的下一个节点
else//如果不是目标节点
cur = cur.next;//则跳转下一个节点继续检测
}
return head;
}
}
可是上述方法就很难受,我们要分别考虑两种情况,虽然不复杂,但是需要两个while循环来解决,因此我们来了解虚拟头节点,这在链表中是一个十分重量级的存在,可以帮助解决许多问题。 上述讲解过操作一个节点一定是上一个节点操作,可是头节点没有上一个节点,所以我们给它强制安一个虚拟头节点dummyHead,来使得原本的链表每个节点都有上一个节点,这样我们就可以使用相同的规则来操作他们。
public class Solution {
public ListNode RemoveElements(ListNode head, int val) {
ListNode dummyHead = new ListNode();//虚拟头节点
dummyHead.next = head;//将虚拟头节点和头节点相连
ListNode cur = dummyHead;
while(cur != null && cur.next != null)//使用while循环就要注意判空
{
//与原本做法一致
if(cur.next.val == val)
cur.next = cur.next.next;
else
cur = cur.next;
}
//这里注意是返回虚拟头节点的下一个节点,而不是头节点,因为头结点可能已经被换掉了
return dummyHead.next;
}
}
LeetCode 707 设计链表(十分重要(个人向))
题目链接:707 设计链表
文章讲解:设计链表
视频讲解:卡哥讲解 —— 设计链表
本题是一个十分重要的内容,常常会让你在面试的时候手撕链表,所以要反复练习,当自己明白了链表的特性,也不需要过多讲解,各种细节需要自己反复思考处理,不断地练习达到不错的水平为止。
下文我使用的是虚拟头节点的方法,同时尽量将细节标明,注意反复练习。
public class ListNode
{
public ListNode(int val)
{
this.val = val;
}
public int val;
public ListNode next;
}
public class MyLinkedList {
public ListNode dummyHead;
public int count;
//构造函数初始化
public MyLinkedList() {
dummyHead = new ListNode(0);
count = 0;
}
public int Get(int index) {
//判断index是否合法 查找一个数 索引一定要小于个数 ,因为索引从0开始
if(index < 0 || count <= index)
return -1;
ListNode cur = dummyHead;
for(int i = 0; i <= index; i++)
cur = cur.next;
return cur.val;
}
public void AddAtHead(int val) {
//这里直接用下面写好的方法即可
AddAtIndex(0,val);
}
public void AddAtTail(int val) {
//这里直接用下面写好的方法即可
AddAtIndex(count , val);
}
public void AddAtIndex(int index, int val) {
//添加索引 索引可以等于个数 但不能超过个数
if(index > count)
return;
ListNode cur = dummyHead;
for(int i = 0; i < index; i++)
cur = cur.next;
ListNode temp = cur.next;
cur.next = new ListNode(val);
cur.next.next = temp;
count++;//注意增加数量
}
public void DeleteAtIndex(int index) {
//删除索引,索引肯定要小于个数且不能等于个数
if(index >= count)
return;
ListNode cur = dummyHead;
for(int i = 0; i < index; i++)
cur = cur.next;
cur.next = cur.next.next;
count--;//注意减少数量
}
}
LeetCode 206 反转链表
题目链接:206 反转链表
文章讲解:反转链表
视频讲解:卡哥讲解 —— 反转链表
本题需要注意的是当要反转整个链表的时候需要三个节点来不停的运作。且每一个节点变换的时机是什么时候,可能需要思考一下才能理解透彻,且过段时间来看是否还能够写出来很重要!
public class Solution {
public ListNode ReverseList(ListNode head) {
ListNode pre = null;//上一个节点
ListNode cur = head;//设置当前节点
while(cur != null)
{
ListNode temp = cur.next;//记录临时节点为当前节点下一个节点
cur.next = pre;
pre = cur;
cur = temp;
}
return pre;
}
}
今天的题目对于第一次接触链表的同学可能有些许困难,尤其是设计链表,需要反复的练习,为了成为算法高手,加油!