Linked list related algorithms

Recently found a course of high quality at a station, the following is the course notes!

Basic operation

Node structure

typedef struct{
    int val;
    Node* next;
}Node;

Find operation

Node* search(int val){
    Node* pNode = root; // 根结点
    while(pNode != nullptr)
         if(pNode->val == val){
             return pNode;
          }
         pNode = pNode->next;
        }
     return nullptr;
 }

Delete operation – give the previous node of the node to be deleted

void delNode(Node* prev){
	Node* curr = prev->next;
	prev->next = curr->next;
	delete curr;
}

Delete operation-give the node to be deleted

void delNode(Node* curr){
	if(curr->next != nullptr){
		Node* temp = curr->next;
		curr->val = temp->val;
		curr->next = temp->next;
		delete temp;
	}else{
		Node* pNode = root; // 头节点
		while(pNode->next != curr){
			pNode = pNode->next;
		}
		pNode->next = nullptr;
		delete curr;
	}
}

Related algorithms

Deduplication of linked list elements

Remove Duplicates from Sorted List
Given a sorted linked list, delete all duplicates such that each element appear only once.For example, Given 1->1->2,return 1->2.Given 1->1->2->3->3, return 1->2->3

Node* deleteDuplicates(Node* head){
	if(head == nullptr){
		return nullptr;
	}
	Node* node = head;
	while(node->next != nullptr){
		if(node->val == node->next->val){
			Node* temp = node->next;
			node->next = temp->next;
			delete temp;
		}else{
			node = node->next;
		}
	}
	return head; 
}

Dummy Node tips
Consider:
a. Which node's next pointer will be affected, you need to amend the pointer
b. If the node to be deleted is a memory space that is opened up dynamically, you need to release this part of the memory (c / c ++)
using dummy node is a very useful trick: as long as the uncertainty involved in the operation of the head node, the head node operation, might create the node dummy:
ListNode
dummy = new new ListNode (0);
dummy-> = the Next head;
*
.
.

Remove Duplicates from Sorted List ||
Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.
For example,
Given 1->2->3->3->4->4->5,return 1->2->5.
Given 1->1->1->2->3, return 2->3

Node* deleteDuplicates(Node* head){
	if(head == nullptr){
		return nullptr;
	}
	Node* dummy = new Node(0);
	dummy->next = head;
	Node* node = dummy;
	while(node->next != nullptr && node->next->next != nullptr){
		if(node->next->val == node->next->next->val){
			int val_pre = node->next->val;
			while(node->next != nullptr && val_pre == node->next->val){
				Node* temp = node->next;
				node->next = temp->next;
				delete temp;
			}
		}else{
			node = node->next;
		}
	}
	return dummy->next;
}

Given a linked list and a value, write a reorder to rearrange the linked list so that the small ratio is all to the left and the large ratio is to the right

Node* partition(Node* head, int x){
	if(head == nullptr){
		return nullptr;
	}
	Node* dummyleft = new Node(0);
	Node* dummyright = new Node(0);
	Node* left = dummyleft;
	Node* right = dummyright;
	Node* node = head;
	while(node->next != nullptr){
		if(node->val < x){
			left->next = node;
			left = left->next;
		}else{
			right->next = node;
			right = right->next;
		}
		node = node->next;
	}
	left->next = dummyright->next;
	right->next = nullptr;
	return dummyleft->next;
}

Catch pointer skills

For the problem of finding a specific position of the list, you may use two chaser and runner to traverse the list at different speeds to find the target position: Node chaser = head, runner = head. And you can use a simple small test case to verify

Find the midpoint of a linked list

Node* midpoint(Node* head){
	if(head == nullptr){
		return nullptr;
	}
	Node* chaser = head, runner = head;
	while(runner && runner->next){
		runner = runner->next->next;
		chaser = chaser->next;
	}
	return chaser;
}

Find the penultimate k node of the linked list

Node* findkthtoLast(Node* head, int k){
	if(head == nullptr || k < 0){
		return nullptr;
	}
	Node* runner = head;
	Node* chaser = head;
	while(k){
		runner = runner->next;
	}
	if(runner == nullptr){
		return nullptr;
	}
	while(runner->next != nullptr){
		runner = runner->next;
		chaser = chaser->next;
	}
	return chaser;
}

Given a linked list with rings, find the node where the ring starts

Analysis: To find a specific location, use the runner technique. Runner traverses at twice the speed, assuming there is a loop, then runner and chaser must be able to meet at a certain point. After the encounter, let chaser trigger from the head to catch up with the runner again, and the node of the second encounter is the position where the loop starts

How to judge whether two singly linked lists have an intersection

Move the node after the kth element of the linked list to the front

Example:
list = 10->20->30->40->50->60 k = 4
change to 50->60->10->20->30->40

