链表
1.链表结构定义
public class ListNode {
public int val;
public ListNode next;
public ListNode(int x) {
val = x;
}
@Override
public String toString() {
if (this.next == null) {
return this.val+"";
}
return this.val + "->" + this.next;
}
}
链表删除定值节点
直接操作next指向下一个,为了防止被删除节点是第一个,新增虚拟头节点可以使代码统一
public ListNode deleteNode(ListNode head, int val) {
ListNode result = new ListNode(-1);
ListNode handle = new ListNode(-1);
result.next = handle;
handle.next = head;
while(handle!=null) {
ListNode next = handle.next;
if (next!=null && next.val == val) {
handle.next = next.next;
}
handle = handle.next;
}
return result.next.next;
}
删除倒数第几个节点
快慢指针,一次遍历,找到目标节点,删除
public ListNode removeNthFromEnd(ListNode head, int n) {
// write code here
// input check ?
ListNode handle = new ListNode(-1);
handle.next = head;
ListNode fast = handle;
ListNode slow = handle;
for (int i=0; i < n;i++){
fast = fast.next;
}
// 找到 倒数N
while (fast.next != null){
fast = fast.next;
slow = slow.next;
}
// 跳过倒数N
slow.next = slow.next.next;
return handle.next;
}
反转链表
双指针法,持续维护pre 和 cur两个节点
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode current = head;
while (current !=null)
{
ListNode next = current.next;
current.next = pre;
pre = current;
current = next;
}
return pre;
}
使用递归法,第一次维护一个空的pre
public ListNode reverseList(ListNode head) {
ListNode pre = null;
return revert(pre, head);
}
private ListNode revert(ListNode pre, ListNode head) {
if (head == null) {
return pre;
}
ListNode next = head.next;
head.next = pre;
return revert(head,next);
}
链表找环
是否有环:快慢指针可以相遇,环的入口:在相遇的点,新节点从头开始走,新节点和快指针相遇的地方为环的入口
从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点
if (slow == fast) {
ListNode* index1 = fast;
ListNode* index2 = head;
while (index1 != index2) {
index1 = index1->next;
index2 = index2->next;
}
return index2; // 返回环的入口
}
\