在实际开发中,遇到指针我们要做好防御性编程。
题目描述 :
给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点 。
题目链接:
这到题目算是链表的基础操作 , 我这里写的是链表的前面是一个虚拟头节点,这样我们就不用考虑删除元素是否是头节点这个情况了 。主要掌握虚拟头节点,当然可以不用这个方法,但是这样会时链表的操作变得更加简洁。 删除的核心操作就是,找到要删除节点的前一个节点:他的next 就是我们要删除的节点 如果删除的节点的前一个节点是p, 那么 p->next = p->next->next。
视频讲解:
手把手带你学会操作链表 | LeetCode:203.移除链表元素_哔哩哔哩_bilibili
- ListNode* removeElements(ListNode* head, int val) {
- ListNode *virtualNode =new ListNode; //定义一个虚拟头结点
- virtualNode->next=head;
- ListNode *temp=virtualNode;
- //遍历链表
- while( temp!= NULL && temp->next!=NULL){
- if(temp->next->val==val){ //找到了满足条件的节点
- //删除节点
- head=temp->next;
- temp->next=temp->next->next;
- delete head;
- continue;
- }
- temp=temp->next;
- }
- return virtualNode->next;
- }
题目描述 :
设计链表,可以是单链表也可以是双链表。
题目链接:
我自己给出的答案是单链表的设计 , 包括一些基础操作,增删查。我们需要知道的是链表也是从0开始计数的,删除和在指定位置插入,我们都是找到待操作位置的前一个位置。
视频讲解:
帮你把链表操作学个通透!LeetCode:707.设计链表_哔哩哔哩_bilibili
- class MyLinkedList { //才用虚拟头节点法
-
- public:
- MyLinkedList() {
- head = new ListHead;
- head->next = NULL;
- head->val = 0;
- size = 0;
- }
-
- //获取元素
- int get(int index) {
- //防御性编程
- if (!head ) return -1; //链表不存在,或者为空
- if (head->next == NULL) return -1;
- if (index < 0) return -1; //下标不合法
- if (index >= size) return -1;
- int i = 0;
- ListNode* p = head; //指向虚拟头结点
- while (i <=index) {
- p = p->next;
- i++;
- }
- return p->val;
- }
-
- //头部添加
- void addAtHead(int val) {
- if (!head) return;
- ListNode* node = new ListNode; //生成一个节点
- node->val = val;
- node->next = head->next;
- head->next = node;
- size++;
- }
-
- //尾部添加
- void addAtTail(int val) {
- if (!head) return; //判断链表是否存在
- ListNode* node = new ListNode; //生成一个节点
- node->val = val;
- ListNode* p = head; //指向第一个节点
- while (p->next!=NULL) {
- p = p->next;
- }
- //循环结束后说明刚好处于最后一个位置
- node->next = p->next;
- p->next = node;
- size++;
- }
-
- //在指定位置添加
- void addAtIndex(int index, int val) {
- if (!head) return; //链表不存在
- if (index < 0) return; //位置不合法
- if (index > size) return;
- ListNode* p = head; //指向虚拟头结点
- while ( index--) {
- p = p->next;
- }
- ListNode* node = new ListNode; //生成一个节点
- node->val = val;
- node->next = p->next;
- p->next = node;
- size++;
- }
-
- //删除位置的元素
- void deleteAtIndex(int index) {
- if (!head ) return;
- if (head->next == NULL) return; //没有元素
- if (index < 0) return ; //下标不合法
- if (index >= size) return ;
- LinkList* p = head;
- if (index == 0) {
- head->next = head->next->next;
- size--;
- return;
- }
-
- while ( index-- ) {
- p = p->next;
- }
- cout << p->val << endl;
- LinkList* temp = p->next;
- p->next = p->next->next;
- delete temp;
- size--;
- }
- void print() {
- ListNode* node = head->next;
- while (node) {
- cout << node->val << " ";
- node = node->next;
- }
- cout << endl;
- }
-
- private:
- //节点结构
- typedef struct LinkList {
- struct LinkList* next;
- int val;
- }ListHead,ListNode;
- ListHead* head;
- int size; //链表的长度
-
- };
题目描述 :
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
题目链接:
这到题目,我们采用双指针的思路。指针 pro 用来记录我们head的前一个节点,开始没有翻转之前,head的前一个节点为NULL ,所有pro初始值为NULL,而我们的第二个指针 temp 则用来记录head的下一个节点。
循环遍历我们的链表,终止条件是 head 指针为空,1-》2断开之后,1-》的next指向了 NULL,然后我们的 temp继续往后移动,而我们的 pro 则指向 head。
视频加文字讲解:
- ListNode* reverseList(ListNode* head) {
- if(!head) return NULL; //链表为空
- if(head->next==NULL) return head; //只有一个元素的情况
- ListNode *pro=NULL ; //用来只想当前位置的前一个节点
- ListNode *temp=head ;
- while( head ){
- temp = temp->next;
- head->next=pro;
-
- pro=head;
- head=temp;
- }
- head=pro;
- return head;
- }