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

203.移除链表元素

题目链接/文章讲解/视频讲解::代码随想录

  • 第一想法:
    • dummy node, 没有用pre, cur, 只用了一个cur
    • while loop 更新条件可以只需要while (cur.next != null)
    • 时间复杂度O(n)
    • class Solution {
          public ListNode removeElements(ListNode head, int val) {
              if (head == null) return head;
              
              ListNode dummy = new ListNode(0);
              dummy.next = head;
              ListNode cur = dummy;
              while (cur!=null && cur.next!=null) {
                  if (cur.next.val == val)
                      cur.next = cur.next.next;
                  else
                      cur = cur.next;
              }
              return dummy.next;
          }
      }
  • 看完讲解:
    • 1. dummy, pre, cur
    • 2. pre, cur
      • if (head == null) return head; 要放在while loop更新完后面
        class Solution {
            public ListNode removeElements(ListNode head, int val) {
                while (head != null && head.val == val) head = head.next;
                if (head == null) return head;
                
                ListNode prev = head;
                ListNode cur = head.next;
                
                while (cur!=null) {
                    if (cur.val == val)
                        prev.next = cur.next;
                    else
                        prev = cur;
                    cur = cur.next;
                }
                return head;
            }
        }
    • 3. 只用cur
      • 注意两个while loop条件:
        • while (cur!=null) {
                      while (cur.next != null && cur.next.val == val)
        • class Solution {
              public ListNode removeElements(ListNode head, int val) {
                  while (head!= null && head.val == val) head = head.next;
                  if (head == null) return head;
                  
                  ListNode cur = head;
                  while (cur!=null) {
                      while (cur.next != null && cur.next.val == val)
                          cur.next = cur.next.next;
                      cur = cur.next;
                  }
                  return head;
              }
          }

707.设计链表

题目链接/文章讲解/视频讲解:代码随想录

  • 第一想法:singly linked list
    • class ListNode{} 在整个class MyLinkedList{} 外面并列的,复习OOP
    • 熟记class ListNode{} (这道题应该不需要this.next)
    • MyLinkedList{}里面的variable:int size, ListNode head
    • add()三个function都有点问题
    • 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 MyLinkedList {
          int size;
          ListNode head;
          
          public MyLinkedList() {
              head = new ListNode(0);
              size = 0;
          }
          
          public int get(int index) {
              if (index < 0 || index >= size) 
                  return -1;
              
              ListNode cur = head;
              while (index > 0) {
                  cur = cur.next;
                  index--;
              }
              return cur.val;
          }
          
          public void addAtHead(int val) {
              if (head == null) {
                  head = new ListNode(val);
                  size++;
                  return;
              }
              
              ListNode temp = new ListNode(val);
              temp.next = head;
              size++;
          }
          
          public void addAtTail(int val) {
              ListNode cur = head;
              while(cur.next != null) {
                  cur = cur.next;
              }
              cur.next = new ListNode(val);
              cur.next.next = null;
              size++;
          }
          
          public void addAtIndex(int index, int val) {
              if (index == 0) addAtHead(val);
              if (index == size) addAtTail(val);
              if (index > size) return;
              
              ListNode cur = head;
              for (int i=0; i<index-1; i++) {
                  cur = cur.next;
              }
      
              ListNode temp = new ListNode(val);
              temp.next = cur.next;
              cur.next = temp;
              size++;
          }
          
          public void deleteAtIndex(int index) {
              if (index < 0 || index >= size) 
                  return;
              if (index == 0)
                  head = head.next;
              
              ListNode cur = head;
              for (int i=0; i<index-1; i++) {
                  cur = cur.next;
              }
              cur.next = cur.next.next;
              size--;
          }
      }
  •  看完讲解:
    • singly linked list
      • 以下所有的边界问题在于,head是dummy node
      • get()里的while (index-- >= 0
      • addAtIndex里的index<0情况:if (index < 0) index = 0;
      • addAtIndex里的for loop边界:for (int i=0; i<index; i++) 
      • deleteAtIndex里不需要特别考虑index==0的情况
      • deleteAtIndex里for loop边界:for (int i=0; i<index; i++) 
      • class ListNode {
            int val;
            ListNode next;
            ListNode() {
                
            }
            ListNode(int val) {
                this.val = val;
            }
        }
        
        
        class MyLinkedList {
            int size;
            ListNode head;
            
            public MyLinkedList() {
                head = new ListNode(0);
                size = 0;
            }
            
            public int get(int index) {
                if (index < 0 || index >= size) 
                    return -1;
                
                ListNode cur = head;
                while (index-- >= 0) {
                    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 cur = head;
                for (int i=0; i<index; i++) {
                    cur = cur.next;
                }
        
                ListNode temp = new ListNode(val);
                temp.next = cur.next;
                cur.next = temp;
                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--;
            }
        }

    • doubly linked list
      • 不需要在addAtStart() / addAtTail()里单独更新head / tail, 只需要在addAtIndex()里更新prev, next逻辑
      • get()里可以从前用next遍历,或者从后用prev遍历
      • class ListNode {
            int val;
            ListNode prev;
            ListNode next;
            ListNode() {
                
            }
            ListNode(int val) {
                this.val = val;
            }
        }
        
        
        class MyLinkedList {
            int size;
            ListNode head;
            ListNode tail;
            
            public MyLinkedList() {
                head = new ListNode(0);
                tail = new ListNode(0);
                head.next = tail;
                tail.prev = head;
                size = 0;
            }
            
            public int get(int index) {
                //判断index是否有效
                if(index<0 || index>=size){
                    return -1;
                }
                ListNode cur = this.head;
                //判断是哪一边遍历时间更短
                if(index >= size / 2){
                    //tail开始
                    cur = tail;
                    for(int i=0; i< size-index; i++){
                        cur = cur.prev;
                    }
                }else{
                    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 cur = head;
                for (int i=0; i<index; i++) {
                    cur = cur.next;
                }
        
                ListNode temp = new ListNode(val);
                temp.next = cur.next;
                temp.next.prev = temp;
                temp.prev = cur;
                cur.next = temp;
                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.next.prev = cur;
                cur.next = cur.next.next;
                size--;
            }
        }

206.反转链表

题目链接/文章讲解/视频讲解:代码随想录

  • 第一想法:
    • class Solution {
          public ListNode reverseList(ListNode head) {
              if (head == null) return head;
              
              ListNode prev = null;
              ListNode cur = head;
              ListNode next;
              
              while (cur!=null) {
                  next = cur.next;
                  cur.next = prev;
                  prev = cur;
                  cur = next;
              }
              return prev;
          }
      }
  • 看完讲解:递归法,一样的逻辑
    • class Solution {
          public ListNode reverseList(ListNode head) {
              return reverse(null, head);
          }
      
          private ListNode reverse(ListNode prev, ListNode cur) {
              if (cur == null) {
                  return prev;
              }
              ListNode temp = null;
              temp = cur.next;// 先保存下一个节点
              cur.next = prev;// 反转
              // 更新prev、cur位置
              // prev = cur;
              // cur = temp;
              return reverse(cur, temp);
          }
      }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值