LinkedList

  1. head, 新旧头节点不能丢失head

  2. .next 来做dereference,null pointer exception的问题需注意

  3. single linked list的最后挂一个null,这个null也是遍历的终止条件

array和single linked list 都是一维的线性结构, 区别

  • single linked list访问已知index,TC为O(n), array 为O(1)

  • array是连续存储的,可以根据array的reference算出连续存储的array的内存首地址,然后根据所存的element数据类型和i本身,算出当前要access的element对于array的内存首地址的offset(偏移量),进而直接可以得到我要access element的地址。

  • int[] arr = null;

  • int[] arr = new int[0] {} 这个表示arr为空,empty

    • null: no object in heap associated with this reference

    • empty(length/size() == 0): has object in heap but the object has no valid element

  • ArrayList<Integer> list = null;

  • ArrayList<Integer> list = new ArrayList<Integer>(); 这个integer表示size大小

  • corner case: head == null, head.next == null: 表示list没有或只有一个的

  • main structure : while loop --> when to exit

  • Generics只接受class

  • T can be Integer of characters

  • Tree? ListNode can also represent TreeNode. --> inplace

    • k TreeNode(clarify guarantee k or at most k)

class ListNode<T>{//Generics
    //fields
    T value;
    ListNode next;
    ListNode prev;
    
    // TreeNode[] array; //n size be guatranteed--> Trie
    ArrayList<Node> nerbs; --> size is dynamic change Hashmap
    
    visited; // if visited, set it as true;
    
    
    //methods
    ListNode(int val){
        value = val;
        next = null;
        prev = null;
    }
}

  • ListNode dummy = new ListNode(0);

    • 定位头节点

L206 reverse linked list by one

  • S0: dummy node

    • 把1 2 3 分别插入到dummy后面

  • S1: iteration

    • 遍历到这个node的时候,箭头不向前指,向后指

    • demo: while loop先保存next,cur.next = prev; prev = cur; cur = next

    • when cur == null, the last node has finished which is prev. so return prev

head(减少head的变量)
null <-- node1 <-- node2 --> node3 --> node4 --> node5 --> node6 --> null
                                                            prev     cur       next
public ListNode reverseLinkedList(ListNode head){
    if(head == null || head.next == null) return head;
    ListNode cur = head;
    ListNode next = null;
    ListNode prev = null;
    
    while(cur != null){
        next = cur.next;
        cur.next = prev;
        prev = cur;
        cur = next;
    }
    return prev;

}
  • S2: recursion **** 这是面试官想要的

    • head.next.next = head;

    • head.next= null

    • TC: O(n)

node1 --> node2 --> node3 --> node4 --> node5 --> node6 --> null
node2 --> node3 --> node4 --> node5 --> node6 --> null
node3 --> node4 --> node5 --> node6 --> null
node4 --> node5 --> node6 --> null
node5 --> <-- node6 --> null        //<-- means head.next.next = head
node6 --> null
public ListNode reverseLinkedList(ListNode head){
    //cc
    if(head == null || head.next == null) return head
    
    ListNode newHead = reverseLinkedList(head.next);
    //wall
    head.next.next = head;
    head.next = null;
    return newHead;
}
  • S3: Recursion similar to DFS //

public ListNode reverseList(ListNode head){ 
    return reverseLinked(head,null);
}
public ListNode reverseLinked(ListNode head, ListNode newHead){
    if(head == null) return newHead;
    ListNode next = head.next;
    head.next = newHead;
    return reverseLinked(next,head);
}
  • 1.1 L24 25 reverse linked list by pair/ three/ k

    • by pair

h
1 --> 2 --> 3 --> 4 --> 5--> 6 --> null
by pair
h
2 --> 1 --> 4 --> 3 --> 6 --> 5--> null
public ListNode reverseByPair(ListNode head){
    if(head == null || head.next == null){ //1
        return head;
    } 
    
    ListNode subHead = reverseByPair(head.next.next); //2
    head.next.next = head; //3
    ListNode newHead = head.next;//4
    head.next= subHead; //5
    return newHead;
    
}
  • by three / k

    • recursion x iteration

    • what if not enough node to reverse?

    • use two while loop

