203.移除链表元素
- 讲解链接
https://programmercarl.com/0203.%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8%E5%85%83%E7%B4%A0.html
- 看答案前
移除元素:元素所在地址从链表中移除,并且把断掉的链表链接起来。
遇到的困难:知道思路,写不出来。
- 看答案后
原来这么简单,可为什么我写不出来?
思路:
1 定义一个虚拟头节点,该节点一开始就指向head,这样做的目的是保持处理逻辑的一致性,否则头节点的处理方法还需要另外写代码,使用的虚拟头节点就不要重写了。
2 定义一个临时节点,用于寻找要删除的元素。初始值赋为虚拟节点。
3 依次移动临时节点,发现目标元素就删除。直到移动到链表尾部。
4 删除操作:将要删除元素的后面部分链表临时存储,删除当前元素,再把存储的链表和删除前一个节点连接起来。
- 代码
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: ListNode* removeElements(ListNode* head, int val) { ListNode* dummy_head = new ListNode(0);//生成一个虚拟头节点 dummy_head->next = head; //将头节点和链表连起来 ListNode* curr = dummy_head; //用于遍历链表的指针 while(curr->next!=nullptr){ if(curr->next->val == val){ ListNode* temp_node = curr->next; curr->next = curr->next->next; delete temp_node;//释放内存 temp_node = nullptr; }else{ curr = curr->next; } } //因为存在链表头节点被删的可能,如果被删除,不做如下操作而直接返回head则链表地址会指向一个未分配内存的位置,会报错.所以需要重新赋值头节点. head = dummy_head->next;// return head; } };
- 总结
虚拟头节点是个好东西,省了好多事。
707.设计链表
讲解链接:
https://programmercarl.com/0707.%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8.html
看解答前:
我的思路:
1 实现个链表节点,很简单但是我实现的方法实在构造函数里实现的节点,这样做不可以,因为每次创建对象都回重新构造构造一个节点。
2 get实现:根据输入的索引返回对应的值。没问题。
3 addAtHead实现:知道在都节点恰插入数据,但是细节没处理好。
4 addAtTail实现:末尾添加就好,直接找到链表末尾新建一个节点链接起来。
5 addAtIndex实现:要考虑索引的大小,这里没注意细节,还是出问题了。
6 deleteAtIndex实现:删除数据后忘记对数据赋予nullptr了。
看解答后:
不得不说虚拟头节点真是好东西。真的可以节省很多事。但是链表的设计过程中index的大小还是要处理好,不然容易出错。两者配合好才行。
代码:
class MyLinkedList { public: struct LInkedNode{ int val; LInkedNode* next; LInkedNode(int val):val(val),next(nullptr){ } }; MyLinkedList():size_(0),dummy_head_(new LInkedNode(0)){ } int get(int index) { if(index > size_ - 1||index < 0){ return -1; } LInkedNode* curr = dummy_head_->next; while(index -- ){ curr = curr->next; } int val = curr->val; return val; } void addAtHead(int val) { LInkedNode* curr = new LInkedNode(val); curr->next = dummy_head_->next; dummy_head_->next = curr; ++size_; } void addAtTail(int val) { LInkedNode* curr = dummy_head_; while(curr->next!=nullptr){ curr = curr->next; } curr->next = new LInkedNode(val); ++size_; } void addAtIndex(int index, int val) { if(index >size_ )return; if(index < 0 )index = 0; LInkedNode* curr = dummy_head_; while(index--){ curr = curr->next; } LInkedNode* tmp = curr->next; curr->next = new LInkedNode(val); curr->next->next = tmp; ++size_; } void deleteAtIndex(int index) { if(index >=size_||index < 0)return; LInkedNode* curr = dummy_head_; while(index --){ curr = curr->next; } LInkedNode* tmp = curr->next; curr->next = curr->next->next; delete tmp; tmp = nullptr; size_--; } private: int size_; LInkedNode* dummy_head_; }; /** * Your MyLinkedList object will be instantiated and called as such: * MyLinkedList* obj = new MyLinkedList(); * int param_1 = obj->get(index); * obj->addAtHead(val); * obj->addAtTail(val); * obj->addAtIndex(index,val); * obj->deleteAtIndex(index); */
总结:
脑子比手快,脑子能想到,手总是写不出来。。。
206.反转链表
讲解链接:
看解答前:
写过,用的是双指针方法,但是还是忘了,算是复习。
看解答后:
双指针已经看过,再次复习一遍,递归的写了半天还是写错。但是思路确实也比较简单。
代码:
双指针
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: //双指针法 ListNode* reverseList(ListNode* head) { ListNode* pre = nullptr; ListNode* curr = head; while(curr!=nullptr){ ListNode* tmp = curr->next; curr->next = pre; pre =curr; curr = tmp; } return pre; } };
递归
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: ListNode* reverse(ListNode* pre,ListNode*curr){ if(curr==nullptr)return pre; ListNode* tmp = curr->next; curr->next = pre; // pre = curr; // curr=tmp; return reverse(curr,tmp); } ListNode* reverseList(ListNode* head) { return reverse(nullptr,head); } };
总结:
这些题目都是看了答案后才觉得原来如此简单,同时也注意到之前写过的算法里面用到的思路如果不及时复习,后面再次遇到时又会忘记。时间太赶,无法好好整理文章,先这样,加油。已经8.21了,洗漱出门。