203. 这是一道极其经典的题目了算是,考验基本的对链表的理解。在删除链表元素的时候,我们首先需要考虑的就是头尾节点的情况。如果删除的是头节点我们应该怎么返回整个链表?这个时候虚拟头节点的用场就来了,虚拟头节点可以当作是我们整个链表的入口所在地,因为它永远不会被删除!下一步就要进行元素的遍历和删除了,这里也是用到了经典思想双指针!!!用一个快慢指针来遍历整个链表找到需要删除的元素的时候slow指针的next就直接跳到fast指针的next,这个应该就不用多说了,不理解的话可能得去补补链表的数据结构了!
这里我个人需要注意的是理解虚拟头节点dummyNode和慢指针slow两个在刚开始是相等的,因此如果删除的是头节点,首先是改变slow节点的指向next且同时dummyNode的next也是跟着slow变动的,因为此时slow==dummyNode。如果不是头节点,在slow=slow.next的情况下dummuNode没有跟着移动,因此slow != dummNode了此时,也不会随着slow移动,因为虚拟头节点要保持它作为头节点的大哥的位置!(最后要返回dummyNode.next)
public ListNode removeElements(ListNode head, int val) {
ListNode dummyNode = new ListNode(0,head);
ListNode slow = dummyNode;
ListNode fast = head;
while(fast!=null){
if(fast.val == val){
slow.next = fast.next;
}else{
slow = fast;
}
fast = fast.next;
}
return dummyNode.next;
}
203. 这一题嘛不算是算法题目,纯纯就是考验数据结构,本科学的都忘记了补补就行了。这里建议使用双向链表那效率是高很多的,看着答案巩固复习了下链表的结构(还记得本科的时候线下期末手写过双向链表哈哈)。总之,这道题目看看理解就行吧我感觉,真实面试大概率不会考这种,除非面试官想恶心你🤣。
206. 典中典的面试题!这道题目的精髓还是双指针,家人们链表类题目一定要记得虚拟头节点和双指针啊!!!这道题目想出来双指针后应该就不难了,唯一需要注意的就是当你把当前的这个node的指针指向变动时,你需要确保还能找到这个node指针没变动前的指向的node是哪一个这样你才能继续遍历下去(a -> b -> c 变动后 a <- b c 需要用一个tmp先保存c的位置,不然你变动b的指针后就找不到c在哪儿了,也就没办法继续遍历下去了)。
public ListNode reverseList(ListNode head) {
if(head==null || head.next == null) return head;
ListNode pre = null;
ListNode cur = head;
while(cur!=null){
ListNode tmp = cur.next;
cur.next = pre;
pre = cur;
cur=tmp;
}
return pre;
}