# Weekly leetcode - 02 linked list topic 237/83/234/138/92/142/Offer 22/148/23/24/147/86/61/328/2/Offer06

## leetcode - 237. Delete node in linked list

Please write a function to delete a specific node in the single linked list. When designing the function, you should pay attention to that you cannot access the head node of the linked list. You can only directly access the node to be deleted. The topic data ensures that the node to be deleted is not the end node. ```class Solution {
public void deleteNode(ListNode node) {
node.val = node.next.val;
node.next = node.next.next;
}
}
```

## leetcode - 83. Delete duplicate elements in the sorting linked list

Given the head of a sorted linked list, delete all duplicate elements so that each element appears only once. Returns the sorted linked list. Method 1: use dummy node

```class Solution {
return null;
}
ListNode dummy = new ListNode(-1);
ListNode cur = dummy;
while (cur.next!=null){
if(cur.val== cur.next.val){
cur.next = cur.next.next;
}else{
cur = cur.next;
}
}
return dummy.next;
}
}
```

The above solution will report an error because we have also calculated the value of dummy: Therefore, we cannot use the value of dummy node:

```class Solution {
return null;
}
ListNode dummy = new ListNode(-1);
ListNode cur = dummy;
while (cur.next!=null && cur.next.next!=null){
if(cur.next.val== cur.next.next.val){
cur.next = cur.next.next;
}else{
cur = cur.next;
}
}
return dummy.next;
}
}
```

Method 2: do not use dummy nodes, and in fact do not need to use dummy nodes, because you need to keep one node

```class Solution {
return null;
}
while (cur.next!=null){
if(cur.val== cur.next.val){
cur.next = cur.next.next;
}else{
cur = cur.next;
}
}
}
}
```

## leetcode - 234. Palindrome linked list

Give you the head node of a single linked list. Please judge whether the linked list is a palindrome linked list. If yes, return true; Otherwise, false is returned. ```class Solution {
// Find the intermediate node of the linked list
while (fast!=null && fast.next!=null){
fast = fast.next.next;
slow = slow.next;
}

// Reverse the second half of the linked list

return false;
}
}
return true;
}

private ListNode reverseList(ListNode cur) {
ListNode pre = null;
while (cur!=null){
ListNode tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
}
```

## leetcode - 138. Copy linked list with random pointer

Give you a linked list with a length of n. each node contains an additional random pointer random, which can point to any node or empty node in the linked list.

Construct a deep copy of this linked list. The deep copy should consist of exactly n new nodes, in which the value of each new node is set to the value of its corresponding original node. The next pointer and random pointer of the new node should also point to the new node in the replication linked list, and these pointers in the original linked list and replication linked list can represent the same linked list state. The pointer in the copy linked list should not point to the node in the original linked list.

For example, if there are two nodes X and Y in the original linked list, where x.random -- > y. Then the corresponding two nodes X and Y in the copy linked list also have x.random -- > y. Returns the header node of the copy linked list.

A linked list composed of n nodes is used to represent the linked list in input / output. Each node is represented by a [val, random_index]:

Val: one represents node Integer of val.
random_index: the node index pointed by the random pointer (range from 0 to n-1); null if it does not point to any node. Problem solving method: https://leetcode-cn.com/problems/copy-list-with-random-pointer/solution/liang-chong-shi-xian-tu-jie-138-fu-zhi-dai-sui-ji-/
We use hash table to solve this problem. First create a hash table, then traverse the original linked list, and put the original node as key and the new node as value into the hash table The second step is to traverse the original linked list. This time, we need to set the next and random pointers of the new linked list From the above figure, we can find that the original node and the new node are in one-to-one correspondence, so

map. Get (original node) and the corresponding new node is obtained
map. Get (original node. next) and get the corresponding new node next
map. Get (original node. random) and get the corresponding new node random

Therefore, we only need to traverse the original linked list again, and then set:

New node next -> map. Get (original node. next)
New node random -> map. Get (original node. random)

In this way, the next and random of the new linked list are connected in series
Finally, we then map Get (head), that is, the head node of the corresponding new linked list, can solve this problem.

