cur.next=head;
head=cur;
cur=curNext;
}
return head;
}
定义快慢指针,注意偶数节点和奇数节点的情况
注意判断条件 在偶数情况下 如果是判断fast.next.next就会空指针异常,必须把判断条件两个都加上。
public ListNode middleNode(ListNode head) {
//定义快慢指针 快指针比慢指针多走一步 注意奇数和偶数情况
if(headnull||head.nextnull){
return head;
}
ListNode slow=head;
ListNode fast=head;
while(fast!=null&&fast.next!=null){
fast=fast.next.next;
slow=slow.next;
}
return slow;
}
定义快慢指针 快指针先走n-1步 之后慢指针再走,修改地址值即可
public ListNode removeNthFromEnd(ListNode head, int n) {
if(head==null){
return null;
}
ListNode fast=head;
ListNode dummy=new ListNode(0,head);
ListNode slow=dummy;
for(int i=1;i<n;i++){
fast=fast.next;
}
while(fast.next!=null){
fast=fast.next;
slow=slow.next;
}
slow.next=slow.next.next;
return dummy.next;
}
给定X值,分割链表 前面链表为小于X的值,后面链表为大于等于X的值
要考虑很多情况
1.第一次插入链表时 要将头节点和尾巴节点都指向插入的节点
2.不是第一次插入时,只需要把尾巴节点next值指向插入的节点,之后把尾巴节点往后挪
3.如果前面链表为空,返回后面链表的头
4。还需要将后面节点的next值置空,之后连接两个链表。
public ListNode partition(ListNode head, int x) {
//分割链表 将小于x的分为一部分,将大于等于x的分为一部分呢! 乖乖yy
if(head==null){
return null;
}
ListNode xh=null;//小于x的头节点
ListNode xe=null;;//小于x的尾巴节点
ListNode Xh=null;//大于等于X的头节点
ListNode Xe=null;//大于等于X的尾节点
ListNode cur=head;
while(cur!=null){
if(cur.val<x){
//小于X的部分
if(xh==null){
//第一次插入
xh=cur;
xe=cur;
}else{
//不是第一次插入
xe.next=cur;
xe=cur;
}
}else{
//>=X 的部分
if(Xh==null){
//第一次插入
Xh=cur;
Xe=cur;
}else{
//不是第一次插入
Xe.next=cur;
Xe=cur;
}
}
cur=cur.next;
}//判断 所有元素都大于x 前面的链表没有数据 要返回后面的链表
if(xh==null){
return Xh;
}
xe.next=Xh;
if(Xh!=null){
//将最后一个元素置为null
Xe.next=null;
}
return xh;
}
和合并有序数组是一样的,链表复杂一些要将后面节点地址先保存,之后定义傀儡节点,按照值小的顺序连接起来
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
//1.思路就是先定傀儡节点,将链表穿起来 定义两个变量将后面地址保存起来 之后串糖葫芦一样串起来
ListNode dummy=new ListNode(-1);
ListNode head=dummy;//保存傀儡节点
ListNode cur1=l1;//保存节点后面的地址值
ListNode cur2=l2;
while(l1!=null&&l2!=null){
cur1=l1.next;
cur2=l2.next;
if(l1.val<=l2.val){
dummy.next=l1;
l1=cur1;
}else{
dummy.next=l2;
l2=cur2;
}
dummy=dummy.next;
}
if(l1!=null){
dummy.next=l1;
}
if(l2!=null){
dummy.next=l2;
}
return head.next;
}
双指针 遇到相等的就跳过 ,最后要将最后一个节点置为空。
public ListNode deleteDuplicates(ListNode head) {
if(head==null){
return null;
}
ListNode prev=head;
ListNode cur=head.next;
while(cur!=null){
if(prev.val==cur.val){
cur=cur.next;
}else{
prev.next=cur;
prev=cur;
cur=cur.next;
}
}
prev.next=cur;
return head;
}
先用set判断是否存在 空间复杂度为O(N),不太符合题目要求
public boolean hasCycle(ListNode head) {
HashSet set=new HashSet<>();
while(head!=null){
set.add(head);
head=head.next;
if(set.contains(head)){
return true;
}
}
return false;
}
2.快慢指针数学问题,快指针走两步,慢指针走一步,有环一定相遇,没有环就不会相遇 空间复杂度为O(1)
public boolean hasCycle(ListNode head) {
//快慢指针还是数学问题
if(headnull||head.nextnull){
return false;
}
ListNode slow=head;
ListNode fast=head.next;
while(slow!=fast){
if(fastnull||fast.nextnull){
return false;
}
fast=fast.next.next;
slow=slow.next;
}
return true;
}
1.先利用set存储节点 之后循环判断,空间复杂度为O(N)时间复杂度为O(N),比较慢
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
HashSetset=new HashSet<>();
while(headA!=null){
set.add(headA);
headA=headA.next;
}
while(headB!=null){
if(set.contains(headB)){
return headB;
}
headB=headB.next;
}
return null;
}
2.双指针,确实没想出来,看了题解才知道是两个链表相连接,遍历是否有想交的节点
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode cur1=headA;
ListNode cur2=headB;
while(cur1!=cur2){
cur1=cur1==null?headB:cur1.next;
cur2=cur2==null?headA:cur2.next;
}
return cur1;
}
这道题没什么技巧,就是注意很多特殊情况,加完要判断进位,我第一次敲的时候能执行但是不能过,没有考虑到特殊情况。
最后看评论解答就是用一个进位标志数来解决,学到了。
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode list=new ListNode(-1);
ListNode head=list;
int t=0;
while(l1!=null||l2!=null||t!=0){
if(l1!=null){
t+=l1.val;
l1=l1.next;
}
if(l2!=null){
t+=l2.val;
l2=l2.next;
}
list.next=new ListNode(t%10);
list=list.next;
t/=10;
}
return head.next;
}
1.可以将链表中值存放在顺序表中,之后定义双指针遍历判断
2.快慢指针带反转
3.利用栈实现li
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
![img](https://img-blog.csdnimg.cn/img_convert/eda9e1cace93d552fb34d6aaad76fd06.jpeg)
言尽于此,完结
无论是一个初级的 coder,高级的程序员,还是顶级的系统架构师,应该都有深刻的领会到设计模式的重要性。
- 第一,设计模式能让专业人之间交流方便,如下:
程序员A:这里我用了XXX设计模式
程序员B:那我大致了解你程序的设计思路了
- 第二,易维护
项目经理:今天客户有这样一个需求…
程序员:明白了,这里我使用了XXX设计模式,所以改起来很快
- 第三,设计模式是编程经验的总结
程序员A:B,你怎么想到要这样去构建你的代码
程序员B:在我学习了XXX设计模式之后,好像自然而然就感觉这样写能避免一些问题
- 第四,学习设计模式并不是必须的
程序员A:B,你这段代码使用的是XXX设计模式对吗?
程序员B:不好意思,我没有学习过设计模式,但是我的经验告诉我是这样写的
从设计思想解读开源框架,一步一步到Spring、Spring5、SpringMVC、MyBatis等源码解读,我都已收集整理全套,篇幅有限,这块只是详细的解说了23种设计模式,整理的文件如下图一览无余!
搜集费时费力,能看到此处的都是真爱!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
方便,如下:
程序员A:这里我用了XXX设计模式
程序员B:那我大致了解你程序的设计思路了
- 第二,易维护
项目经理:今天客户有这样一个需求…
程序员:明白了,这里我使用了XXX设计模式,所以改起来很快
- 第三,设计模式是编程经验的总结
程序员A:B,你怎么想到要这样去构建你的代码
程序员B:在我学习了XXX设计模式之后,好像自然而然就感觉这样写能避免一些问题
- 第四,学习设计模式并不是必须的
程序员A:B,你这段代码使用的是XXX设计模式对吗?
程序员B:不好意思,我没有学习过设计模式,但是我的经验告诉我是这样写的
[外链图片转存中…(img-3Xq2iXGw-1713714212110)]
从设计思想解读开源框架,一步一步到Spring、Spring5、SpringMVC、MyBatis等源码解读,我都已收集整理全套,篇幅有限,这块只是详细的解说了23种设计模式,整理的文件如下图一览无余!
[外链图片转存中…(img-4iPjZvpX-1713714212110)]
搜集费时费力,能看到此处的都是真爱!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!