h
1 --> 2 --> 3 -->   4 --> 5--> 6 --> null
by pair
h
3 --> 2 --> 1 --> 6 --> 5 --> 4--> null
  • Q1.2 reverse linkedList by range

    • range 内 by one reverse

Q2 find middle node(1/2) in LinkedList --> 1/3 1/5 3/7

  • slow fast two pointers

    • if 1/2: fast goes 2 steps, slow goes 1

    • 1/3: fast goes 3 steps, slow goes 1

    • 3/7: fast goes 7 steps, slow goes 3

  • 1/3 究竟指的是谁,但如果一共7个呢

  • S1: while loop :fast != null&&fast.next != null

    • check if total node num is even

  • S2: fast.next != null && fast.next.next != nullor s= 0, f = 1, s and f差一步

public ListNode findMid(ListNode head){
    if(head == null || head.next == null){
        return head;
    }
    ListNode slow = head;
    ListNode fast = head.next;
    while(fast.next != null && fast.next.next != null){
        slow = slow.next;
        fast = fast.next.next;
    }
    return slow;
}
  • 2.1 singly linked list, kth position to the right(LC19)

    • question: if k> size

Q3 L141 check whether a linkedlist has cycle 2007 第六节1:27

  • 查重/查环的方式:1:31

    • 1.hashset

      • 遍历过的node都丢到hashset中

    • 2. 加一个visited

      • 新的node设为true

    • 3. slow fast pointer, how to set the speed?

      • 两倍速肯定没问题

      • slow第一次到达之前,fast已经check出来

  • 3.0 reverse linkedlist with cycle 1:41:02

    • 先clarify带环的linkedlist是什么样的

      • 重复之前的node断开

      • while(cur != null)

      while(!Hashset.contains(cur))

      head.next == null

      !Hashset.contains(head.next)

  • 3.1 L160 intersection of linkedlist 1:48:26

    • 找到交叉口

    • 从两个head出发 往后走,list1list2拥有相同的node

      • 1. Hashset: 放list 1 的listnode 的reference,再找2

      • 2. visited

      • 3. 假如知道list1.size and list2.size,找相遇的node

      • 4. a + b + c = c + b + a

        • cur1从h1走完跳回h2走 cur2从h2走完跳回h1走

  • 3.2 return size of cycle 1:59:04

    • 先check有没有环,找出入口点

  • 3.3 L142 return enter node of cycle环入口 2:00:43

    • 算法解:查重,重复的点就是入口

    • 数学解:fast =(a + b)+ n(b+c); slow = a+ b

      • a = (n-1)(b+c) + c

  • 3.4 return kth position after enter node of cycle 2:06:47

    • 取余

Q4 Insert a value/node into sorted LinkedList 2:20:08

  • difference between value and node

    • node is like a basket, value is the apple in the basket

L147

1.find the position(think about the head and tail position)

2. need to know prev and cur

  • prev is required

3. pre processing

S2: no dummy node

  • in the while loop, use prev.next instead of cur to insert the value in the correct position

public ListNode insertValue(ListNode head, int value){
    ListNode newNode = new ListNode(value);
    if(head == null || value <= head.val){
        newNode.next = head;
        return newNode;
    }
    ListNode prev = head;
    while(prev.next != null || prev.next.val < value){
        prev = prev.next;
    }
    newNode.next = prev.next;
    pre.next = newNode;
    return head;
    
}
  • L148 Sort List 2:42:31以一次一次加一个新的值的方式完成sort

Q5 L203 L237 Delete a node/value from LinkedList 2:51:30

  • 删值需要先找到值,重复状态下怎么删值

  • 定位到要删的node

    • with head:要删的前提需要知道previous node

      • prev = head, if prev.next.val == target, prev.next =prev.next.next

    • if without head, 把下一个篮子里的值存到要删值的篮子里,要删的值就被替代了,把被提取的篮子删掉

  • 5.1 L83 remove duplicate 2:57:21

    • from remove duplicate, wil onlyl be value

    • 没有箭头连接的node怎么办?

      • garbage collection:不被使用的时候启用了此机制

