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

第二章 链表part01

  •  链表理论基础 
  •  203.移除链表元素 
  •  707.设计链表 
  •  206.反转链表 

 链表理论基础 

建议:了解一下链接基础,以及链表和数组的区别 

文章链接:代码随想录

 203.移除链表元素  

建议: 本题最关键是要理解 虚拟头结点的使用技巧,这个对链表题目很重要。

题目链接:203. 移除链表元素 - 力扣(LeetCode)

文章讲解/视频讲解::代码随想录

 707.设计链表  

建议: 这是一道考察 链表综合操作的题目,不算容易,可以练一练 使用虚拟头结点

题目链接:707. 设计链表 - 力扣(LeetCode)

文章讲解/视频讲解:代码随想录

 206.反转链表 

题目链接:206. 反转链表 - 力扣(LeetCode)

文章讲解/视频讲解:代码随想录


代码随想录算法训练营day3|203.移除链表元素、707.设计链表、206.反转链表_第1张图片

c++代码示例如下O(n)

ListNode* removeElements(ListNode* head, int val) {
	while (head != NULL && head->val == val) {
		ListNode* tmp = head;
		head = head->next;
		delete tmp;
	}
	ListNode* cur = head;
	while (cur != NULL && cur->next != NULL) {
		if (cur->next->val == val) {
			ListNode* tmp = cur->next;
			cur->next = cur->next->next;
			delete tmp;
		}
		else {
			cur = cur->next;
		}
	}
	return head;
}

设置一个虚拟头结点再进行移除节点操作

ListNode* removeElements(ListNode* head, int val) {
	ListNode* dummyHead = new ListNode(0);
	dummyHead->next = head;
	ListNode* cur = dummyHead;
	while (cur->next != NULL) {
		if (cur->next->val == val) {
			ListNode* tmp = cur->next;
			cur->next = cur->next->next;
			delete tmp;
		}
		else {
			cur = cur->next;
		}
	}
	head = dummyHead->next;
	delete dummyHead;
	return head;
}

这个例子中ListNode(0)源于链表结构体定义中的构造函数。

ListNode(int x) : val(x),next(NULL) {}

让我们逐一解析这段代码:

  1. ListNode (int x): 这是ListNode类的构造函数的声明。它接受一个整数参数x
  2. :val(x), next(NULL): 这是初始化列表。它用于初始化类的成员变量。在这里,val成员变量被初始化为x,而next成员变量被初始化为NULL
  3. { }: 这是构造函数的主体。在这里它是空的,因为所有的初始化都在初始化列表中完成了。

总的来说,当你创建一个新的ListNode对象并传递一个整数给它时,这个构造函数将确保该节点的值被设置为该整数,并且该节点没有指向任何下一个节点(因为next被初始化为NULL)。

注意:如果不定义构造函数使用默认构造函数的话,在初始化的时候不能直接给变量赋值!

代码随想录算法训练营day3|203.移除链表元素、707.设计链表、206.反转链表_第2张图片

代码随想录算法训练营day3|203.移除链表元素、707.设计链表、206.反转链表_第3张图片

c++代码示例如下

class MyLinkedList {
public:
	struct LinkedNode {
		int val;
		LinkedNode* next;
		LinkedNode(int val) :val(val), next(NULL) {}
	};
	MyLinkedList() {
		dummyHead = new LinkedNode(0);
		size = 0;
	}

	int get(int index) {
		if (index > (size - 1)|| index < 0){
			return -1;
		}
		LinkedNode* cur = dummyHead->next;
		while (index--) {
			cur = cur->next;
		}
		return cur->val;
	}

	void addAtHead(int val) {
		LinkedNode* newNode = new LinkedNode(val);
		newNode->next = dummyHead->next;
		dummyHead->next = newNode;
		size++;
	}

	void addAtTail(int val) {
		LinkedNode* newNode = new LinkedNode(val);
		LinkedNode* cur = dummyHead;
		while (cur->next != NULL) {
			cur = cur->next;
		}
		cur->next = newNode;
		size++;
	}

	void addAtIndex(int index, int val) {
		if (index > size) return;
		if (index < 0) index = 0;
		LinkedNode* newNode = new LinkedNode(val);
		LinkedNode* cur = dummyHead;
		while (index--) {
			cur = cur->next;
		}
		newNode->next = cur->next;
		cur->next = newNode;
		size++;

	}

