重生之我在代码随想录刷算法第三天 | 203. 移除链表元素、707.设计链表、 206.反转链表

64 阅读4分钟

参考文献链接:代码随想录

本人代码是Java版本的,如有别的版本需要请上代码随想录网站查看。

203. 移除链表元素

[力扣题目链接](leetcode.cn/problems/bi…)

解题思路

这道题目还是比较简单的,目的是为了练习链表的删除操作。题目简要意思就是把链表中对应值的节点删除。

还记得第一次做这道题的时候一看题目这么简单,不就是把上一个节点的next指向下一个节点吗,结果操作一顿之后发现还是不能通过。后来看了题解才明白。

这次做的话就很清晰了,在思考这类问题时要多想想头和尾这些特殊部位。比如这道题的头节点都没有上一个节点,你还怎么让他的上一个节点指向下一个节点呢?

所以要么特殊处理,要么加入虚拟头节点

虚拟头节点

虚拟头节点的意思就是去给当前链表加一个头节点,这样你的剩余节点都可以当作普通节点处理。

代码如下

 /**
  * Definition for singly-linked list.
  * 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; }
  * }
  */
 class Solution {
     public ListNode removeElements(ListNode head, int val) {
             if(head == null){
                 return head;
             }
             //定义一个虚拟头节点,让其指向head真正的头节点  
             ListNode vir = new ListNode();
             vir.next = head;
             //定义一个临时节点去进行循环操作
             ListNode tmp = vir;
             while(tmp.next != null){
                 //如果临时节点的下一个节点val值等于目标值,那么就进行删除操作。
                 if(tmp.next.val == val){
                     tmp.next = tmp.next.next; 
                 }else{
                     //否则tmp++
                     tmp = tmp.next;
                 }
                 千万不要把else忘记,我做的时候以为不管怎么样都得tmp++,后来思考发现如果进行了删除操作后,那么tmp的下一个节点变化了,还得继续判断它,不能tmp++。
                 
             }
             return vir.next;
     }
 }

707.设计链表

力扣题目链接

解题思路

这道题目是刚接触链表一个很好的练手题,因为它涵盖了链表几乎所有操作。我们直接来上代码吧!

代码

要学会怎么定义链表,平时做题都是力扣帮忙定义好了,但面试万一不会定义就糟糕了。

其实只要明白了一个方法,其余的相差无几。中心思想就是通过节点.next去移动,直到自己想操作的位置进行操作,思路简单,注意一些特殊位置的判断即可

 class ListNode {
     int val;
     ListNode next;
     ListNode(){}
     ListNode(int val) {
         this.val=val;
     }
 }
 ​
 class MyLinkedList {
     //长度
     int size;
 ​
     //虚拟头节点
     //为了操作方便统一我们还是引入虚拟头节点
     ListNode head;
     
     public MyLinkedList() {
         //初始化,size为0,只有一个虚拟头节点
         size = 0;
         head = new ListNode();
     }
     
     public int get(int index) {
         //判断index的合法性
         if(index < 0 || index >= size){
             return -1;
         }
         //通过index移动tmp,直到想要的节点
         ListNode tmp = head.next;
         for(int i = 0;i < index;i++){
             tmp = tmp.next;
         }
         return tmp.val;
     }
     
     public void addAtHead(int val) {
         //虚拟头节点立大功,不用考虑别的,直接添加即可
         ListNode add = new ListNode(val);
         ListNode tmp = head.next;
         head.next = add;
         add.next = tmp;
         size++;
     }
     
     public void addAtTail(int val) {
         //如果size为0,直接交给头节点处理就好
         if(size == 0){
             addAtHead(val);
             return;
         }
         //其实跟get方法本质一样,移动到相应位置进行操作即可
         ListNode tmp = head.next;
         for(int i = 0;i < size - 1;i++){
             tmp = tmp.next;
         }
         tmp.next = new ListNode(val);
         size++;
     }
     
     public void addAtIndex(int index, int val) {
         if(index > size){
             return;
         }
         if(index == 0){
             addAtHead(val);
             return;
         }
         ListNode tmp = head.next;
         for(int i = 0;i < index - 1;i++){
             tmp = tmp.next;
         }
         ListNode next = tmp.next;
         tmp.next = new ListNode(val);
         tmp.next.next = next;
         size++;
     }
     
     public void deleteAtIndex(int index) {
         if(index < 0 || index >= size){
             return;
         }
         ListNode tmp = head;
         for(int i = 0;i < index;i++){
             tmp = tmp.next;
         }
         tmp.next = tmp.next.next;
         size--;
     }
 }
 ​
 /**
  * Your MyLinkedList object will be instantiated and called as such:
  * MyLinkedList obj = new MyLinkedList();
  * int param_1 = obj.get(index);
  * obj.addAtHead(val);
  * obj.addAtTail(val);
  * obj.addAtIndex(index,val);
  * obj.deleteAtIndex(index);
  */

206.反转链表

力扣题目链接

解题思路

对于这种反转类的题目我想到的是栈和递归法。具体如何反转很简单,难的是想法和栈的使用。

首先先介绍一下栈的概念和基本使用:

它是Package java.util下的Class Stack,它是一个先进后出的数据结构。

image-20240913203156941

构造方法:

Stack() Creates an empty Stack.

方法

Modifier and TypeMethodDescription
booleanempty()判断栈是否为空
Epeek()查看栈顶部的对象并返回
Epop()移除栈顶部的对象并返回
Epush(E item)压栈:将一个元素放入栈顶
intsearch(Object o)查找对象。

相信看完这些官方api就很好解决这道题目了

代码如下:

 /**
  * Definition for singly-linked list.
  * 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; }
  * }
  */
 class Solution {
     public ListNode reverseList(ListNode head) {
         if(head == null){
             return head;
         }
         Stack<ListNode> stack = new Stack<>();
         //将每个节点依次放入栈中
         while(head != null){
             stack.push(head);
             head = head.next;
         }
         //创建新的头节点,并依次接收弹出的元素排成新的链表
         ListNode newHead = stack.pop();
         ListNode tmp = newHead; 
         while(stack.size()!=0){
             tmp.next = stack.pop();
             tmp = tmp.next;
             if(stack.size()==0){
                 tmp.next = null;
             }
 ​
         }
         return newHead;
     }
 }

递归法

 /**
  * Definition for singly-linked list.
  * 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; }
  * }
  */
 class Solution {
     public ListNode reverseList(ListNode head) {
         reverse(null,head);
     }
     public ListNode reverse(ListNode pre,ListNode cur){
         if(cur == null){
             return pre;
         }
         ListNode tmp = cur.next;
         cur.next = pre;
         pre = cur;
         cur = tmp;
         return reverse(pre,cur);
     }
 }