Leetcode | list

Time:2020-9-28

160. Intersecting linked list

Write a program to find the starting node of the intersection of two single linked lists.

As shown in the following two linked lists:
Leetcode | list
The intersection begins at node C1.
Example 1:
Leetcode | list
Input: intersectval = 8, lista = [4,1,8,4,5], listb = [5,0,1,8,4,5], skipa = 2, skipb = 3
Output: reference of the node with value = 8
Input explanation: the value of the intersection node is 8 (note that if two lists intersect, it cannot be 0). Starting from the respective header, the linked list a is [4,1,8,4,5], and the linked list B is [5,0,1,8,4,5]. In a, there are two nodes before the intersection node; in B, there are three nodes before the intersection node.

be careful:

  • If two linked lists have no intersection, null is returned
  • After the results are returned, the two linked lists still need to keep the original structure.
  • It can be assumed that there are no loops in the entire linked list structure.
  • The program satisfies o (n) time complexity and only uses o (1) memory.

Explanation
Method 1
Two pointers are used to obtain the length of two linked lists, and the length difference is obtainedn
The pointer of a long list runs from the beginningnStep, the pointer of the short chain list points to the pointer of the short chain header, and then the two pointers run backward synchronously until the two pointers intersect.

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        //1. Calculate the length difference between two linked lists
        ListNode p1 = headA;
        ListNode p2 = headB;
        int n = 0;
        while (p1!=null){
            p1 = p1.next;
            n++;
        }
        while (p2!=null){
            p2 = p2.next;
            n--;
        }
        //P1 points to long chains and P2 to short chains
        if (n>0){
            p1 = headA;
            p2 = headB;
        }else {
            p1 = headB;
            p2 = headA;
        }
        n = Math.abs(n);
        //Long chain takes n steps first
        for (int i = 0; i<n; i++){
            p1 = p1.next;
        }
        //P1, P2 go together
        while(p1!=p2){
            p1 = p1.next;
            p2 = p2.next;
        }
        return p1;
    }
}

Method 2
The more concise method first makes the long list pointer reach the end of the same distance as the short list length.
P1 and P2 point to the linked list heada and headb respectively. If P1 runs first, P1 points to headb; if P2 runs out, P2 points to heada until P1 and P2 are the same.
For example, for a linked list:A={1,3,5,7,9,11}andB={2,4,9,11}, intersect at the node9The length difference between the two lists is 2. Then the list B is less than two nodes.
Pointer P2 runs first in linked list B, resets P2 to a, P1, P2 and continues to run backward synchronously. Pointer P1 will run through two more nodes in a, and P2 will also run two nodes in B simultaneously. At this time, the position pointed by P2 is exactly the part longer than that of list a and list B. Finally, P1 points to headb, and P1 and P2 are at the same distance from the end, so we just need to go backward synchronously until we meet the intersection point.

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode p1 = headA;
        ListNode p2 = headB;
        while (p1!=p2){
            p1 = p1==null? headB: p1.next;
            p2 = p2==null? headA: p2.next;
        }
        return p1;
    }
}

Time complexity O (M + n)
Space complexity O (1)


206. Reverse linked list (simple)

Source: leetcode
Link: https://leetcode-cn.com/probl…

Invert a single linked list.

Example:

Input: 1 > 2 > 3 > 4 > 5 > null
Output: 5 > 4 > 3 > 2 > 1 > null

Advanced:
You can invert the list iteratively or recursively. Can you solve the problem in two ways?

answer:
1. iterative version

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode curr = head;
        ListNode prev = null;
        ListNode temp = null;
        
        while (curr!=null){
            temp = curr.next;
            curr.next = prev;
            prev = curr;
            curr = temp;
        }
        return prev;
    }
}

Time complexity O (n)
Space complexity O (1)

2. Recursive version

class Solution {
    public ListNode reverseList(ListNode head) {
        if (head==null || head.next==null){
            return head;
        }
        ListNode res = reverseList( head.next ); // reverse linked list head.next
        //Finally, reverse the head
        head.next.next = head;
        head.next = null;
        return res;
    }
}

