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

111 阅读1分钟

203. Remove Linked List Elements Given the head of a linked list and an integer val, remove all the nodes of the linked list that has Node.val == val, and return the new head.

 

Example 1:

Input: head = [1,2,6,3,4,5,6], val = 6
Output: [1,2,3,4,5]

Example 2:

Input: head = [], val = 1
Output: []

Example 3:

Input: head = [7,7,7,7], val = 7
Output: []

 

Constraints:

  • The number of nodes in the list is in the range [0, 104].
  • 1 <= Node.val <= 50
  • 0 <= val <= 50

这题是关于基础链表操作,基本上就是扫描链表,检查数值,如符合,则令当前节点cur的前一节点prev的next指针,指向当前节点cur的next节点。所以在循环的每一层,需要保留前一节点的指针prev。

有几个细节需要注意:

  1. 需要删除的节点为head,怎么处理。这时候设立一个虚假的头节点,指向head,会很有帮助。可以让每层循环的逻辑一致。否则需要加入头部检查处理和重新赋值的逻辑。最后,返回dummy.next即为新head。
  2. 删除节点时,赋值要注意顺序。顺序为:prev.next = cur.next; prev = cur; cur = cur.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) {
        ListNode cur = head;
        ListNode prev = head;
        ListNode dummy = new ListNode();

        dummy.next = head;
        prev = dummy;

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

            cur = cur.next;
        }

        return dummy.next;


    }
}

707. Design Linked List Design your implementation of the linked list. You can choose to use a singly or doubly linked list.
A node in a singly linked list should have two attributes: val and nextval is the value of the current node, and next is a pointer/reference to the next node.
If you want to use the doubly linked list, you will need one more attribute prev to indicate the previous node in the linked list. Assume all nodes in the linked list are 0-indexed.

Implement the MyLinkedList class:

  • MyLinkedList() Initializes the MyLinkedList object.
  • int get(int index) Get the value of the indexth node in the linked list. If the index is invalid, return -1.
  • void addAtHead(int val) Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list.
  • void addAtTail(int val) Append a node of value val as the last element of the linked list.
  • void addAtIndex(int index, int val) Add a node of value val before the indexth node in the linked list. If index equals the length of the linked list, the node will be appended to the end of the linked list. If index is greater than the length, the node will not be inserted.
  • void deleteAtIndex(int index) Delete the indexth node in the linked list, if the index is valid.

这题要写的代码不少,逻辑处理要很小心。

首先是否要定义自己的链表结构,其实也可以直接使用MyLinkedList class作为链表结构,但代码逻辑会有点乱,因为val,next,dummy header全都要堆在一起。还是定义一个子class ListNode为好。 使用虚假头部dummyHead会让逻辑思路变得很清晰。尤其在实现void addAtIndex(int index, int val)时,要注意要求是插入index元素之前而不是之后,index可以超出链表最大index,达到max index + 1,这时候要将新节点插入到尾部。而void deleteAtIndex(int index) 是不可能处理max index + 1的情况,但这两个函数的循环结束条件却是一样的,在末尾端要考虑清楚。。

代码:

class MyLinkedList {
    class ListNode {
        public ListNode() {val = 0; next = null;}
        public ListNode(int v) { val = v; next = null;}
        private int val;
        private ListNode next;
    }

    public MyLinkedList() {
        dummy = new ListNode();
        size = 0;
    }
    
    public int get(int index) {
        ListNode cur = dummy;

        if(index < 0 || index >= size) {
            return -1;
        }
        int pos = 0;
        while(pos <= index) {
            cur = cur.next;
            pos++;
        }

        return cur.val;

    }
    
    public void addAtHead(int val) {
        ListNode ent = new ListNode(val);

        ent.next = dummy.next;
        dummy.next = ent;
        size++;
    }
    
    public void addAtTail(int val) {
        ListNode ent = new ListNode(val);

        ListNode cur = dummy;

        while(cur.next != null) {
            cur = cur.next;
        }

        cur.next = ent;
        ent.next = null;

        size++;

    }
    
    public void addAtIndex(int index, int val) {
        if(index > size || index < 0) {
            return;
        }

        ListNode cur = dummy;
        ListNode ent = new ListNode(val);

        int pos = 0;

        while(pos < index) {
            cur = cur.next;
            pos++;
        }

        ent.next = cur.next;
        cur.next = ent;

        size++;
    }
    
    public void deleteAtIndex(int index) {
        if(index >= size || index < 0) {
            return;
        }

        ListNode cur = dummy;
        int pos = 0;

        while(pos < index) {
            cur = cur.next;
            pos++;
        }

        if (cur.next != null){
            cur.next = cur.next.next;
            size--;
        }

    }
    private int size;
    private ListNode dummy;
}

/**
 * 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. Reverse Linked List Given the head of a singly linked list, reverse the list, and return the reversed list.

 

Example 1:

Input: head = [1,2,3,4,5]
Output: [5,4,3,2,1]

这题不难但也有一些小细节。很容易想到思路就是以节点指针cur从head开始扫描,在每一次循环内部,将cur.next指向它的前一节点prev,但要注意改变cur.next之后,cur就无法定位到它的下一个节点,所以要在赋值之前用temp保存cur.next,然后在循环结束前将cur 赋值为temp。 这题有双指针和递归两种写法。递归更简洁。双指针我使用了dummy head,也可以不用。 递归:

/**
 * 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 reverseHelper(ListNode cur, ListNode pre) {
        if(cur == null) {
            return pre;
        }
        ListNode next = cur.next;
        cur.next = pre;

        return reverseHelper(next, cur);
    }
    public ListNode reverseList(ListNode head) {
        if(head == null) {
            return null;
        }

        return reverseHelper(head, null);

    }
}

双指针(感觉也算是三指针)

class Solution { public ListNode reverseList(ListNode head) { if(head == null) { return null; } ListNode dummy = new ListNode(-1, head);

    ListNode cur = head;
    ListNode prev = dummy;
    ListNode lat = null;

    while(cur != null) {
        lat = cur.next;
        cur.next = prev;
        prev = cur;
        cur = lat;
    }
    //cur.next = prev;
    dummy.next.next = null;
    return prev;

}

}