```class Solution {
// Create a hash table. key is the original node and value is the new node
HashMap<Node,Node> map = new HashMap<>();
// Put the original node and the new node into the hash table
while (cur!=null){
Node newNode = new Node(cur.val);
map.put(cur,newNode);
cur = cur.next;
}

// Traverse the original linked list and set the next and random of the new node
while (cur!=null){
Node newNode = map.get(cur);
if(cur.next!=null){
newNode.next = map.get(cur.next);
}
if(cur.random!=null){
newNode.random = map.get(cur.random);
}
cur = cur.next;
}
}
}
```

## leetcode - 92. Reverse linked list II

Give you the head pointer of the single linked list and two integers left and right, where left < = right. Please reverse the linked list node from position left to position right and return the reversed linked list. ```class Solution {
public ListNode reverseBetween(ListNode head, int left, int right) {
ListNode dummy = new ListNode(0);
ListNode pre = dummy;
ListNode endNode = dummy;

// Let pre point to the previous node of the left position node
for(int i=0;i<left-1;i++){
pre = pre.next;
}

// Let the endNode point to the node in the right position
for(int i=0;i<right;i++){
endNode = endNode.next;
}

// Split the linked list and reverse the linked list from left to right
ListNode startNode  = pre.next;
ListNode cur  = endNode.next;
pre.next = null;
endNode.next = null;

reverseList(startNode);

pre.next = endNode;
startNode.next = cur;

return dummy.next;
}

private void reverseList(ListNode cur) {
ListNode pre = null;
while (cur!=null){
ListNode tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
}
}
```

## leetcode - 142. Circular linked list II

Given the head node of a linked list, it returns the first node from the linked list into the ring. If the linked list is acyclic, null is returned. ```public class Solution {
while (true){
if(fast==null || fast.next==null){
return null;
}
fast = fast.next.next;
slow = slow.next;
if(slow==fast){
break;
}
}
while (slow!=fast){
fast = fast.next;
slow = slow.next;
}
return slow;
}
}
```

## Sword finger Offer - 22 The penultimate node in the lin k ed list

Input a linked list and output the penultimate node in the linked list. In order to conform to the habit of most people, this question starts from 1, that is, the tail node of the linked list is the penultimate node.
For example, a linked list has six nodes. Starting from the beginning, their values are 1, 2, 3, 4, 5 and 6. The penultimate node of this linked list is the node with the value of 4. ```class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
return null;
}
for(int i=0;i<k;i++){
fast = fast.next;
}
while (fast!=null){
slow = slow.next;
fast = fast.next;
}
return slow;
}
}
```

## leetcode - 148. Sort linked list (merge sort algorithm) Divide and Conquer: merge sorting algorithm
The merging method is a top-down merging method. Let the current interval of merging sorting be R[low... high], and the three steps of divide and conquer are:

① Decomposition: divide the current interval into two, that is, find the splitting point
② Solution: recursively merge and sort the two sub intervals R[low... Mid] and R[mid+1... high];
③ Combination: merge the sorted two sub intervals R[low... Mid] and R[mid+1... high] into an ordered interval R[low... high].

The end condition of recursion: the length of the subinterval is 1 (a record is naturally ordered). ```class Solution {
public static void main(String[] args) {
int[] arr = {-3,1,2,3,4,5,6,10};
int left = 0;
int right = arr.length-1;
mergeSort(arr,left,right);
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
}

private static void mergeSort(int[] arr, int left, int right) {
if(left>=right){
return;
}
int mid = left+(right-left)/2;

mergeSort(arr,left,mid);
mergeSort(arr,mid+1,right);
merge(arr,left,mid,mid+1,right);
}

private static void merge(int[] arr, int leftStart, int leftEnd, int rightStart, int rightEnd) {
int i = leftStart;
int j = rightStart;
int k = 0;
int[] tmp = new int[leftEnd-leftStart+rightEnd-rightStart+2];

while (i<=leftEnd && j<=rightEnd){
if(arr[i]<=arr[j]){
tmp[k++] = arr[i++];
}else{
tmp[k++] = arr[j++];
}
}
while (i<=leftEnd){
tmp[k++] = arr[i++];
}
while (j<=rightEnd){
tmp[k++] = arr[j++];
}
k = leftStart;
for(int value:tmp){
arr[k++] = value;
}
}
}
```