Time complexity O (n)
Space complexity O (n)


  1. Merge two ordered linked lists

Merge two ascending lists into a new ascending list and return. The new linked list is composed of all nodes of two given linked lists.

Example:

Input: 1 - > 2 - > 4, 1 - > 3 - > 4
Output: 1 - > 1 - > 2 - > 3 - > 4 - > 4

The merging part is similar to the merging part of merge sort

class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
            ListNode head  = new ListNode(-1);
            ListNode p = head;
        while (l1!=null && l2!=null){
            if (l1.val<=l2.val){
                p.next = l1;
                p = p.next;
                l1 = l1.next;
            }
            else{
                p.next = l2;
                p = p.next;
                l2 = l2.next;
            }
        }
        //There is only one list that has not been traversed
        p.next = l1 == null ? l2 : l1;
        return head.next;
    }
}

Time complexity: O (M + n)
Spatial complexity: O (1)

83. Remove duplicate elements from sorted list (simple)

Given a sort list, delete all duplicate elements so that each element appears only once.

Example 1:

Input: 1 - > 1 - > 2
Output: 1 - > 2

Example 2:

Input: 1 > 1 > 2 > 3 > 3
Output: 1 - > 2 - > 3

Explanation:
1. Double pointer

class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        if (head == null || head.next == null){
            return head;
        }
        ListNode pre = head;
        ListNode curr = pre.next;
        while (curr != null){
            if (curr.val != pre.val){
                pre.next = curr;
                pre = pre.next;
            }
            curr = curr.next;
        }
        pre.next = null;
        return head;
    }
}

2. Single pointer*

class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        ListNode curr = head;
        while (curr !=null && curr.next != null){
            if (curr.val == curr.next.val){
                curr.next  = curr.next.next ; // if the value of the current node is equal to that of the next node, the same node in the middle will be skipped
            }else{
                curr =  curr.next ; // otherwise, do not skip
            }
        }
        return head;
    }
}

Time complexity O (n)
Space complexity O (1)


19. Delete the last nth node of the linked list (medium)

Given a linked list, delete the last nth node of the list, and return the head node of the list.

Example:

Given a linked list: 1 - > 2 - > 3 - > 4 - > 5, and N = 2

When the penultimate node is deleted, the linked list becomes 1 - > 2 - > 3 - > 5
explain:

The given n guarantee is valid.

Advanced:
Can you try one scan?

One scan method
Using two pointers, the pointer P1 takes n steps first, and the other pointer P2 moves backward synchronously from the beginning node. At this time, the two pointers are separated by N pointers. When P1 reaches the end, P2 happens to be on the last N + 1 node. Delete the last nth node.

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(-1);
        dummy.next = head;
        ListNode pre = dummy;
        ListNode curr = head;
        while(curr!=null){
            curr = curr.next;
            If (n! = 0) {// curr
                n--;
            }After else {// curr takes n steps, pre starts walking
                pre = pre.next;
            }
        }
        pre.next = pre.next.next;
        return dummy.next;
    }
}

Time complexity O (L), l is the length of linked list
Space complexity O (1)


82. Delete duplicate elements II from sorted list

Given a sort list, delete all nodes with duplicate numbers, and keep only the numbers that do not appear repeatedly in the original list.

Example 1:

Input: 1 - > 2 - > 3 - > 3 - > 4 - > 4 - > 5
Output: 1 - > 2 - > 5
Example 2:

Input: 1 > 1 > 1 > 2 > 3
Output: 2 - > 3

Explanation

Solution 1: tail inserting non repeated nodes

