leetcode:删除链表中给定的结点
思路
:
代码实现:
class Solution { public ListNode deleteNode(ListNode head, int val) { //结点为空时 if(head==null){ return null; } ListNode cur=head; ListNode prev=null; //prev标记cur的前一个结点 while(cur!=null){ if(cur.val==val){ //删除结点 //如果是头结点 if(prev==null){ head=cur.next; cur=head; }else{ //不是头结点 prev.next=cur.next; cur=prev; } }else{ prev=cur; cur=cur.next; } } return head; } }
leetcode:反转链表
思路
:
借助三个引用:cur prev next
;
遍历链表,同时将当前结点的指向修改为指向它的前一个引用;由于结点没有引用其前一个结点,因此必须事先保存它的前一个结点,在更改引用之前,还需要保存它的后一个结点;
代码实现:
class Solution { public ListNode reverseList(ListNode head) { //链表为空时 if(head==null){ return null; } ListNode cur=head; ListNode prev=null; //指向当前结点的前一个 ListNode next=null; //指向当前结点的后一个 while(cur!=null){ //说明结点存在 //修改之前先保存其后一个结点 next=cur.next; //修改引用 cur.next=prev; prev=cur; cur=next; } return prev; } }
leetcode:链表的中间结点
思路
:
借助两个引用:fast slow
;
代码实现:
class Solution { public ListNode middleNode(ListNode head) { //借助快慢引用 ListNode fast=head; ListNode slow=head; while(fast!=null && fast.next!=null){ //保证两步都可以走成功 fast=fast.next.next; //fast每次走两步 slow=slow.next; //slow每次走一步 } return slow; } }
思考:
该题目中,当结点个数为偶数时,返回的是后一个结点,如果要返回前一个结点,怎么做?
方法:将
slow
的前一个结点prev
保存起来,当为偶数个结点且要返回前一个时,只需要返回prev
即可;
if(fast)=null,return prev; //偶数结点
if(fast)!=null,return slow; //奇数结点
leetcode:链表的倒数第K个结点
思路
:
借助两个引用:front back
;
front
从起始位置先走K
步;front
与back
同时往后走,front
为空时结束;back
的位置刚好就是倒数第K
个结点的位置;图解:
代码实现:
class Solution { public ListNode getKthFromEnd(ListNode head, int k) { //借助两个引用 ListNode front=head; ListNode back=head; //让front先往后走K步 while(0!=k){ if(front==null){ return null; } front=front.next; k--; } //让两个引用同时走 while(front!=null){ front=front.next; //走一步 back=back.next; //走一步 } return back; } }
leetcode:链表的第一个公共结点
思路
:
遍历链表
,看是否相等);由题目中已知,链表不带环,不带环的链表相交的三种情况如下所示:
代码实现:
public class Solution { public ListNode getIntersectionNode(ListNode headA, ListNode headB) { //任意一个链表为空时,均不可能相交 if(headA==null ||headB==null){ return null; } //遍历链表求交点 //遍历链表A ListNode curA=headA; int sizeA=1; while(curA.next!=null){ sizeA++; //遍历一个结点,sizeA增加一个 curA=curA.next; } //遍历链表B ListNode curB=headB; int sizeB=1; while(curB.next!=null){ sizeB++;//遍历一个结点,sizeB增加一个 curB=curB.next; } if(curA!=curB){ return null; } //上面执行完,肯定会相交 //求交点 int gap=sizeA-sizeB; curA=headA; curB=headB; if(gap>=0){ //A比B长 while(0!=gap--){ curA=curA.next; } }else{ while(0!=gap++){ curB=curB.next; } } while(curA!=curB){ curA=curA.next; curB=curB.next; } return curA; } }
leetcode:分割链表
思路
:
lessHead greatHead
;lessHead
用来存放小于给定值的结点, greatHead
用来存大于给定值的结点;lessHead
的尾结点指定greatHead
的头结点即可(注意是带头的
);代码实现:
class Solution { public ListNode partition(ListNode head, int x) { //链表为空时 if(head==null){ return null; } //将lessHead和greatHead给为带头结点的链表 ListNode lessHead =new ListNode(0); //保存小于特定值的结点 ListNode tailL= lessHead; ListNode greatHead =new ListNode(0); //保存大于特定值的结点 ListNode tailG =greatHead; ListNode cur=head; while(cur!=null){ if(cur.val<x){ tailL.next=cur; tailL=cur; }else{ tailG.next=cur; tailG=cur; } cur=cur.next; } //链接链接起来 //两个都带头结点,所以要指向greatHead.next tailL.next=greatHead.next; tailG.next=null; return lessHead.next; } }
leetcode:回文链表
思路
:
head1
,head2
两个链表;代码实现:
class Solution { //找中间结点方法 public ListNode getMiddleNode(ListNode head){ ListNode fast=head; ListNode slow=head; ListNode prev=null; //确保fast两次都可以走成功 while(fast!=null && fast.next!=null){ fast=fast.next.next; prev=slow; slow=slow.next; } if(fast==null){ return prev; } return slow; } //逆置链表 public ListNode reverseList(ListNode head){ ListNode cur=head; ListNode next=null; ListNode prev=null; while(cur!=null){ //修改之前先保存next的位置 next=cur.next; //修改引用 cur.next=prev; prev=cur; cur=next; } return prev; } public boolean isPalindrome(ListNode head) { //1.找链表的中间结点 ListNode mid=getMiddleNode(head); ListNode B=mid.next; //2.将后一个链表进行逆置 B= reverseList(B); //3. 依次比较两个链表的值域 ListNode curA=head; ListNode curB=B; boolean ret=true; while(curA!=null && curB!=null){ if(curA.val!=curB.val){ ret=false; break; } curA=curA.next; curB=curB.next; } //4.将链表链表链接 B=reverseList(B); mid.next=B; return ret; } }
leetcode:复杂链表的复制
思路
:
插入相同结点的新链表
给每个随机引用赋值
cur在第一个结点时:
插入的结点断开
代码实现:
class Solution { public Node copyRandomList(Node head) { //链表为空时 if(head==null){ return null; } //1. 在原链表的每个结点后插入值相等的结点 Node cur=head; while(cur!=null){ //new一个与原结点相同值域的结点 Node newNode=new Node(cur.val); newNode.next=cur.next; cur.next=newNode; cur=newNode.next; } //2.给新插入的结点的随机引用赋值 cur=head; while(cur!=null){ Node newNode =cur.next; if(cur.random!=null){ newNode.random=cur.random.next; } cur=newNode.next; } //将插入结点断开 Node newHead=head.next; cur=head; while(cur.next!=null){ Node curNext=cur.next; cur.next=curNext.next; cur=curNext; } return newHead; } }