Day3 | 203移除链表元素&707设计链表&206反转链表

76 阅读2分钟

移除链表元素 LeetCode 203

题目链接:LeetCode 203 - 简单

思路

看到移除链表中的元素,就直接考虑使用虚拟头指针。

O(n)时间复杂度:

java
/**
 * 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 headNode = new ListNode(0,head);
        ListNode pre = headNode;
        ListNode next = head;
        while(next != null){
            if(next.val == val){
                pre.next = next.next;
                next = pre.next;
                continue;
            }
            pre = next;
            next = pre.next;
        }
        return headNode.next;

    }
}

总结

有不使用虚拟头结点的方法,即用while判断头结点的值是否为val

设计链表 LeetCode 707

题目链接:LeetCode 707 - 中等

思路

看到链表设计的题目时,只想到addAtHead和addAtTail可以使用addAtIndex。

单链表:

java
class ListNode{
    int val;
    ListNode next;
    ListNode(){}
    ListNode(int val){
        this.val = val;
    }
}
class MyLinkedList {
    int size;
    ListNode head;
    public MyLinkedList() {
        size = 0;
        head = new ListNode(0);
    }
    
    public int get(int index) {
        if(index<0 || index>=size){
            return -1;
        }
        ListNode currNode=head;
        for(int i=0;i<=index;i++){
            currNode = currNode.next;
        }
        return currNode.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;
        }
        size++;
        if(index<0){
            index=0;
        }
        ListNode currNode = head;
        for(int i=0;i<index;i++){
            currNode = currNode.next;
        }
        ListNode temp = new ListNode(val);
        temp.next = currNode.next;
        currNode.next = temp;
    }
    
    public void deleteAtIndex(int index) {
        if(index<0 || index>=size){
            return;
        }
        size--;
        ListNode currNode = head;
        for(int i=0;i<index;i++){
            currNode = currNode.next;
        }
        currNode.next = currNode.next.next;
    }
}


总结

  1. 分为单链表和双链表两种解题方式。
  2. 写代码时没有考虑要定义一个ListNode类,这是其一。其二对于index何时等于,何时不取到思维混乱。其三,没有充分考虑到size的增加减少,这是很重要的考虑问题。

反转链表 LeetCode 206

题目链接:LeetCode 206 - 简单

思路

206.png

刚看到反转链表的时候打算使用双指针和虚拟头节点,但是这样子有些繁琐,并且不太便于书写代码。如果选择一个temp节点来存储cur.next的话,在代码书写上会更加简洁。这道题属于高频题。

该题有两种解题思路,递归和遍历。

该题使用遍历的方式会比使用递归的方式更加好写一些。 主要就是: 在遍历链表时 ①存储当前节点的后一个节点(next=cur.next) ②将当前节点的next指针指向前一个节点(cur.next=pre) ③将当前的节点存储为pre ④将next节点存储到cur中

最后返回新的头结点

遍历:

class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode pre = null;
        ListNode cur = head;

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

        return pre;
    }
}

206-2.png

该反转链表使用递归的话:

1.确定递归终止条件:if(head==null||head.next==null){ return head;}

2.确定递归调用:反转链表

3.最后返回新的头结点

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;
    }
}