代码随想录算法训练营第三天 | 203.移除链表元素、 707.设计链表、 206.反转链表
移除链表元素
思路:
遍历链表,若遇到目标值,则删除,记得释放内存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
class Solution { public: ListNode* removeElements(ListNode* head, int val) { ListNode* cur=new ListNode(0); cur->next=head; ListNode *ahead; ahead=cur; while (ahead->next != NULL) { if (ahead->next->val == val) { ListNode* tmp = ahead->next; ahead->next = ahead->next->next; delete tmp; } else ahead=ahead->next; } return cur->next; } };
|
注意:本题应用了虚拟头结点,这样避免了目标元素在头结点的分类讨论。
设计链表
思路:
△头指针、头结点、第一个节点的区别
第一个节点:链表中存储第一个元素的结点,是头结点后边第一个结点。
头指针:指链表的指针,是指向链表中第一个节点(或为头结点或为首元结点)的指针。
头结点:是在链表开始结点之前附加的一个结点,其数据域一般无意义,不存放有效数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| class MyLinkedList { public: struct LinkedNode { int val; struct LinkedNode* next; LinkedNode(int x):val(x),next(nullptr){} }; MyLinkedList() { aHead = new LinkedNode(0); _size = 0; }
int get(int index) { if (index > (_size - 1) || index < 0) return -1; LinkedNode* cur = aHead->next; while (index--) { cur = cur->next; } return cur->val; } void addAtHead(int val) { LinkedNode* newNode = new LinkedNode(val); newNode->next = aHead->next; aHead->next = newNode; _size++;; }
void addAtTail(int val) { LinkedNode* newnode = new LinkedNode(val); LinkedNode* cur = aHead; while (cur->next != nullptr) { cur = cur->next; } cur->next = newnode; _size++; }
void addAtIndex(int index, int val) { if (index > _size) return; LinkedNode* newNode = new LinkedNode(val); LinkedNode* cur = aHead; 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 = aHead; while (index--) { cur = cur->next; } LinkedNode* tmp = cur->next; cur->next = cur->next->next; delete tmp; tmp = nullptr; _size--; } private: int _size; LinkedNode* aHead; };
|
注意:删除tmp注意加一句tmp=nullptr。
反转链表
思路:
使用两个指针初始时一个指向NULL,一个指向首节点,逐个改变方向。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Solution { public: ListNode* reverseList(ListNode* head) { ListNode* temp; ListNode* cur = head; ListNode* pre = NULL; while (cur) { temp = cur->next; cur->next = pre; pre = cur; cur = temp; } return pre;
} };
|
递归法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Solution { public: ListNode* reverse(ListNode* pre,ListNode* cur){ if(cur == NULL) return pre; ListNode* temp = cur->next; cur->next = pre; return reverse(cur,temp); } ListNode* reverseList(ListNode* head) { return reverse(NULL, head); }
};
|
还有另外一种与双指针法不同思路的递归写法:从后往前翻转指针指向。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Solution { public: 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; } };
|