Q6 L21 Merge two sorted LinkedList/Array 2:59:56

  • S1: use dummy node, extra linkedlist

  • S2: 以pre processing的方式找到头节点去做

    • 两个list的头节点,谁小谁就是答案的头节点

public ListNode mergeTwoList(ListNode h1, ListNode h2){
    if(h1 == null) return h2;
    if(h2 == null) return h1;
    ListNode head, cur;
    if(h1.val <= h2.val){ //谁小取谁
        head = h1;
        h1 = h1.next
    }else{
        head = h2;
        h2 = h2.next
    }
    cur = head;
    while(h1 != null && h2 != null){
        if(h1.val < h2.bal){
            cur.next = h1;
            h1 = h1.next;
        }else{
            cur.next = h2;
            h2 = h2.next;
        }
        cur = cur.next;
    }
    if ( h1 != null ) cur.next = h1;
    if ( h2 != null ) cur.next = h2;
    return head;
}

第七节 13:41 review L21 S2: iteration

  • corner case need to be discussed

  • S3:merge two linkedlist recursion 25:05

public ListNode mergeTwoList(ListNode l1, ListNode l2){
    if(l1 == null) return l2;
    if(l2 == null) return l1;
    
    if(l1.val < l2.val){
        l1.next = mergeTwoList(l1.next, l2); //wall
        return l1; //把小的return上去以便于把更小的接上
    }else{
        l2.next = mergeTwoList(l1, l2.next); //wall
        return l2;
    }
}

Q7 L143 Reorder List 38:37

  • pair merge demo过程49:16

  • S1: extra O(n) space:

    • reverse the whole linkedlist and pair merge

  • S2: in place without alter nodes' value

    • 找mid然后断开

public ListNode reorderList(ListNode head){
    //corner case
    if(head == null || head.next == null) return head;
    ListNode mid = findMid(head);
    ListNode leftHead = head;
    ListNode rightHead = mid.next
    mid.next = null; 断开
    
    return merge(leftHead, reverse(rightHead));
}

findMid();
reverse();
    
private ListNode merge(ListNode h1, ListNode h2){
    ListNode dummy = new ListNode(0);
    ListNode cur = dummy;
    ListNode l1 = h1, l2 = h2;
    while(l1 != null && l2 != null){
        cur.next = l1;
        l1 = l1.next;
        cur = cur.next;
        cur.next = l2;
        l2 = l2.next;
        cur cur.next;
    }
    // if(h1 != null) cur.next = l1;
    cur.next = l1;
    return dummy.next;
    
}

Q8 L328 Odd Even List 1:00:04

  • partition 基于什么:

    • 基于值

    • 基于奇偶位置

  • S1:两个dummy node为头节点的linkedlist,一个存odd,一个存even, 然后merge起来;//记得尾节点加null

  • S2:不能使用dummy node:因为是连续的,所以可以直接存

Q9 L86 Partition List 1:13:50

  • similiar with quick sort; but it is a single linked list, so it can't be read randomly

  • should be stable

  • need a current initialize the input head to traverse or iterate the whole list

    • two dummy heads

public ListNode partitionList(ListNode head, int value){
    if(head == null || head.next == null) return head;
    ListNode less = new ListNode(0);
    ListNode larger = new ListNode(0);
    ListNode cur = head;
    ListNode curLess = less;
    ListNode curLarger = larger;
    while(cur != null){
        if(cur.val < value){
            curLess.next = cur;
            curLess = curLess.next;
        }else{
            curLarger.next = cur;
            curLarger = curLarger.next;
        }
        cur = cur.next;
    }
    curLarger.next = null; //null pointer exception
    curLess.next = larger.next;
    return less.next;
}

Q10 L369 Plus One Linked List 1:35:47

10.1 L2 Add two Number --> minus 小数

10.2 add two string

Integer所表示的最大数字是 2^31-1 最小是-2^31 range 2^32

Last updated

Was this helpful?