class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        ListNode dummy = new ListNode();
        ListNode tail = dummy;
        
        //Find the node that does not repeat and insert the tail of the node after tail
        //Record the repeat interval [I, J) with double pointer L, R. if the length of [I, J) is 1, then I is the non repeating node, tail inserted!
        //If the length of [I, J) is not 1, then I is a repeating node without tail insertion
        
        for (ListNode L = head, R = head; R != null; L = R){
            while (R!= null && L.val == R.val){
                R = R.next;
            }
            If (l.next = = R) {// the next node of L is r, then l is not a repeating element, but tail inserted
                tail.next = L;
                tail = L;
                tail.next = null;
            }
        }
        return dummy.next;
    }
}

Time complexity: O (n)
Spatial complexity: O (1)

Solution 2: delete duplicate nodes

class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        ListNode dummy = new ListNode(-1);
        dummy.next = head;

        ListNode pre = dummy, cur = head;
        while (cur != null && cur.next != null) {
            if (cur.val != cur.next.val) {
                if (pre.next != cur) pre.next = cur.next;
                else pre = pre.next;
            }
            cur = cur.next;
        }
        if (pre.next != cur) pre.next = cur.next;
        return dummy.next;
    }
}

Time complexity: O (n)
Spatial complexity: O (1)

24. Nodes in pairwise exchange linked list (medium)

Given a linked list, two adjacent nodes are exchanged, and the exchanged linked list is returned.
You can’t just change the values inside the nodes, you need to actually exchange nodes.

Example:

Given 1 - > 2 - > 3 - > 4, you should return 2 - > 1 - > 4 - > 3

Explanation:
1. Iteration
Leetcode | list

class Solution {
    public ListNode swapPairs(ListNode head) {
        ListNode dummy = new ListNode(-1);
        dummy.next = head;
        ListNode pre = dummy;
        ListNode curr = dummy.next;
        while (curr != null && curr.next != null){
            ListNode temp = curr.next;
            curr.next = curr.next.next;
            temp.next = curr;
            pre.next = temp;
            pre = curr;
            curr = curr.next;
        }
        return dummy.next;
    }
}

Time complexity O (n)
Space complexity O (1)

2. Recursion

//Recursion
class Solution {
    public ListNode swapPairs(ListNode head) {
        if (head == null || head.next == null){
            return head;
        }
        
        ListNode first = head;
        ListNode second = head.next;
        
        first.next  = swapPairs( second.next ); // the next node of the first node is the check point after the exchange of nodes after the second node
        second.next  =First; // the second node points to the first node
        Return second; // the second node is now the header node, so the second node is returned
    }
}

Time complexity: O (n)
Spatial complexity: O (n)

445. Add two numbers II * (medium)

Two non empty linked lists are given to represent two nonnegative integers. The highest digit is at the beginning of the list. Each node of them stores only a single number. Adding the two numbers returns a new linked list.
You can assume that neither of these numbers begins with zero except for the number 0.

Advanced:
What to do if the input list cannot be modified? In other words, you can’t flip the nodes in the list.

Example:

Input: (7 → 2 → 4 → 3) + (5 → 6 → 4)
Output: 7 > 8 > 0 > 7

Explanation:
1. Borrowing stack
Two stacks are used to store the values of the two linked lists. Each time the corresponding digit sum is calculated, the top element of the stack will pop up and accumulate.

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode(0);
        Stack<Integer> stack1 = new Stack<>();
        Stack<Integer> stack2 = new Stack<>();
        //L1 stack
        ListNode p = l1;
        while (p != null){
            stack1.push(p.val);
            p = p.next;
        }
        //L2 stack
        p = l2;
        while (p != null){
            stack2.push(p.val);
            p = p.next;
        }
        //Stack top element addition
        Int carry = 0; // carry
        while (!stack1.isEmpty() || !stack2.isEmpty() || carry!=0){
            //Add two numbers and add up
            int sum = 0;
            if (!stack1.isEmpty()){
                sum += stack1.pop();
            }
            if (!stack2.isEmpty()){
                sum += stack2.pop();
            }
            sum += carry;
            
            //Find the remainder
            //Insert new node
            int remainder = sum % 10;   
            ListNode s = new ListNode(remainder);
            s.next = dummy.next;
            dummy.next = s;
            
            Carry = sum / 10; // next round carry
           
        }
        return dummy.next;
    }
}

