美文网首页
算法|移除链表节点、翻转链表、设计链表

算法|移除链表节点、翻转链表、设计链表

作者: 激扬飞雪 | 来源:发表于2022-11-18 22:58 被阅读0次

    一、203. 移除链表元素

    题目连接:https://leetcode.cn/problems/remove-linked-list-elements/
    思路:单链表要移除元素,需要知道删除元素的前一个节点,改变前一个元素的pre.next等于cur.next
    思路一:通过添加虚拟头节点,遍历如果下一个节点=val,即pre.next == val, 则删除next节点,即pre.next=pre.next.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 dummyHead = new ListNode();
            dummyHead.next = head;
            ListNode pre = dummyHead; 
            while (pre.next != null) {
                if (pre.next.val == val) {
                    pre.next = pre.next.next;
                } else {
                    pre = pre.next;
                }
            }
            return dummyHead.next;
        }
    }
    

    思路二:不使用虚拟节点,先看head是否等于val,等于修改head为head.next,在通过pre.next.val 是否等于val 来是否移除元素

    /**
     * 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) {
            while (head != null && head.val == val){
                head = head.next;
            }
            ListNode pre = head;
            while (pre != null && pre.next != null) {
                if (pre.next.val == val) {
                    pre.next = pre.next.next;
                } else {
                    pre = pre.next;
                }
            }
            return head;
        }
    }
    

    二、 206. 反转链表

    题目连接:https://leetcode.cn/problems/reverse-linked-list/
    思路一、迭代法,记录前一个指针pre、让当前的cur.next=pre,在这之前要下记录下next,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 reverseList(ListNode head) {
            ListNode cur = head;
            ListNode pre = null;
            while (cur != null) {
                ListNode next = cur.next;
                cur.next = pre;
                pre = cur;
                cur = next;
            }
            return pre;
        }
    }
    

    思路二、使用递归、递归到最后一个元素时,即head.next == null,递归回溯,修改当前节点的next.next = 当前节点,并且head.next = null;

    /**
     * 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 reverseList(ListNode head) {
            if (head == null || head.next == null) {
                return head;
            }
            ListNode listNode = reverseList(head.next);
            head.next.next = head;
            head.next = null;
            return listNode;
        }
    }
    

    思路三、使用栈模拟递归的过程

    /**
     * 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 reverseList(ListNode head) {
            Stack<ListNode> stack = new Stack<>();
            ListNode cur = head;
            while (cur != null && cur.next != null){
                stack.push(cur);
                cur = cur.next;
            }
            ListNode newHead = cur;
            while (!stack.isEmpty()){
                ListNode listNode = stack.pop();
                listNode.next = null;
                cur.next = listNode;
                cur = listNode;
            }
            return newHead;
        }
    }
    

    三、707. 设计链表

    题目连接:https://leetcode.cn/problems/design-linked-list/
    1、使用单链表,设计一个虚拟头结点、查找的时候要 <= index, 添加和删除要找到前一个节点即 < index
    添加节点:newListNode.next = pre.next;
           pre.next = newListNode;
           size++;
    删除节点:pre.next = pre.next.next;
           size--;

    class MyLinkedList {
        public static class ListNode {
            public int val;
            public ListNode next;
            public ListNode(){}
            public ListNode(int val) {
                this.val = val;
            }
            public ListNode(int val, ListNode next) {
                this.val = val;
                this.next = next;
            }
        }
        private ListNode dummy;
        int size = 0;
        public MyLinkedList() {
            dummy = new ListNode();
        }
        
        public int get(int index) {
            if (index < 0 || index >= size) return -1;
            ListNode cur = dummy;
            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) {
            if (index > size) return;
            if (index < 0) index = 0;
            ListNode pre = dummy;
            for (int i = 0; i < index; i++){
                pre = pre.next;
            }
            ListNode newListNode = new ListNode(val);
            newListNode.next = pre.next;
            pre.next = newListNode;
            size++;
        }
        
        public void deleteAtIndex(int index) {
            if (index < 0 || index >= size) return;
            ListNode pre = dummy;
            for (int i = 0; i < index; i++){
                pre = pre.next;
            }
            pre.next = pre.next.next;
            size--;
         }
    }
    

    2、使用双链表,注意查找的时候当 index >= size / 2 从后面向前搜索;同理删除和添加也是,获取到index的前一个节点pre.
    查找操作:

    if (index > size / 2) {
        ListNode cur = tail;
        for (int i = 0; i < size - index; i++) {
            cur = cur.prev;
        }
        return cur.val;
    } else {
        ListNode cur = head;
        for (int i = 0; i <= index; i++) {
            cur = cur.next;
       }
      return cur.val;
    }
    

    添加操作:ListNode newListNode = new ListNode(val);
           newListNode.next = pre.next;
           pre.next.prev = newListNode;
           pre.next = newListNode;
           newListNode.prev = pre;
    删除操作:pre.next.next.prev = pre;
           pre.next = pre.next.next;

    class MyLinkedList {
        public static class ListNode {
            public int val;
            public ListNode next;
            public ListNode prev;
            public ListNode(){}
            public ListNode(int val) {
                this(val, null);
            }
            public ListNode(int val, ListNode next){
                this(val, next, null);
            }
    
            public ListNode(int val, ListNode next, ListNode prev) {
                this.val = val;
                this.next = next;
                this.prev = prev;
            }
        }
        private ListNode head;
        private ListNode tail;
        int size = 0;
        public MyLinkedList() {
            head = new ListNode();
            tail = new ListNode();
            head.next = tail;
            tail.prev = head;
            size = 0;
        }
        
        public int get(int index) {
            if (index < 0 || index >= size) return -1;
            if (index  > size / 2) {
                ListNode cur = tail;
                for (int i = 0; i < size - index; i++){
                    cur = cur.prev;
                }
                return cur.val;
            } else {
                ListNode cur = head;
                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);
            ListNode newListNode = new ListNode(val);
            tail.prev.next = newListNode;
            newListNode.prev = tail.prev;
            newListNode.next = tail;
            tail.prev = newListNode;
            size++;
        }
        
        public void addAtIndex(int index, int val) {
            if (index > size) return;
            if (index < 0) index = 0;
            // ListNode pre = head;
            // for (int i = 0; i < index; i++){
            //     pre = pre.next;
            // }
            if (index == size) {
                addAtTail(val);
                return;
            }
            ListNode pre = getListPreNode(index);
            ListNode newListNode = new ListNode(val);
            newListNode.next = pre.next;
            pre.next.prev = newListNode;
            pre.next = newListNode;
            newListNode.prev = pre;
            size++;
        }
        
        private ListNode getListPreNode(int index) {
            if (index < 0 || index >= size) return null;
            if (index >= size / 2) {
                ListNode pre = tail;
                for (int i = 0; i <= size - index; i++){
                    pre = pre.prev;
                }
                return pre;
            } else {
                ListNode pre = head;
                for (int i = 0; i < index; i++) {
                    pre = pre.next;
                }
                return pre;
            }
        }
        public void deleteAtIndex(int index) {
            if (index < 0 || index >= size) return;
            // ListNode pre = head;
            // for (int i = 0; i < index; i++){
            //     pre = pre.next;
            // }
            // pre.next.next.prev = pre;
            // pre.next = pre.next.next;
            ListNode pre = getListPreNode(index);
            pre.next.next.prev = pre;
            pre.next = pre.next.next;
            size--;
        }
    }
    

    相关文章

      网友评论

          本文标题:算法|移除链表节点、翻转链表、设计链表

          本文链接:https://www.haomeiwen.com/subject/srhvxdtx.html