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

发布时间:2023年12月30日

第二章?链表part01

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

?链表理论基础?

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

文章链接:代码随想录

?203.移除链表元素??

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

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

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

?707.设计链表??

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

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

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

?206.反转链表?

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

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


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)。

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

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);
	}
}

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

定义一个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;
}

文章来源:https://blog.csdn.net/2302_79277225/article/details/135279032
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。