Time complexity O (n + m)
Space complexity O (n + m)


234. Palindrome list * (medium)

Source: leetcode
Link: https://leetcode-cn.com/probl…

Please judge whether a linked list is a palindrome list.

Example 1:

Input: 1 - > 2
Output: false

Example 2:

Input: 1 - > 2 - > 2 - > 1
Output: true

Advanced
Can you solve this problem with O (n) time complexity and O (1) space complexity?

answer:
1. Borrowing stack:
Considering that the stack structure is in reverse order when it comes out of the stack, the stack is used.
Scan the linked list once and store the values in the stack;
Scan the linked list again, scan each node to see if it is equal to the top element of the stack, and pop up an element. If each time is equal, it is a palindrome linked list.
Space complexity O (n)

2. Stack + speed pointer:
The second half of the list is put on the stack, and the first half of the list is compared with the stack.
(to find the midpoint, the fast pointer takes two steps at a time, and the slow pointer takes one step at a time)
Space complexity O (n / 2)

3. Fast / slow pointer + reverse linked list:
The second half of the list is in reverse order. Compare whether the two lists are equal.
The second half of the list is restored again.
Note:
First of all, regardless of whether the number of nodes in the list is odd or even, the rear split node is the next node of P1, so P1 is determined, and the latter half is determined.
Secondly, when the number of nodes in the list is odd, the length of the first half of the list is 1 more than that of the second half. However, in the comparison, the last node of the first half is not considered. As long as the pointer of the latter half of the list reaches the end, the comparison is successful.

Time complexity O (n + n / 2) = O (n);
Only constant pointers are used, so the space complexity is O (1)
Leetcode | list
java code

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isPalindrome(ListNode head) {
        //Define a fast pointer and a slow pointer
        ListNode p1 = head;
        ListNode p2 = head;
        if (head == null || head.next == null) return true;
        //Find the midpoint, P1 points to the midpoint, P2 points to the node after the midpoint
        while(p2.next!=null && p2.next.next!=null){
            p1 = p1.next;
            p2 = p2.next.next;
        }
        p2 = p1.next;
        p1.next = null;
        
        //Reverse the second half of the list, Rev is the inverted list
        ListNode p3 = null;
        while (p2!=null){
            ListNode temp = p2.next;
            p2.next = p3;
            p3 = p2;
            p2 = temp;
        }
        ListNode rev = p3;
        
        //Compare two linked lists
        p1 = head;
        while(p3!=null){
            if ( p1.val == p3.val){
                p1 = p1.next;
                p3 = p3.next;
            }
            else break;
        }
        if (p3 == null){
            return true;
        }else{
            return false;
        }
    }
}

Time complexity O (n)
Space complexity O (1)


725. Split linked list * (medium)

Given a linked list whose head node is root, write a function to divide the list into k continuous parts.
The length of each part should be as equal as possible: the length difference between any two parts cannot exceed 1, which means that some parts may be null.
The K parts should be output in the order they appear in the linked list, and the length of the first part should be greater than or equal to the length of the following part.
Returns a list of linked lists that meet the above rules.

Example 1:

Input: 
root = [1, 2, 3], k = 5
Output: [[1], [2], [3], [],]
Explanation:
The input and output parts should be linked lists, not arrays.
For example, the input node root has Val = 1, root.next.val  = 2, \ root.next.next . Val = 3, and root.next.next .next = null。
The first output [0] is output [0]. Val = 1, output [0]. Next = null.
The last element output [4] is null, which means that the last part is an empty linked list.

Example 2:

