目录
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;
}
}
1.反转链表
反转链表 要求:时间复杂度O(n),空间复杂度O(1)
class Solution {
public ListNode reverseList(ListNode head) {
if (head == null) { //一个节点都没有
return null;
}
if (head.next == null) { //只有一个节点
return head;
}
ListNode cur = head.next;
head.next = null;
while (cur != null) {
ListNode curNext = cur.next;
cur.next = head;
head = cur;
cur = curNext;
}
return head;
}
}
2.链表的中间节点
class Solution {
public ListNode middleNode(ListNode head) {
if (head == null) { //一个节点都没有
return null;
}
if (head.next == null) { //只有一个节点
return head;
}
//快慢指针
ListNode fast = head;
ListNode slow = head;
while (fast != null && fast.next != null) { //注意这里两个条件顺序不能变!!
fast = fast.next.next; //fast一次走两步
slow = slow.next; //slow一次走一步
}
return slow;
}
}
3.链表中倒数第k个节点
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
if (k <= 0 || head == null) { //判断k和链表的有效性
return null;
}
//快慢指针
ListNode fast = head;
ListNode slow = head;
for (int i = 0;i < k-1;i++) { //先让fast走k-1步
fast = fast.next;
if (fast == null) { //相当于直接越界
return null;
}
}
while (fast.next != null) { //再让fast和slow一起走
fast = fast.next;
slow = slow.next;
}
return slow;
}
}
4.合并两个有序链表
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
ListNode newHead = new ListNode();//定义一个新头作为合并链表的起点
ListNode tmpH = newHead;//tmpH指向每一个合并后链表的元素
while (list1 != null && list2 != null) {
if (list2.val < list1.val) { //list2的val小于list1的val时
tmpH.next = list2; //当前tmpH的next存入该节点的地址
tmpH = tmpH.next; //tmpH向后走一步
list2 = list2.next; //list2向后走一步
}else { //同上
tmpH.next = list1;
tmpH = tmpH.next;
list1 = list1.next;
}
}
//list1为空时,说明list1已遍历完,此时list2剩余元素直接接入list1后即可
if (list1 == null) {
tmpH.next = list2;
}
//同上
if (list2 == null) {
tmpH.next = list1;
}
//注意返回的是newHead.next而不是newHead
return newHead.next;
}
}
5.链表分割
public class Partition {
public ListNode partition(ListNode pHead, int x) {
ListNode bs = null;//before start
ListNode be = null;//before end
ListNode as = null;//after start
ListNode ae = null;//after end
ListNode cur = pHead ;//cur初识化为头节点
while (cur != null) { //遍历链表
if (cur.val < x) { //小于x放在前面
if (bs == null) { //第一次存放
bs = cur;
be = cur;
}else {
be.next = cur;
be = be.next;
}
}else { //大于x放在后面
if (as == null) { //第一次存放
as = cur;
ae = cur;
}else {
ae.next = cur;
ae = ae.next;
}
}
cur = cur.next; //cur向后走一步
}
if (bs == null) { //说明没有元素小于x
return as; //返回后面的头节点
}
if (as != null) { //当后面存放了元素时
ae.next = null; //注意要手动将尾节点置空
}
be.next = as; //将前后连起来
return bs; //返回前面头节点
}
}
6.判断回文链表
public class PalindromeList {
public boolean chkPalindrome(ListNode head) {
if (head == null) {
return true;
}
//找到中点节点
ListNode fast = head;
ListNode slow = head;
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 (head != slow){
if (head.val != slow.val) {
return false;
}
if (head.next == slow) { //此处是偶数情况
return true;
}
head = head.next;
slow = slow.next;
}
return true;
}
}
7.递归逆序打印链表
递归在C语言中写了不少了,图也没啥好画的,直接上代码~~
public class Test {
/*void printList(ListNode head){
if(null != head){
printList(head.next);
System.out.print(head.val + " ");
}
}*/
public static void printList(ListNode head) {
if (head == null) {
return;
}
if (head.next == null) {
System.out.print(head.val+" ");
return;
}
printList(head.next);
System.out.print(head.val+" ");
}
}
8.相交链表
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) {
return null;
}
ListNode plong = headA;//假设A长B短
ListNode pshort = headB;
//1.分别求两个链表的长度
int len1 = 0;
int len2 = 0;
while (plong != null) {
len1++;
plong = plong.next;
}
while (pshort != null) {
len2++;
pshort = pshort.next;
}
plong = headA;
pshort = headB;
//2.求两个链表的差值
int len = len1 - len2;
if (len < 0) { //说明A短B长
plong = headB;
pshort = headA;
len = len2 - len1;
}
//到这里确保plong指向长链表,len大于0
//3.哪个链表长先走len步
while (len != 0) {
plong = plong.next;
len--;
}
//4.一起走,直到相遇
while (plong != pshort) {
plong = plong.next;
pshort = pshort.next;
}
return plong;
}
}
9.环形链表Ⅰ
public class Solution {
public boolean hasCycle(ListNode head) {
if (head == null) {
return false;
}
ListNode fast = head;
ListNode slow = head;
while (fast != null && fast.next != null) {
fast = fast.next.next; //fast每次走2步
slow = slow.next; //slow每次走1步
if (fast == slow) { //相遇说明一定有环
return true;
}
}
return false;
}
}
10.环形链表Ⅱ
public class Solution {
public ListNode detectCycle(ListNode head) {
if (head == null) {
return null;
}
//找相遇点
ListNode fast = head;
ListNode slow = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if (fast == slow) {
break;
}
}
//判断是否有环
if (fast == null || fast.next == null) {
return null;
}
//fast在起始点,slow在相遇点
fast = head;
//一起走直到相遇就是入口点
while (fast != slow) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
}