一、逆置反转单链表
例如:操作前:1 2 3 4 null
操作后: 4 3 2 1 null
方法一:
public ListNode reverseList_01(ListNode head) {
ListNode result = null;
ListNode cur = head;
while (cur != null) {
ListNode node = cur.next;
cur.next = result;
result = cur;
cur = node;
}
return result;
}
方法二:
public ListNode reverseList_02(ListNode head) {
ListNode prev = null;
ListNode cur = head;
ListNode next = head.next;
while (cur != null) {
cur.next = prev;
//整体后移
prev = cur;
cur = next;
if (next != null) {
next = next.next;
}
}
return head;
}
二、删除链表中等于给定值 val 的所有节点
方法一:
1、创建一个新的链表 result
每遍历一个结点 拿去与 val 比较
如果不相等 则尾插到 result 中
相等则继续往后走
//思路与第一题雷同
public ListNode removeElements(ListNode head, int val) {
ListNode result = null;
ListNode cur = head;
ListNode lastNode = null;//结果链表的最后一个结点
while (cur != null) {
ListNode node = cur.next;
if (cur._value != val) {
// cur.next = null;
if (result == null) {
result = cur;
} else {
lastNode.next = cur;
}
lastNode = cur;//更新:此时链表的最后一个结点变成了刚刚尾插进来的cur
}
cur = node;
}
return result;
}
方法二:
就地查找并删除
public ListNode removeElements111(ListNode head, int val) {
ListNode cur = head.next;
ListNode pre = head;
if (head == null) {
return null;
}
while (cur != null) {
if (cur._value == val) {
//如果是则删除(跳过)该结点pre.next 便指向 cur.next;
pre.next = cur.next;
cur = cur.next;
continue;
}
pre = cur;//更新
cur = cur.next;
}
return head;
}
三、以给定值x为基准将链表分割成两部分所有小于x的结点排在大于或等于x的结点之前
且顺序不变
例如:操作前: 3 5 2 1 4 8 x=5
操作后: 3 2 1 4 5 8
public ListNode fenGe(ListNode pHead, int x) {
ListNode small = null;
ListNode smallLast = null;
ListNode big = null;
ListNode bigLast = null;
ListNode cur = pHead;
while (cur != null) {
ListNode next = cur.next;
// 小于 x,尾插到 small,大于等于 x,尾插到 big
if (cur._value < x) {
cur.next = null;
if (small == null) {
small = cur;
} else {
smallLast.next = cur;
}
smallLast = cur;
} else {
cur.next = null;
if (big == null) {
big = cur;
} else {
bigLast.next = cur;
}
bigLast = cur;
}
cur = cur.next;
}
/**
* 合并small 与 big 两个链表
*/
//如果有链表为空
if (small == null) {
return big;
} else {
smallLast.next = big;
return small;
}
}
}
四、删除所有重复的value
/**
* 例如:删除前:1 3 3 4 5 5 6
* 删除后:1 4 6
*/
public ListNode deletDoplicate(ListNode head) {
if (head == null) {
return null;
}
//创建一个假结点,用于Prev所指
/**
* 创建假结点,便于处理 第一个结点重复,需删除的情况
* 消除第一个结点没有前驱的特殊性
*/
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode prev = dummy;// prev 永远是 p1 的前驱结点,用来删除结点
ListNode p1 = head;
ListNode p2 = head.next;
while (p2 != null) {
//在不重复的情况下,三个引用 同时往后走
if (p1._value != p2._value) {
p1 = p1.next;
p2 = p2.next;
prev = prev.next;
} else {
//一但重复,则p2后走,p1不动,继续比较,直到不等,进行删除
while (p2 != null && p2._value == p1._value) {
p2 = p2.next;
}
prev.next = p2;
p1 = p2;
}
if (p2 != null) {
p2 = p2.next;
}
}
return dummy.next;
}
五、合并两个有序链表,合并完依然有序
/**
* 创建一个新链表result
* 比较L1.value 与L2.value
* 谁小谁尾插到result上
*/
例如:L1:1 3 5 6
L2:1 2 6 8
result:1 1 2 3 5 6 6 8
public ListNode mergeTwoLists(ListNode L1, ListNode L2) {
ListNode cur1 = L1;
ListNode cur2 = L2;
ListNode result = null;// 结果链表的第一个结点
ListNode last = null; // 结果链表的最后一个结点
//有一条为空,就直接返回另一条
if (L1 == null) {
return L2;
}
if (L2 == null) {
return L1;
}
while (cur1 != null && cur2 != null) {
if (cur1._value <= cur2._value) {
// 1. 让 cur1 可以在运行后执行 原 cur1 的下一个结点
// 2. 让 cur1 尾插到 [result, last] 链表上
// 3. 更新 last
ListNode node = cur1.next;
// 把 cur1 尾插到 result 上
//cur1.next = null;
if (result == null) {
// result 链表中没有结点
result = cur1;
} else {
// result 链表中有结点
last.next = cur1;
}
last = cur1; // 更新最后一个结点记录
cur1 = node;
} else {
ListNode next = cur2.next;
// 把 cur2 尾插到 result 上
//cur2.next = null;
if (result == null) {
result = cur2;
} else {
last.next = cur2;
}
last = cur2;
cur2 = next;
}
}
//当其中一条链表走到空时,直接将另一条结点剩下的结点尾插到结果链表中
if (cur1 != null) {
last.next = cur1;
}
if (cur2 != null) {
last.next = cur2;
}
return result;
}