目录
1、删除值为val的所有节点
删除链表中等于给定值val的所有节点。【OJ链接】
/**
* 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 null;
}
ListNode prev=head;
ListNode cur=head.next;
while(cur!=null){
if(cur.val==val){
prev.next=cur.next;
cur=cur.next;
}else{
prev=cur;
cur=cur.next;
}
}
if(head.val==val){
head=head.next;
}
return head;
}
}
2、反转链表
反转一个链表。【OJ链接】
/**
* 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 reverseList(ListNode head) {
if(head==null){
return null;
}
ListNode cur=head.next;
head.next=null;
while(cur!=null){
ListNode curNext=cur.next;
cur.next=head;
head=cur;
cur=curNext;
}
return head;
}
}
3、返回链表中间节点
给定一个带有头节点的非空单链表,返回链表的中间节点。如果有两个中间节点,则返回第二个中间节点。【OJ链接】
/**
* 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 middleNode(ListNode head) {
if(head==null){
return null;
}
ListNode slow=head;
ListNode fast=head;
while(fast!=null&&fast.next!=null){
fast=fast.next.next;
slow=slow.next;
}
return slow;
}
}
4、返回链表第K个节点
输入一个链表,返回该链表中倒数第K个节点。【OJ链接】
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
if(k<=0||head==null){
return null;
}
ListNode fast=head;
ListNode slow=head;
while(k-1>0){
if(fast.next==null){
return null;
}
fast=fast.next;
//先让快节点走k-1步
k--;
}
while(fast.next!=null){
fast=fast.next;
slow=slow.next;
}
return slow;
}
}
5、合并有序链表
将两个有序链表合并为一个有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。【OJ链接】
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
if(list1==null){
return list2;
}
if(list2==null){
return list1;
}
//创建虚拟节点,充当新链表的头节点,值不代表任何意义
ListNode node=new ListNode(-1);
ListNode cur=node;
while(list1!=null&&list2!=null){
if(list1.val<list2.val){
cur.next=list1;
list1=list1.next;
}else{
cur.next=list2;
list2=list2.next;
}
cur=cur.next;
}
if(list1==null){
cur.next=list2;
}else{
cur.next=list1;
}
return node.next;
}
}
6、按值分割链表
将一个链表按照给定值X划分为两部分,所有小于X的节点排在大于或等于X的节点之前。不改变节点原来的顺序。【OJ链接】
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Partition {
public ListNode partition(ListNode pHead, int x) {
if(pHead==null){
return null;
}
ListNode bs=null;
ListNode be=null;
ListNode as=null;
ListNode ae=null;
ListNode cur=pHead;
while(cur!=null){
if(cur.val<x){
if(bs==null){
bs=cur;
be=cur;
}else{
be.next=cur;
be=cur;
}
}else{
if(as==null){
as=cur;
ae=cur;
}else{
ae.next=cur;
ae=cur;
}
}
cur=cur.next;
}
if(bs==null){
return as;
//如果小于X部分为空,则直接返回大于X部分即可。此时ae.next一定为null
}
be.next=as;//否则连接小于X和大于X部分
if(as!=null){
ae.next=null;
//当小于X部分不为空时,ae.next可能不为null,需要手动置为null
}
return bs;
}
}
7、判读回文链表
判断链表是不是回文链表。【OJ链接】
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class PalindromeList {
public boolean chkPalindrome(ListNode A) {
if(A==null){
return false;
}
if(A.next==null){
return true;
}
//求链表的中间节点
ListNode slow=A;
ListNode fast=A;
while(fast!=null&&fast.next!=null){
fast=fast.next.next;
slow=slow.next;
}
//反转后半段链表
ListNode cur=slow.next;
while(cur!=null){
ListNode curNext=cur.next;
cur.next=slow;
slow=cur;
cur=curNext;
}
//判断回文链表
while(slow!=A){
if(slow.val!=A.val){
return false;
}
if(A.next==slow){
return true;
}
slow=slow.next;
A=A.next;
}
return true;
}
}
8、找两个链表的公共节点
输入两个链表,输出两个链表的第一个公共节点。没有返回NULL。【OJ链接】
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
//求链表长度
public int len(ListNode head){
int len=0;
while(head!=null){
head=head.next;
len++;
}
return len;
}
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA==null||headB==null){
return null;
}
ListNode pl=headA;
ListNode ps=headB;
int lenA=len(headA);
int lenB=len(headB);
int len=lenA-lenB;
if(len<0){
//pl指向长的链表,ps指向短的链表
pl=headB;
ps=headA;
len=-len;
}
while(len--!=0){
pl=pl.next;
}
while(pl!=null){
if(pl==ps){
return pl;
}
pl=pl.next;
ps=ps.next;
}
return null;
}
}
9、判断成环链表
判断链表中是否有环。【OJ链接】
【拓展】
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public boolean hasCycle(ListNode head) {
if(head==null||head.next==null){
return false;//链表为空或者只有一个节点时,没有环
}
ListNode slow=head;
ListNode fast=head;
while(fast!=null&&fast.next!=null){
fast=fast.next.next;
slow=slow.next;
if(fast==slow){
return true;
//如果快慢节点可以相遇,表示链表有环
}
}
return false;
}
}
10、返回成环链表的入口
给定一个链表,判断链表是否有环并返回入环的节点。如果没有环,返回NULL。【OJ链接】
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
//判断链表是否有环,并返回第一次快慢节点相交的位置
public ListNode hasCycle(ListNode head){
if(head==null||head.next==null){
return null;
}
ListNode slow=head;
ListNode fast=head;
while(fast!=null&&fast.next!=null){
slow=slow.next;
fast=fast.next.next;
if(slow==fast){
return slow;
}
}
return null;
}
//当返回的结点与头节点再次相交时,为环的入口
public ListNode detectCycle(ListNode head) {
ListNode node=hasCycle(head);
if(node==null){
return null;
}else{
while(head!=node){
head=head.next;
node=node.next;
}
}
return head;
}
}