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

Posted 蔚尺丈八声

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了代码随想录算法训练营第三天 | 203.移除链表元素707.设计链表 206.反转链表相关的知识,希望对你有一定的参考价值。

移除链表元素

【力扣】203.移除链表元素

/**
 * 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 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) 
        /*
         * 思路:添加一个虚拟头结点
         * 参考:
         * https://leetcode.cn/problems/remove-linked-list-elements/solutions/10957/203yi-chu-lian-biao-yuan-su-by-lewis-dxstabdzew/
         * https://www.bilibili.com/video/BV18B4y1s7R9/?vd_source=accc6a9ec558fa81b34f121125d4eff0
         *
         *
         * 对于链表,主要掌握添加一个虚拟结点的操作,才能统一删除第一个结点
         * 和除第一个结点外其他结点的操作。
         * 注意删除结点的核心语句cur.next = cur.next.next;
         * 
         */

        // 设置一个虚拟头结点,便于统一操作
        ListNode dummNode = new ListNode(0);
        dummNode.next = head;

        // 指向当前结点
        // 删除结点时必须知道它的前一个结点,如果是删除第一个结点,
        // 就需要知道dummyNode,所以最开始要用cur指向dummyNode而不是dummyNode.next
        ListNode cur = dummNode;
        // 确保当前结点后还有结点
        while (cur.next != null) 
            // 如果碰到相同的值,则跳过,否则继续向下遍历
            if (cur.next.val == val) 
                cur.next = cur.next.next;
             else 
                cur = cur.next;
            
        

        return dummNode.next; // 删除虚拟头结点
    

设计链表

【力扣】707. 设计链表

// class ListNode 
//     int val;
//     ListNode next;

//     ListNode() 
//     

//     ListNode(int val) 
//         this.val = val;
//     
// 

class MyLinkedList 
    /*
     * 思路:
     * 
     * 参考:
     * https://programmercarl.com/0707.%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8.html#%E5
     * %85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC
     * 
     * 注意链表的index是从0开始计数的
     * 
     * 本题的不同方法:
     * 1、get:直接遍历到index的位置,返回该位置的元素。
     * 2、addAtHead:相当于在index=0的位置插入元素,即addAtIndex(0,val)
     * 3、addAtTail:相当于在index=链表长度的位置插入元素addAtIndex(链表长度),val)
     * 4、addAtIndex:排除异常情况,然后先遍历到index-1的位置,再在index处插入元素
     * 5、deleteAtIndex:排除异常情况,然后先遍历到index-1的位置,再在index处删除元素
     */

    ListNode head; // 虚拟头结点
    int size; // 链表长度

    public MyLinkedList() 
        head = new ListNode(0);
        size = 0;
    

    public int get(int index) 

        // 排除异常:索引无效(注意链表结点的索引是0,1,……size-1,位置size没有结点)
        if (index < 0 || index >= size) 
            return -1;
        

        ListNode cur = head; // 所遍历的结点
        // 注意为了遍历到index的位置,循环条件是i<=index,不是i<index
        for (int i = 0; i <= index; i++) 
            cur = cur.next;
        
        return cur.val;
    

    public void addAtHead(int val) 
        addAtIndex(0, val);
    

    public void addAtTail(int val) 
        addAtIndex(size, val);
    

    public void addAtIndex(int index, int val) 
        // 排除异常:如果 index 大于链表长度,则不会插入节点。
        if (index > size) 
            return;
        

        // 排除异常:如果index小于0,则在头部插入节点。
        if (index < 0) 
            index = 0;
        

        // 开始遍历到第index-1的位置
        ListNode cur = head;
        for (int i = 0; i < index; i++) 
            cur = cur.next;
        

        // 在第index的位置插入元素
        ListNode addNode = new ListNode(val);
        addNode.next = cur.next;
        cur.next = addNode;

        // 链表长度+1
        size++;

    

    public void deleteAtIndex(int index) 

        // 排除异常:索引无效
        if (index < 0 || index >= size) 
            return;
        

        // 开始遍历到第index-1的位置
        ListNode cur = head;
        for (int i = 0; i < index; i++) 
            cur = cur.next;
        

        // 删除元素关键语句
        cur.next = cur.next.next;

        // 链表长度-1
        size--;
    

    // public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException 

    //     // 循环打印链表输出
    //     MyLinkedList linkedList = new MyLinkedList();
    //     Class myClass = linkedList.getClass();
    //     String methods[] =  "addAtHead", "addAtTail", "addAtIndex", "get", "deleteAtIndex", "get",
    //             "get", "deleteAtIndex", "deleteAtIndex", "get", "deleteAtIndex", "get" ;
    //     Object params[][] =   1 ,  3 ,  1, 2 ,  1 ,  1 ,  1 ,  3 ,  3 ,  0 ,  0 ,  0 ,
    //              0  ;
    //     for (int i = 0; i < methods.length; i++) 
    //         int param_length = params[i].length;
    //         Class c[] = new Class[param_length];
    //         for (int j = 0; j < param_length; j++) 
    //             c[j] = wrapperToPrimitive.get(params[i][j].getClass());
    //         
    //         Method method = myClass.getDeclaredMethod(methods[i], c);
    //         method.invoke(linkedList, params[i]);
    //         System.out.print(methods[i]+" ");
    //         for(int k=0;k<params[i].length;k++)
    //             System.out.print(params[i][k]+" ");
    //         
    //         System.out.println();
    //         for (int k=0;k<linkedList.size;k++) 
    //             System.out.print(linkedList.get(k)+" ");
    //         
    //         System.out.println();
    //     

    // 

    // private static final Map<Class, Class> wrapperToPrimitive = new HashMap<Class, Class>();
    // static 
    //     wrapperToPrimitive.put(Integer.class, int.class);
    //     // wrVoid.class, void.class,
    //     // Boolean.class, boolean.class,
    //     // Byte.class, byte.class,
    //     // Character.class, char.class,
    //     // Short.class, short.class,
    //     // , int.class,
    //     // Long.class, long.class,
    //     // Float.class, float.class,
    //     // Double.class, double.class)
    // 


