算法day03 | 链表 | 203.移除链表元素,707.设计链表,206.反转链表

52 阅读2分钟

java链表相关

节点定义:

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

节点声明:

ListNode h = new ListNode();

ListNode h = new ListNode(-1);

ListNode h = new ListNode(-1, head);

前两种如果需要使用next节点,需要单独说明

# 203.移除链表元素

总结:虚拟头结点的使用技巧

  • 第一次写,出错: 太自信了,完全没带脑子写呢……
class Solution {
    public ListNode removeElements(ListNode head, int val) {
        ListNode h = new ListNode(-1, head);
        ListNode tmp = h;
        while(tmp.next != null) {
            if(tmp.next.val == val) {
                tmp.next = tmp.next.next;
            }
            tmp = tmp.next;
        }

        return h.next;
    }
}
  • 正确解法:
class Solution {
    public ListNode removeElements(ListNode head, int val) {
        ListNode h = new ListNode(-1, head);
        ListNode tmp = h;
        while(tmp.next != null) {
            if(tmp.next.val == val) {
                tmp.next = tmp.next.next;
            } else {
                tmp = tmp.next;
            }
        }

        return h.next;
    }
}

707.设计链表

问题:

① java相关链表操作忘干净了。

② 没审题,题目明确说明:假设链表中的所有节点下标从 0 开始。

③ 觉得很奇怪,分不清class ListNode和class MyLinkedList的区别。前者只是定义链表中每个的节点的内容,后者定义的是链表类。

看了思路之后开始写,但报错。

技巧总结:addAtHead、addAtTail可以合并到 addAtIndex方法中

class ListNode {
    int val;
    ListNode next;
    ListNode() {}
    ListNode(int val) {
        this.val=val;
    }
}
//注意节点编号从0开始,我们自己设置的head不是第0个
class MyLinkedList {

    int size;
    ListNode head;

    public MyLinkedList() {
        head = new ListNode(0);
        size = 0;
    }
    
    //获取第index个节点的数值,注意index是从0开始的,第0个节点就是头结点
    public int get(int index) {
        if(index < 0 || index >= size) {
            return -1;
        }
        ListNode cur = head;
        //找到第index-1个节点
        // 因为index从0开始
        for(int i = 0; i < index; i++) {
            cur = cur.next;
        }
        return cur.next.val;
    }
    
    public void addAtHead(int val) {
        ListNode tmp = new ListNode(val);
        tmp.next = head.next;
        head.next = tmp;
        size++;
    }
    
    public void addAtTail(int val) {
        ListNode newNode = new ListNode(val);
        newNode.next = null;

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

        cur.next = newNode;
        size++;
    }
    
    public void addAtIndex(int index, int val) {
        if( index < 0 || index > size) {
            return;
        }
        ListNode newNode = new ListNode(val);
        
        ListNode cur = head;
        for(int i=0; i<index;i++) {
            cur = cur.next;
        }
        newNode = cur.next; //这里写错了,改成newNode.next = cur.next;就可以了
        cur.next = newNode;
        size++;
    }
    
    public void deleteAtIndex(int index) {
        if(index < 0 || index >= size) {
            return;
        }

        ListNode cur = head;
        for(int i=0; i<index; i++) {
            cur = cur.next;
        }
        cur.next = cur.next.next;
        size--;
    }
}

206.反转链表

对啦,终于出现写过并改正的题重新写对的情况。

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

        ListNode p1 = null;
        ListNode p2 = head;
        // p2.next
        ListNode tmp = p2.next;
        while(tmp != null) {
            p2.next = p1;
            p1 = p2;
            p2 = tmp;
            tmp = tmp.next;
        }
        p2.next = p1;
        return p2;
    }
}

优化:

其实while的条件 为 while(p2!=null)更合理,这样还能少一步p2.next = p1;