Input: 
root = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], k = 3
Output: [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
Explanation:
The input is divided into several consecutive parts, and the length difference of each part is no more than 1. The length of the front part is greater than or equal to that of the back part.

Tips:
Length range of root: [0, 1000]
Enter the size range of each node: [0, 999]
The value range of K is: [1,50]

Explanation:

  1. Construct a new linked list

First find the length of the listn, the length of each linked list in the array is at leastn/kIfn%k = rem>0, then the length of the first REM array plus1, forlen+1. build a new linked list and add nodes of corresponding length to the list.

class Solution {
    public ListNode[] splitListToParts(ListNode root, int k) {
        ListNode[] res = new ListNode[k];
        
        int n = 0;
        ListNode curr = root;
        while(curr!=null){
            curr = curr.next;
            n++;
        }
        int len = n / k;
        Int REM = n% K; // the length of the first REM linked list is len + 1, and the length of the rest is len
        
        //Add linked list to array
        curr = root;
        for (int i = 0; i < k; i++){
            ListNode dummy = new ListNode(-1);
            ListNode p = dummy;
             
            For (int j = 0; J < len + (REM > 0? 1:0); j + +) {// add nodes to each linked list
               
                if (curr!=null){
                    p = p.next = new ListNode(curr.val);
                    curr = curr.next;
                }
                Else p.next = null; // if the original linked list is completely separated, put the empty list into the array not added to the linked list
            }
            res[i] = dummy.next;
            REM --; // construct a linked list, REM minus 1
        }
        return res;
    }
}

The time complexity is O (n + k). If K is large, k-1 empty nodes should be added at most
Space complexity O (max (n + k))

2. separate from the original list
Curr points to the current node and breaks after the corresponding length.

class Solution {
    public ListNode[] splitListToParts(ListNode root, int k) {
        ListNode[] res = new ListNode[k];
        ListNode curr = root;
        int n = 0;
        while(curr!=null){
            curr = curr.next;
            n++;
        }
        
        int len = n/k;
        int rem = n%k;
        
        curr = root;
        for (int i=0; i<k; i++){
            res[i] = curr;
            for(int j =0; j< len + (rem>0?1: 0)-1; j++){
                if (curr!=null){
                     curr = curr.next;
                }
            }
            //Disconnect
            if (curr!=null){
                ListNode temp = curr.next;
                curr.next = null;
                curr = temp;
            }
            rem--;
        }
        return res;
    }
}

The time complexity is O (n + k). If K is large, k-1 empty nodes should be added at most
Space complexity O (k)


328. Parity list (medium)

Source: leetcode
Link: https://leetcode-cn.com/probl…

Given a single linked list, all odd and even nodes are arranged together. Note that the odd and even nodes here refer to the parity of the node number, not the parity of the node’s value.
Try using the in place algorithm. The space complexity of your algorithm should be o (1), the time complexity should be o (nodes), nodes is the total number of nodes.

Example 1:

Input: 1 > 2 > 3 > 4 > 5 > null
Output: 1 > 3 > 5 > 2 > 4 > null

Example 2:

Input: 2 > 1 > 3 > 5 > 6 > 4 > 7 > null 
Output: 2 > 3 > 6 > 7 > 1 > 5 > 4 > null

explain:
The relative order of odd and even nodes should be maintained.
The first node of a linked list is considered an odd node, the second node is considered an even node, and so on.

Explanation
Put odd nodes in one list and even nodes in another. Then connect the even list to the end of the odd list.

public class Solution {
    public ListNode oddEvenList(ListNode head) {
        if (head == null) return null;
        ListNode odd = head;
        ListNode even_head = head.next;
        ListNode even = even_head;
        while (even != null &&  even.next  ! = null) {// note the boundary conditions
           odd.next = even.next;
           odd = odd.next;
           even.next = odd.next;
           even = even.next;
        }
        odd.next = even_head;
        return head;
    }
}

Time complexity O (n)
Space complexity O (1)

Recommended Today

On the theoretical basis of SRE

What is SRE? When I first got into contact with SRE, many people thought that it was a post with full stack capability in Google and could solve many problems independently. After in-depth exploration, it is found that SRE can solve many problems, but there are too many problems. It is difficult for a post […]