leetcode-zgd-day3-203.移除链表元素/707.设计链表/206.反转链表

1,438 阅读3分钟

203.移除链表元素

题目链接:203. 移除链表元素 - 力扣(LeetCode)

对于链表的题目,主要是分为两种处理方式,一种是创建虚拟头结点的方式,一种是不创建的方式,创建虚拟头结点,其余节点的处理逻辑就可以统一化,不需要单独处理头结点,如果不创建虚拟头结点,那么就需要单独处理虚拟头结点。

带虚拟头结点的写法:

 public ListNode removeElements(ListNode head, int val) {
     // 带头结点的解法
     ListNode nHead = new ListNode(-1, head);
     ListNode p = nHead;
     while(p.next != null){
         if(p.next.val != val){
             p = p.next;
         }
         else{
             p.next = p.next.next;
         }
     }
     return nHead.next;
 }

不带虚拟头结点的写法:

 public ListNode removeElements(ListNode head, int val) {
     //不带头结点的解法
     ListNode p = head;
     while(p != null && p.val == val){
         p = p.next;
     }
     if(p == null) return null;
     else{
         //头结点为p
         ListNode q = p; // 这里又创建一个结点q的原因是需要将p作为头结点返回,因为最初的head可能已经被移除了
         while(q.next != null){
             if(q.next.val != val){
                 q = q.next;
             }
             else{
                 q.next = q.next.next;
             }
         }
     }
     return p;
 }

707.设计链表

题目链接:Loading Question... - 力扣(LeetCode)

该题目就是实现以下链表中的函数

单链表的实现方法如下:

  单链表实现
 class ListNode{
     int val;
     ListNode next;
     ListNode(){}
     ListNode(int val){
         this.val = val;
     }
 }
 class MyLinkedList {
     // 链表的长度,方便addAtTail
     int size;
     // 虚拟头节点
     ListNode head;
 ​
     ListNode p;
 ​
     public MyLinkedList() {
         head = new ListNode(-1);
         size = 0;
     }
 ​
     public int get(int index) {
         if(index < 0 || index >= size) return -1;
          p = head;
         while(index > -1){
             p = p.next;
             index--;
         }
         return p.val;
     }
 ​
     public void addAtHead(int val) {
         ListNode hnode = new ListNode(val);
         hnode.next = head.next;
         head.next = hnode;
         size++;
     }
 ​
     public void addAtTail(int val) {
          p = head;
         while(p.next != null){
             p = p.next;
         }
         ListNode tnode = new ListNode(val);
         p.next = tnode;
         size++;
     }
 ​
     public void addAtIndex(int index, int val) {
         if(index <= 0){
             addAtHead(val);
             return;
         }
         if(index > size) return;
         if(index == size){
             addAtTail(val);
             return;
         }
         p = head;
         while(index > 0){
             p = p.next;
             index--;
         }
         ListNode iNode = new ListNode(val);
         iNode.next = p.next;
         p.next = iNode;
         size++;
     }
 ​
     public void deleteAtIndex(int index) {
         if(index < 0 || index >= size) return;
          p = head;
         while(index > 0){
             p = p.next;
             index--;
         }
         p.next = p.next.next;
         size--;
     }
 }

双链表的实现方式如下:

     // 双链表实现
 class ListNode{
      int val;
      ListNode next,pre;
      ListNode(){}
      ListNode(int val){
         this.val = val;
      }
 }
 class MyLinkedList {
     // 链表的长度,方便addAtTail
     int size;
     // 虚拟头节点
     ListNode head;
     // 虚拟尾节点
     ListNode tail;
 ​
     ListNode p;
 ​
     public MyLinkedList() {
         head = new ListNode(-1);
         tail = new ListNode(-1);
         head.next = tail;
         tail.pre = head;
         size = 0;
     }
 ​
     public int get(int index) {
         if(index < 0 || index >= size) return -1;
         p = head;
         while(index > -1){
             p = p.next;
             index--;
         }
         return p.val;
     }
 ​
     public void addAtHead(int val) {
         ListNode hnode = new ListNode(val);
         hnode.next = head.next;
         hnode.next.pre = hnode;
         head.next = hnode;
         hnode.pre = head;
         size++;
     }
 ​
     public void addAtTail(int val) {
         ListNode tnode = new ListNode(val);
         tnode.next = tail;
         tnode.pre = tail.pre;
         tnode.pre.next = tnode;
         tail.pre = tnode;
         size++;
     }
 ​
     public void addAtIndex(int index, int val) {
         if(index <= 0){
             addAtHead(val);
             return;
         }
         if(index > size) return;
         if(index == size){
             addAtTail(val);
             return;
         }
         p = head;
         while(index > 0){
             p = p.next;
             index--;
         }
         ListNode iNode = new ListNode(val);
         iNode.next = p.next;
         iNode.next.pre = iNode;
         p.next = iNode;
         iNode.pre = p;
         size++;
     }
 ​
     public void deleteAtIndex(int index) {
         if(index < 0 || index >= size) return;
         p = head;
         while(index > 0){
             p = p.next;
             index--;
         }
         p.next = p.next.next;
         p.next.pre = p;
         size--;
     }
 }

该题目需要留意的一点是代码复用的问题,前面实现的功能在后续的代码功能实现中是否可以复用,这个是值得思考的一个问题。

206.反转链表

题目链接:206. 反转链表 - 力扣(LeetCode)

带头结点的版本:

 public ListNode reverseList(ListNode head) {
     // 带头结点的版本
     if(head == null || head.next == null) return head;
     ListNode nHead = new ListNode(-1);
     ListNode p = head;
     while(p != null){
         ListNode q = p.next;
         p.next = nHead.next;
         nHead.next = p;
         p = q;
     }
     return nHead.next;
 }

不带头结点的版本:

 public ListNode reverseList(ListNode head) {
     // 不带头结点的版本
     if(head == null || head.next == null) return head; 
     ListNode p = head; // p永远是断链前面那段的头结点,q是锻炼后那段的头结点
     ListNode q = p.next;
     p.next = null;
     while(q != null){
         ListNode r = q.next;
         q.next = p;
         p = q;
         q = r;
     }
     return p;
 }

\