代码随想录算法训练营第三天| 203.移除链表元素 707.设计链表 206.反转链表

203.移除链表元素

原方法:

  • head是指向头节点的指针
  • 先处理头节点的特殊情况,再判断链表为空,因为可能头节点处理后为空了
  • cur是一个指针,用来遍历链表
class Solution {
    public ListNode removeElements(ListNode head, int val) {
       
        while(head != null && head.val == val){
            head = head.next;
        }

         if(head == null){
            return head;
        }

        ListNode cur = head;
        while(cur.next != null){
            if(cur.next.val == val){
                cur.next = cur.next.next;
            }else{
                cur = cur.next;
            }
        }
        return head;
    }
}

虚拟头节点

  • 加了虚拟头节点就不用单独处理别的情况了
class Solution {
    public ListNode removeElements(ListNode head, int val) {
        
        ListNode dummy =new ListNode();
        dummy.next = head;

        ListNode cur = dummy;
        while(cur.next != null){
            if(cur.next.val == val){
                cur.next = cur.next.next;
            }else{
                cur = cur.next;
            }
        }

        return dummy.next;
    }
}

递归:分三步

  • head代表当前节点,head.next代表下一个节点

  • 如果后续链表已处理好的情况下,如何处理当前节点

  • 基准问题(终止条件):空链表不需要移除元素

  • 分析问题(最简单情况):当节点指向的子链中没有val值时,只用判断自己,若自己不等于val则返回自己,否则返回head.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) {
        //递归方法
        //确定问题:删除链表中的val值,返回新的头节点

        //基准问题:空链表不需要移除元素
        if(head == null){
            return head;
        }

        //分析问题:当节点指向的子链中没有val值时,只用判断自己
        head.next = removeElements(head.next, val);
        if(head.val == val){
            return head.next;
        }else{
            return head;
        }
    }
}

707.设计链表

最痛苦的一集

  • 注意合法条件,index插入时,index可以等于size,相当于尾插
  • java不能用while(i--),不合法
  • 记得更新size
class MyLinkedList {
        class ListNode{
            int val;
            ListNode next;
            ListNode(int val){
                this.val = val;
            }
        } 

         private int size = 0;
         private ListNode dummyhead;

    public MyLinkedList() {
        this.size = 0;
        this.dummyhead = new ListNode(0);
    }
    
    public int get(int index) {
        ListNode cur = dummyhead.next;
        if(index < 0 || index > size - 1){
            return -1;
        }else{
            for(int i = 0; i < index; i++){
                cur = cur.next;
            }
        }
        return cur.val;
    }
    
    public void addAtHead(int val) {
        ListNode newNode = new ListNode(val);
        newNode.next = dummyhead.next;
        dummyhead.next = newNode;
        size++;
    }
    
    public void addAtTail(int val) {
        ListNode cur = dummyhead;
        ListNode newNode = new ListNode(val);
        while(cur.next != null){
            cur = cur.next;
        }
        cur.next = newNode;
        size++;
    }
    
    public void addAtIndex(int index, int val) {
        if(index < 0 || index > size - 1){
            return;
        }
        ListNode cur = dummyhead;
        ListNode newNode = new ListNode(val);

       for(int i = 0; i < index; i++){
            cur = cur.next;
        }
        newNode.next = cur.next;
        cur.next = newNode;
        size++;
    }
    
    public void deleteAtIndex(int index) {
        if(index < 0 || index > size - 1){
            return;
        }
        ListNode cur = dummyhead;
        for(int i = 0; i < index; i++){
            cur = cur.next;
        }
        cur.next = cur.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.反转链表

双指针法

  • cur : 遍历链表
  • pre : 记录cur前面节点地址
  • temp : 记录cur后面节点地址
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode curr = head;
        while(curr != null){
            ListNode next = curr.next;
            curr.next = prev;
            prev = curr;
            curr = next;
        }
        return prev;
    }
}

递归法

  • head代表当前节点,head.next代表下一个节点

  • 确定问题 : 若后续链表反转好的情况下,如何处理自己

  • 基准问题(终止条件) : 当head == null,和head.next == null时不需要操作

  • 分析问题 : 当前节点的后一个节点指向自己,当前节点指向null

class Solution {
    public ListNode reverseList(ListNode head) {
       if(head == null || head.next == null){
        return head;
       }

       ListNode newHead = reverseList(head.next);
       head.next.next = head;
       head.next = null;
       return newHead;
    }
}