if(ahead.val == val)//如果先驱节点的值正好等于目标值
{
cur.next=ahead.next;//跨过ahead节点连接
ahead = cur;//先驱节点退回,等待下一次使用。
}
}
if(cur.next != null && cur.next.val != val)
{
cur = cur.next;//cur能向前移动
ahead = ahead.next;
}
if(cur.next == null)
{
if(head.val == val) return head.next;
else break;
}
}
return head;
}
}
关于本题解,补充说明如下,
//首先其实本题我的解法循环不变量设置的有问题,**很多情况下不论是数组还是链表
//快慢指针也好,滑动窗口也罢,其实极大多数都是将走的快的指针 一探到底设置为终止条件的**
//循环不变量设置为cur,我的上述都是在while循环内针对cur.next不为空进行的操作,也就是最后cur.next==null的时候循环出不去了,所以需要进行处理!
//只有cur的下一个节点的值不为目标值,才能移动cur,所以到了此步(cur.next==null),不用再检查cur的val了
//拐回去判断一下头节点即可!~~,因为一开始就是从cur和cur.next起始的,正好错过第一个头结点记得要在内部返回,不然报错死循环!也就是说你循环不变量找错了,需要手动退出~太菜了
//所以推荐大家用移动的快的指针做循环不变量终止循环!
根据本题,总结经验:
1:从一开始如果第一个头结点后是一连串符合要求需要删去的,那么要求你要么不断将指针回退,避免连续符合要求的情况,但是指针不断前进漏过去了:
要么跳过第一个头结点,扫描一遍再回头看第二个
2:while循环还是要找对循环不变量条件,出去的条件要考虑到
**很多情况下不论是数组还是链表
//快慢指针也好,滑动窗口也罢,其实极大多数都是将走的快的指针 一探到底设置为终止条件的**
找对条件事半功倍
3: 其次,如果起手一连串相同的,不如先考虑从第二个开始,然后再回头检查第一个,这种思想真的不错。
力扣刷题——————>单链表系列
第一题:移除链表元素
第二种解法:在原链表上进行操作,博哥版
===================
此题某种意义上可以写成 单链表内的增删查改中的删除方法,remove属实高效。
更改了循环不变量!
/**
-
Definition for singly-linked list.
-
-
public class ListNode {
-
-
int val;
-
-
ListNode next;
-
-
ListNode() {}
-
-
ListNode(int val) { this.val = val; }
-
-
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
-
-
}
*/
class Solution {
//博哥解法
public ListNode removeElements(ListNode head, int val) {
if (head == null) return head;//只有在此判断是不是链表上来就为空,反手一个空,下面的引用变量就爆炸了,无法声明
ListNode cur = head;//起手把用来穿的固定节点定在第一个
ListNode ahead = head.next;//把先驱节点定在第二个
//到时候回头来检查第一个节点
//如果是 66666 val==6这种极端特判,从第一个开始检查太费劲,先驱结点需要不断退回~
while (ahead != null)
//此处用ahead先驱节点做循环不变量,好处有三
//1:下面循环内的两种情况,不管何种,ahead的位置都在不断变更向前,当ahead为空,链表扫描一遍,复杂度为n
//2:如果是只有一个节点的情况,ahead就是空,进不去循环。
{
if (ahead.val == val)//如果先驱节点的值就是目标值,先跳过这个结点,然后再跟固定的穿起来
{
ahead = ahead.next;
cur.next = ahead;
} else//先驱节点安全,先往前再说,新ahead的值下次循环再判
{
cur = cur.next;
ahead = ahead.next;
}
}//出了循环,然后再判断头结点
if (head.val == val) {
return head.next;
}
return head;
}
}
第三种解法:论 链表的暴力解法!及其容易出现和发生的bug
=============================
- 🔲不要忘了暴力解法声明新数组是一个一个结点申请copy往后加上的
力扣大佬,宫水三叶姐姐说过:链表 的 暴力解法 可以解决百分之九十的问题,
模板就是,申请一个新的头结点!ListNode newHead = new ListNode (-10),最后返回这个新头结点的 next,然后不断的copy不和条件的新节点添加到新链表中,最后再返回即可!~~
本题:力扣刷题——————>单链表系列
第一题:移除链表元素
第三种解法:申请链表,不断在后面动态更新加上原链表中符合要求的新的节点,三叶姐版
我的理解不深时候手敲的第一遍错误代码!
注意是错误的,大家看一看找出错误即可,浅尝辄止哦,不要上头!~
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
判断
回到题目,如果你真想检验一个人的水平。第一步先考察一下基本的编程基础,问几个基本的编程问题,可以和前端相关也可以无关。比如垃圾收集大致是怎么做的,setTimeout 大致做了什么(说会在另一个线程里执行回调的直接毙掉)。
第二步考察一下知识面,问问http、tcp的基本知识,dns是怎么工作的,或者常用框架的实现原理,看看候选人是不是除了自己的一亩三分地什么都不关心。
第三步考察hold业务逻辑的能力,从一个简单的注册页,或者查询页开始,先让说下代码的基本架构,然后需求、性能、可靠性、安全层层加码,看看能不能很快的反馈出解决方案。能对答如流的要么做过,要么对他来说这种复杂度的东西是小case。
前三步都没问题,基本上说明候选人已经还行了,但是行到什么程度,不知道。如果想找比较厉害的,就增加个第四步,亮点项目考察。
总的来说,面试官要是考察思路就会从你实际做过的项目入手,考察你实际编码能力,就会让你在电脑敲代码,看你用什么编辑器、插件、编码习惯等。所以我们在回答面试官问题时,有一个清晰的逻辑思路,清楚知道自己在和面试官说项目说技术时的话就好了,我整理一套前端面试题分享给大家,希望对即将去面试的小伙伴们有帮助!
页,或者查询页开始,先让说下代码的基本架构,然后需求、性能、可靠性、安全层层加码,看看能不能很快的反馈出解决方案。能对答如流的要么做过,要么对他来说这种复杂度的东西是小case。
前三步都没问题,基本上说明候选人已经还行了,但是行到什么程度,不知道。如果想找比较厉害的,就增加个第四步,亮点项目考察。
总的来说,面试官要是考察思路就会从你实际做过的项目入手,考察你实际编码能力,就会让你在电脑敲代码,看你用什么编辑器、插件、编码习惯等。所以我们在回答面试官问题时,有一个清晰的逻辑思路,清楚知道自己在和面试官说项目说技术时的话就好了,我整理一套前端面试题分享给大家,希望对即将去面试的小伙伴们有帮助!
[外链图片转存中…(img-tJcPPsYp-1711827554129)]
[外链图片转存中…(img-BIKIRTaX-1711827554129)]