Use the merge algorithm to solve this problem:

```class Solution {
return null;
}
// Recursive termination condition
}
while (fast!=null && fast.next!=null){
fast = fast.next.next;
slow = slow.next;
}
slow.next = null;

return mergeSortList(list1,list2);
}

ListNode dummy = new ListNode(0);
ListNode cur = dummy;
cur = cur.next;
}else {
cur = cur.next;
}
}
}
}
return dummy.next;
}
}
```

## leetcode - 23. Merge K ascending linked lists Method 1: time complexity O (k^2*n), space complexity O(1)

```class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if(lists==null || lists.length==0){
return null;
}
ListNode ans = null;
for(int i=0;i<lists.length;i++){
ans = mergeTwoList(ans,lists[i]);
}
return ans;
}

private ListNode mergeTwoList(ListNode list1, ListNode list2) {
if(list1==null && list2==null){
return null;
}
ListNode dummy = new ListNode(0);
ListNode cur = dummy;
while (list1!=null && list2!=null){
if(list1.val<list2.val){
cur.next = list1;
cur = cur.next;
list1 = list1.next;
}else{
cur.next = list2;
cur = cur.next;
list2 = list2.next;
}
}
if(list1!=null){
cur.next = list1;
}
if(list2!=null){
cur.next = list2;
}
return dummy.next;
}
}
```

Method 2: divide, rule and merge The asymptotic time complexity is: O(kn) × logk).
Stack space recursion complexity: K

```class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if(lists==null){
return null;
}
return merge(lists,0,lists.length-1);
}

private ListNode merge(ListNode[] lists, int left, int right) {
// branch
// Note this boundary condition: when left=right, lists[left] should be returned instead of null
if(left==right){
return lists[left];
}
if(left>right){
return null;
}
int mid = left+(right-left)/2;
ListNode list1 = merge(lists,left,mid);
ListNode list2 = merge(lists,mid+1,right);

// close
return mergeList(lists,list1,list2);
}

private ListNode mergeList(ListNode[] lists, ListNode list1, ListNode list2) {
ListNode dummy = new ListNode(0);
ListNode cur = dummy;
while (list1!=null && list2!=null){
if(list1.val<list2.val){
cur.next = list1;
cur = cur.next;
list1 = list1.next;
}else{
cur.next = list2;
cur = cur.next;
list2 = list2.next;
}
}
if(list1!=null){
cur.next = list1;
}
if(list2!=null){
cur.next = list2;
}
return dummy.next;
}
}
```

## leetcode - 24. Exchange the nodes in the linked list

Give you a linked list, exchange the adjacent nodes and return the head node of the linked list after exchange. You must complete this problem without modifying the value inside the node (that is, you can only exchange nodes). ```class Solution {
ListNode dummy = new ListNode(-1);
ListNode pre = dummy;

// 0--1--2
// 0--2--1
while (start!=null && start.next!=null){
ListNode end = start.next;
ListNode tmp = end.next;
pre.next = end;
end.next = start;
start.next = tmp;
pre = start;
start = tmp;
}
return dummy.next;
}
}
```

## leetcode - 147. Insert and sort the linked list Insert sorting algorithm:
Scan every element from scratch. Whenever an element is scanned, it is inserted into the appropriate position of the head to keep the head data in order

If it is the insertion sort of the array, the front part of the array is an ordered sequence. Each time you find the insertion position of the first element (element to be inserted) behind the ordered sequence, move the elements behind the insertion position in the ordered sequence one bit back, and then place the element to be inserted in the insertion position.

```class Solution {
public static void main(String[] args) {
int[] arr = {1,9,5,2,9,3};
insertSort(arr);
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
}

private static void insertSort(int[] arr) {
for(int i=1;i<arr.length;i++){
int insertValue = arr[i];
int insertIndex = i-1;
while (insertIndex>=0 && insertValue<=arr[insertIndex]){
arr[insertIndex+1] = arr[insertIndex];
insertIndex--;
}
arr[insertIndex+1] = insertValue;
}
}
}
```