void rotate(Node** root, int k){
	if(k == 0){
		return;
	}
	Node* current = root;
	for(int count = 1; count < k && current != nullptr;count++){
		current = current->next;
	}
	if(current == nullptr){
		return;
	}
	Node *kthNode = current;
	while(current->next != nullptr){
		current = current->next;
	}
	current->next = root;
	root = kthNode->next;
	kthNode->next = nullptr;
}

.
Pattern recognition
1. When traversing the linked list, note that only one or a pair of nodes is processed per loop. The core node only handles the current one, otherwise it is easy to have repeated processing problems.

.

Reverse linked list

Reverse Linked List
Reverse the linked list and return the new head.

—递归版本—

Node* reverseList(Node* head){
	if(head == nullptr){
		return nullptr;
	}
	Node* prev = nullptr;
	while(head != nullptr){
		Node* curr = head;
		head = head->next;
		curr->next = prev;
		prev = curr;
	}
	return prev;
}

—Non-recursive version—

Node* reverseList(Node* head){
	if(head == nullptr){
		return head;
	}
	if(head->next == nullptr){
		return head;
	}
	Node* newHead = reverseList(head->next);
	head->next->next = head;
	head->next = nullptr;
	return newhead;
}

.
Pattern recognition
2. Swap Node problem
3. If two nodes are swapped, if there is no deletion, the next pointers of the two nodes' prev nodes and the next pointers of these two nodes will be affected. It is always possible
a. First exchange the values ​​of the next pointers of the two prev nodes
b. Then exchange the values ​​of the next pointers of the
two nodes Regardless of the relative and absolute positions of the two nodes, the above processing method always holds

.

Swap two adjacent nodes

Swap Adjacent Nodes
Given a linked list,swap every two adjacent nodes and return its head.

Node* swapPairs(Node* head){
	if(head == nullptr){
		return head;
	}
	Node* dummy = new Node(0);
	dummy->next = head;
	Node* prev = dummy;
	Node* node1 = head;
	Node* node2 = head->next;
	while(node1 && node1->next != nullptr){
		node2 = node1->next;
		prev->next = node1->next;
		
		node1->next = node2->next;
		node2->next = node1;

		prev = node1;
		node1 = prev->next;
	}
	return dummy->next;
}

.
Pattern recognition
3. The process two linked list problems, circulatory conditions generally can use while (l1 && l2), and then handle the rest of the list of non-NULL In this case, the boundary case special treatment, the conventional case conventional treatment.

.

Linked list addition

Add List Sum
Given two linked lists, each element of the lists is a integer. Write a function to return a new list, whick is the “sum” of the given two lists.
Part a. Given input (7->1->6) + (5->9->2), output 2->1->9.
Part b. Given input (6->1->7) + (2->9->5), output 9->1->2.

Part a–

Node* addTwoNumbers(Node* l1, Node* l2){
	Node dummy(0);
	Node* p = &dummy;
	int cn = 0;
	while(l1 || l2){
		int val = cn + (l1 ? l1->val : 0) + (l2 ? l2->val : 0);
		cn = val / 10;
		val = val % 10;
		p->next = new Node(val);
		p = p->next;
		if(l1){
			l1 = l1->next;
		}
		if(l2){
			l2 = l2->next;
		}
	}
	if(cn != 0){
		p->next = new Node(cn);
		p = p->next;
	}
	return dummy->next;
}

Partb-
Problem analysis: For a, the solution of the front node does not depend on the rear node, so it is sufficient to traverse the solution in sequence. For b, the solution of the front node depends on the back node (carry), so it must be processed by recursion or stack. And, the result returned by subproblem can be a custom structure (carry + sub-list). Of course, you can also use the solution of a after solving the reverse list.

Combine two or more sorted linked lists

Merge Two Sorted List
Merge two sorted linked lists and return it as a new list.

Node* mergeTwoLists(Node* l1, Node* l2){
	Node* dummy = new Node(0);
	Node* curr = dummy;
	while(l1 && l2){
		if(l1->val <= l2->val){
			curr->next = l1;
			l1 = l1->next;
		}{
			curr->next = l2;
			l2 = l2->next;
		}
		curr = curr->next;
	}
	curr->next = (l1 != nullptr) ? l1 : l2;
	return dummy->next;
}

Merge K Sorted List

Node* mergeKLists(vector<Node*>&lists){
	if(lists.size() == 0)return nullptr;
	Node* p = lists[0];
	for(int i = 0; i < l1sts.size(); i++){
		p = mergeTwoLists(p, lists[i]);
	}
	return p;
} 

Not finished!

Published 21 original articles · Likes0 · Visits 163

Guess you like

Origin blog.csdn.net/qq_45227330/article/details/105060058