	void deleteAtIndex(int index) {
		if (index >= size || index < 0) {
			return;
		}
		LinkedNode* cur = dummyHead;
		while (index--) {
			cur = cur->next;
		}
		LinkedNode* tmp = cur->next;
		cur->next = cur->next->next;
		delete tmp;
		tmp = NULL;
		size--;
	}
private:
	int size;
	LinkedNode* dummyHead;
};

c语言代码示例如下

typedef struct MyLinkedList {
	int val;
	struct MyLinkedList* next;
}MyLinkedList;
MyLinkedList* myLinkedListCreate() {
	MyLinkedList* head = (MyLinkedList*)malloc(sizeof(MyLinkedList));
	head->next = NULL;
	return head;
}
int myLinkedListGet(MyLinkedList* obj, int index) {
	MyLinkedList* cur = obj->next;
	for (int i = 0; cur != NULL; i++) {
		if (i == index) {
			return cur->val;
		}
		else {
			cur = cur->next;
		}
	}
	return -1;
}
void myLinkedListAddAtHead(MyLinkedList* obj, int val) {
	MyLinkedList* nhead = (MyLinkedList*)malloc(sizeof(MyLinkedList));
	nhead->val = val;
	nhead->next = obj->next;
	obj->next = nhead;
}
void myLinkedListAddAtTail(MyLinkedList* obj, int val) {
	MyLinkedList* cur = obj;
	while (cur->next != NULL) {
		cur = cur->next;
	}
	MyLinkedList* ntail = (MyLinkedList*)malloc(sizeof(MyLinkedList));
	ntail->val = val;
	ntail->next = NULL;
	cur->next = ntail;
}
void myLinkedListAddAtIndex(MyLinkedList* obj,int index,int val) {
	if (index == 0) {
		myLinkedListAddAtHead(obj, val);
		return;
	}
	MyLinkedList* cur = obj->next;
	for (int i = 1; cur != NULL; i++){
		if (i == index) {
			MyLinkedList* newNode = (MyLinkedList*)malloc(sizeof(MyLinkedList));
			newNode->val = val;
			newNode->next = cur->next;
			cur->next = newNode;
			return;
		}
		else {
			cur = cur->next;
		}
	}
}
void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) {
	if (index == 0) {
		MyLinkedList* tmp = obj->next;
		if (tmp != NULL) {
			obj->next = tmp->next;
			free(tmp);
		}
		return;
	}
	MyLinkedList* cur = obj->next;
	for (int i = 1; cur != NULL && cur->next != NULL; i++) {
		if (i == index) {
			MyLinkedList* tmp = cur->next;
			if (tmp != NULL) {
				cur->next = tmp->next;
				free(tmp);
			}
			return;
		}
		else {
			cur = cur->next;
		}
	}
}
void myLinkedListFree(MyLinkedList* obj) {
	while (obj != NULL) {
		MyLinkedList* tmp = obj;
		obj = obj->next;
		free(tmp);
	}
}

代码随想录算法训练营day3|203.移除链表元素、707.设计链表、206.反转链表_第4张图片

代码随想录算法训练营day3|203.移除链表元素、707.设计链表、206.反转链表_第5张图片

        已知头结点,使用双指针法一个节点一个节点的处理:

定义一个cur指针(head),pre指针(NULL),定义一个临时变量tmp把cur->next的内容拿出来,然后把pre指针放进去,就完成了节点的反转。更新pre指针(cur),cur指针(tmp)。循环遍历完链表就完成整体的反转。循环结束时,cur一定指向最后一个节点的->next==NULL,pre一定指向最后一个节点。返回pre

c++代码示例如下O(n)

ListNode* reverseList(ListNode* head) {
	ListNode* tmp;
	ListNode* cur = head;
	ListNode* pre = NULL;
	while (cur) {
		tmp = cur->next;
		cur->next = pre;
		pre = cur;
		cur = tmp;
	}
	return pre;
}

还可以用递归实现,能够迭代就一定可以递归!

ListNode* reverse(ListNode* pre, ListNode* cur) {
	if (cur == NULL) {
		return pre;
	}
	ListNode* tmp = cur->next;
	cur->next = pre;
	return reverse(cur, tmp);
}

这个代码实现逻辑和双指针实现逻辑一模一样,实质上都是从前往后反转指针指向,其实还可以从后往前反转指针。(这个方法还不懂)

ListNode* reverseList(ListNode* head) {
	if (head == NULL) return NULL;
	if (head->next == NULL) return head;
	ListNode* last = reverseList(head->next);
	head->next->next = head;
	head->next = NULL;
	return last;
}

你可能感兴趣的:(代码随想录,算法)