The insertion sorting algorithm is used to solve this problem:

For the linked list, when inserting elements, you only need to update the pointers of adjacent nodes, and you don't need to move the elements behind the insertion position backward like an array. Therefore, the time complexity of the insertion operation is O(1), but finding the insertion position requires traversing the nodes in the linked list. The time complexity is O(n), so the total time complexity of the insertion sorting of the linked list is still O(n^2), Where n is the length of the linked list. ```class Solution {
return null;
}
// 1 2 7 4 0 5
ListNode dummy = new ListNode(0);
// Last executes the last node of the ordered linked list
// cur points to the node to be sorted
ListNode cur = last.next;
while (cur!=null){
if(last.val<cur.val){
last = last.next;
cur = cur.next;
}else{
last.next = cur.next;
// Use a pointer pre to find the position of the node to be inserted
ListNode pre = dummy;
while (pre.next.val<cur.val){
pre = pre.next;
}
cur.next = pre.next;
pre.next = cur;
cur = last.next;
}
}
return dummy.next;
}
}
```

## leetcode - 148. Sorting linked list (insert sorting algorithm) Insert sorting algorithm:

```class Solution {
return null;
}
// 1 2 7 4 0 5
ListNode dummy = new ListNode(0);
// Last executes the last node of the ordered linked list
// cur points to the node to be sorted
ListNode cur = last.next;
while (cur!=null){
if(last.val<cur.val){
last = last.next;
cur = cur.next;
}else{
last.next = cur.next;
// Use a pointer pre to find the position of the node to be inserted
ListNode pre = dummy;
while (pre.next.val<cur.val){
pre = pre.next;
}
cur.next = pre.next;
pre.next = cur;
cur = last.next;
}
}
return dummy.next;
}
}
```

## leetcode - 86. Separate linked list

Give you a head node of the linked list and a specific value X. please separate the linked list so that all nodes less than x appear before nodes greater than or equal to X. You should keep the initial relative position of each node in both partitions. ```class Solution {
public ListNode partition(ListNode head, int x) {
return null;
}
// Define two dummy nodes and divide the linked list into two linked lists, one is greater than or equal to X and the other is less than x
// cur is used to traverse the linked list nodes and compare with x
ListNode largeNode = new ListNode(-1);
ListNode smallNode = new ListNode(-1);
ListNode small = smallNode;
ListNode large = largeNode;
while (cur!=null){
if(cur.val<x){
small.next = cur;
small = small.next;
cur = cur.next;
}else{
large.next = cur;
large = large.next;
cur = cur.next;
}
}
large.next = null;
small.next = largeNode.next;
return smallNode.next;
}
}
```

## leetcode - 61. Rotating linked list

Give you a head node of the linked list. Rotate the linked list and move each node of the linked list k positions to the right. Method 1:

```class Solution {
public ListNode rotateRight(ListNode head, int k) {
return null;
}
// First, let the tail of the linked list point to the head to form a ring, find the last k node, and disconnect the previous node

// Find the length of the linked list
int n = 0;
while (fast!=null){
n++;
fast = fast.next;
}
// The reason for this is that k > n exists
k = k % n;
// Find the previous node of the penultimate node
for(int i=0;i<k;i++){
fast = fast.next;
}
while (fast.next!=null){
fast = fast.next;
slow = slow.next;
}
// Disconnect from the previous node of the penultimate node
ListNode tmp = slow.next;
slow.next = null;
return tmp;
}
}
```

Method 2:

```class Solution {
public ListNode rotateRight(ListNode head, int k) {
return null;
}
// First, let the tail of the linked list point to the head to form a ring, find the last k node, and disconnect the previous node

// Find the length of the linked list
int n = 1;
while (cur.next != null) {
cur = cur.next;
n++;
}

// Find the previous node of the penultimate node
k = n-k%n;
for(int i=0;i<k;i++){
cur = cur.next;
}
ListNode tmp = cur.next;
cur.next = null;
return tmp;
}
}
```

## leetcode - 328. Parity linked list

Give the head node of the order linked list, combine all nodes with odd index and even index respectively, and then return the reordered list. The index of the first node is considered to be odd, the index of the second node is even, and so on.

Note that the relative order within even and odd groups should be the same as when entering. You have to solve this problem under the additional space complexity of O(1) and the time complexity of O(n). Method 1: the idea I used in this question is the same as the idea separated by 86 questions. For the optimization method, see method 2

```class Solution {
return null;
}
ListNode oddNode = new ListNode(0);
ListNode evenNode = new ListNode(0);
ListNode odd = oddNode;
ListNode even = evenNode;
int count = 1;
while (cur!=null){
if(count%2==1){
odd.next = cur;
cur = cur.next;
odd = odd.next;
count++;
}else{
even.next = cur;
cur = cur.next;
even = even.next;
count++;
}
}
// There are even number of linked list nodes
if(odd.next!=null){
odd.next = null;
}
// There are an odd number of linked list nodes
if(even.next!=null){
even.next=null;
}
odd.next = evenNode.next;
return oddNode.next;
}
}
```

Method 2: merge after separating nodes (the idea is the same as method 1, which is the optimization of method 1)

For the original linked list, each node is an odd or even node. The head node is an odd node, the last node of the head node is an even node, and the parity of adjacent nodes is different. Therefore, odd nodes and even nodes can be separated into odd linked list and even linked list, and then the even linked list is connected after the odd linked list, and the combined linked list is the result linked list.

Maintain two pointers, odd and even, pointing to odd and even nodes respectively. Initially, odd = head and even = evenHead. The odd and even nodes are separated into two linked lists by iteration. In each step, the odd nodes are updated first, and then the even nodes are updated.

• When updating odd nodes, the latter node of odd nodes needs to point to the latter node of even nodes, so make odd next = even. Next, and then make odd = odd Next, at this time, odd becomes the next node of even.
• When updating even nodes, the latter node of even nodes needs to point to the latter node of odd nodes, so make even next = odd. Next, and then make even = even Next, at this time, even becomes the next node of odd.

After the above operation, the separation of an odd node and an even node is completed. Repeat the above operation until all nodes are separated. The condition that all nodes are separated is that even is an empty node or even Next is an empty node. In this case, odd points to the last odd node (that is, the last node of the odd linked list).

The idea seems very complex. It's better to understand the code. In fact, it's very simple:

``` class Solution {
return null;
}
// When the number of linked list nodes is odd, it is even next!= null
// When the number of linked list nodes is even, yes (even!=null)
while (even!=null && even.next!=null){
odd.next = even.next;
odd = odd.next;
even.next = odd.next;
even = even.next;
}
}
}
```

## leetcode - 2. Addition of two numbers (summation of linked list)

Give you two non empty linked lists to represent two non negative integers. They store each number in reverse order, and each node can store only one number. Please add the two numbers and return a linked list representing sum in the same form. You can assume that neither number starts with 0 except the number 0. ```class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
// l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
/**
*        9  9  9  9  9  9  9
*    +   9  9  9  9  0  0  0
*   ------------------------------
*        8  9  9  9  0  0  0  1
*/
ListNode dummy = new ListNode(0);
ListNode cur = dummy;
int sum = 0;
while (l1!=null || l2!=null){
if(l1!=null){
sum = sum+l1.val;
l1 = l1.next;
}
if(l2!=null){
sum = sum + l2.val;
l2 = l2.next;
}
cur.next = new ListNode(sum%10);
cur = cur.next;
sum = sum / 10;
}
if(sum==1){
cur.next = new ListNode(1);
}
return dummy.next;
}
}
```

## Sword finger Offer - 06 Print linked list from end to end

Enter the head node of a linked list, and return the value of each node from tail to head (returned by array). ```class Solution {
return new int[]{};
}
Stack<Integer> stack = new Stack<>();
while (cur!=null){
stack.push(cur.val);
cur = cur.next;
}
int[] arr = new int[stack.size()];
for(int i=0;i<arr.length;i++){
arr[i] = stack.pop();
}
return arr;
}
}
```

Keywords: Java Back-end

Added by tress on Fri, 04 Mar 2022 16:20:49 +0200