剑指offer面试题13 在O(1)时间删除链表结点

考察点

链表

知识点

链表的删除正常情况下需要O(n)的时间,因为需要找到待删除结点的前置结点

题目

分析
我们都知道链表删除往往需要O(n)遍历链表,找到待删除结点的前置结点,把前置结点的next指针指向待删除结点的后置结点。现在要求O(1)时间删除,那肯定不能用遍历的办法了,试想一下一个结点包括一个值和指向下一个结点的指针,如果把待删除结点的后置结点的值复制到待删除结点这里,然后删除掉待删除结点的后置结点其实就相当于把待删除结点删除掉了。其中有俩个特殊场景需要注意:如果待删除的结点是尾结点则只能按照遍历的方式删除,如果待删除的结点是头结点则在删除的时候也需要把头结点置空

public class LinkNode {
	int val;
	LinkNode next;

	public LinkNode(int data) {
		this.val = data;
		this.next = null;
	}
}
import java.util.Deque;
import java.util.LinkedList;

public class LinkList {
	LinkNode head;
	public LinkList() {
		this.head = null;
	}
	public LinkNode getNode(int cnt) {
		if (this.head == null) {
			return null;
		}
		LinkNode cur = this.head;
		while(cur != null && cnt > 1) {
			cur = cur.next;
			cnt --;
		}
		return cur;
	}
	//o(1)方式删除元素
	public void deleteLinkNode(LinkNode pDelete) {
		if (this.head == null || pDelete == null) {
			return;
		}
		//只有一个头结点
		if (this.head.next == null && this.head == pDelete) {
			this.head = null;
			pDelete = null;
			return;
		}
		//删除的是尾结点
		if (pDelete.next == null) {
			LinkNode cur = this.head;
			while (cur.next != pDelete) {
				cur = cur.next;
			}
			cur.next = null;
			pDelete = null;
			return;
		}
		LinkNode tmp = pDelete.next;
		pDelete.val = tmp.val;
		pDelete.next = tmp.next;
		tmp = null;
	}
	//添加元素
	public void addNode(int data) {
		LinkNode node = new LinkNode(data);
		if (this.head == null) {
			this.head = node;
		} else {
			LinkNode cur = this.head;
			while(cur.next != null) {
				cur = cur.next;
			}
			cur.next = node;
		}
	}
	//正序打印
	public void print() {
		LinkNode node = this.head;
		while(node != null) {
			System.out.print(node.val);
			System.out.print(" ");
			node = node.next;
		}
		System.out.println();
	}
	//倒序打印
	public void reversePrint() {
		Deque<Integer> stack = new LinkedList<>();
		LinkNode cur = this.head;
		while(cur != null) {
			stack.push(cur.val);
			cur = cur.next;
		}
		while(stack.size() > 0) {
			System.out.print(stack.peek());
			System.out.print(" ");
			stack.pop();
		}
		System.out.println();
	}
	//删除元素
	public void deleteNode(int data) {
		if (this.head != null) {
			LinkNode pDelete = null;
			if (this.head.val == data) {
				pDelete = this.head;
				this.head = this.head.next;
			} else {
				LinkNode cur = this.head;
				while(cur.next != null && cur.next.val != data) {
					cur = cur.next;
				}
				if (cur.next != null && cur.next.val == data) {
					pDelete = cur.next;
					cur.next = cur.next.next;
				}
			}
			if (pDelete != null) {
				pDelete = null;
			}
		}

	}
}
public class Thirteen {
	public static void main(String[] args) {
		LinkList linkList = new LinkList();
		linkList.addNode(1);
		linkList.addNode(2);
		linkList.addNode(3);
		linkList.addNode(4);
		linkList.addNode(5);
		linkList.print();
		LinkNode p = linkList.getNode(2);
		if (p != null) {
			linkList.deleteLinkNode(p);
			linkList.print();
		}
		LinkNode tailNode = linkList.getNode(4);
		if (tailNode != null) {
			linkList.deleteLinkNode(tailNode);
			linkList.print();
		}
		LinkNode headNode = linkList.getNode(1);
		if (headNode != null) {
			linkList.deleteLinkNode(headNode);
			linkList.print();
		}
		p = linkList.getNode(2);
		if (p != null) {
			linkList.deleteLinkNode(p);
			linkList.print();
		}
		LinkNode singleHeadNode= linkList.getNode(1);
		if (singleHeadNode != null) {
			linkList.deleteLinkNode(singleHeadNode);
			linkList.print();
		}
	}
}

你可能感兴趣的:(剑指offer,java版,链表,数据结构,java,面试,leetcode)