算法第三天 —— 移除链表元素、反转链表、设计链表

86 阅读2分钟

移除链表元素

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点

解题思路: 这个题主要是删除head的下一个元素,需要考虑到删除头结点以及非头结点的问题

 public ListNode removeElements(ListNode head, int val) {
         // 如果是头结点,删除头结点
         while (head != null && head.val == val) {
             head = head.next;
         }
         if (head == null) return head;
         ListNode pre = head;
         ListNode cur = head.next;
 ​
         while (cur != null) {
             if (cur.val == val) {
                 pre.next = cur.next;
             } else {
                 pre = cur;
             }
             cur = cur.next;
         }
         return head;
     }
 ​
 ​
     /**
      * 使用虚拟节点的方式
      */
     public ListNode removeEle(ListNode head, int val) {
         if (head == null) {
             return head;
         }
 ​
         ListNode dummy = new ListNode(-1, head);
         ListNode pre = dummy;
         ListNode cur = head;
 ​
         while (cur != null) {
             if (cur.val == val) {
                 pre.next = cur.next;
             } else {
                 pre = cur;
             }
             cur = cur.next;
         }
 ​
         return dummy.next;
     }

704设计链表

设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。

 public class ListNode {
 ​
     public ListNode() {
 ​
     }
 ​
     // 存储的元素个数
     int size;
     // 虚拟头结点
     ListNode head;
 ​
     public int get(int index) {
         if (index < 0 || index > size) return -1;
         ListNode currentHead = this.head;
         for (int i = 0; i <= index; i++) {
             currentHead = currentHead.next;
         }
         return currentHead.val;
     }
 ​
     public void addAtHead(int val) {
         addAtIndex(0, val);
     }
 ​
     public void addAtTail(int val) {
         addAtIndex(size, val);
 ​
     }
 ​
     public void addAtIndex(int index, int val) {
         // 排除
         if (index > size) return;
         if (index < 0) {
             index = 0;
         }
         size++;
 ​
         // 找到插入的前驱节点
         ListNode pre = head;
         for (int i = 0; i < index; i++) {
             pre = pre.next;
         }
         ListNode addNode = new ListNode(val);
         addNode.next = pre.next;
         pre.next = addNode;
 ​
     }
 ​
     public void deleteAtIndex(int index) {
         if (index < 0 || index >= size) return;
 ​
         size--;
 ​
         ListNode pred = head;
         for (int i = 0; i < index; i++) {
             pred = head.next;
         }
         pred.next = pred.next.next;
     }
 }
 ​
 ​

206 反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

 ​
     /**
      * 双指针的方法
      * 1.先保存下一个节点
      * 2. 当前位置的元素反转下
      * 3. 首先移动当前node的前一个
      * 4. 移动当前node到下一位
      *
      * @param head
      * @return
      */
     public ListNode reverseList(ListNode head) {
         ListNode pre = null;
         ListNode cur = head;
         ListNode temp = null;
 ​
         while (cur != null) {
             temp = cur.next;
             cur.next = pre;
             // 移动pre cur的指针,一定注意两个顺序
             pre = cur;
             cur = temp;
         }
         return pre;
     }
 ​
     public ListNode reverseNode(ListNode head) {
         return reverse(null, head);
     }
 ​
     public ListNode reverse(ListNode pre, ListNode cur) {
         if (cur == null) {
             return pre;
         }
         ListNode temp = null;
         temp = cur.next; //先保存下一个节点
         cur.next = pre; // 反转
         return reverse(cur, temp);
     }