反转链表

【力扣】206. 反转链表

// 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 reverseList(ListNode head) 
        /*
         * 思路:双指针,一个指针指向原链表,另一个指针指向新的链表(倒序)
         * 
         * 参考:
         * https://programmercarl.com/0206.%E7%BF%BB%E8%BD%AC%E9%93%BE%E8%A1%A8.html#%E5%8F%8C%E6%8C%87%E9%92%88%E6%B3%95
         * 
         * 首先定义一个cur指针,指向头结点,再定义一个pre指针,初始化为null
         * 然后就要开始反转了,首先要把cur->next节点用tmp指针保存一下,也就是保存一下这个节点
         * 为什么要保存一下这个节点呢,因为接下来要改变cur->next的指向了,将cur->next指向pre,此时已经反转了第一个节点了
         * 接下来,就是循环走如下代码逻辑了,继续移动pre和cur指针
         * 最后,cur指针已经指向了null,循环结束,链表也反转完毕了。此时我们return pre指针就可以了,pre指针就指向了新的头结点
         * 
         * p.s.本质上就是每一步从旧链表中摘出头结点,加在新链表的头结点之前
         */

        ListNode pre = null; // 新链表
        ListNode cur = head; // 原链表
        ListNode tmp = null;
        while (cur != null) 
            tmp = cur.next;// 保存下一个节点
            // 把旧链表(cur)的next从旧链表中断掉,重新连到新链表的头结点(pre)之前
            cur.next = pre;
            // 将pre指针移动到cur的位置,也即pre指向新链表的头结点处,
            // 以待下一次旧链表中取出一个头结点与其连接
            pre = cur;
            // 将cur指针移动到tmp(cur.next)的位置,也即cur指向旧链表的头结点处
            cur = tmp;
        
        return pre;
    

以上是关于代码随想录算法训练营第三天 | 203.移除链表元素707.设计链表 206.反转链表的主要内容,如果未能解决你的问题,请参考以下文章

Java算法 每日一题 编号203:移除链表元素

Java算法 每日一题 编号203:移除链表元素

Java算法 每日一题 编号203:移除链表元素

LeetCode与《代码随想录》链表篇:做题笔记与总结-JavaScript版

leetcode算法203.移除链表元素

力扣算法JS LC [203. 移除链表元素] LC [206. 反转链表]