Leetcode 203. 移除链表元素
ListNode* removeElements(ListNode* head, int val) {
ListNode* cur=nullptr;
ListNode* front=head;
//cur=cur->next;
//用while不用if是为了防止头部几个节点都重复的情况,删除节点直到遇到一个不是val的节点
while(head)
{
front=head;
if(head->val==val){
head=head->next;
delete front;
}else{
break;
}
}
cout<<"head="<<head->val<<endl;
cur=head;
//从第一个不是不是val值得节点开始,遍历链表
for(;cur!=nullptr;cur=cur->next){//这个地方出了问题
cout<<cur->val<<endl;
if(cur->val==val){
cout<<"delete:"<<cur->val<<endl;
front->next=cur->next;
delete cur;
cur=front->next;
}
front=cur;
}
cout<<endl;
return head;
}
Line 32: Char 36: runtime error: member access within null pointer of type ‘ListNode’ (solution.cpp)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior prog_joined.cpp:37:36
原因应该是因为,cur=cur->next,如果next是空的时候会遇到这个问题
感悟:
机器的运行规律和我们人不一样,我看到这个数组可以直观的直到要删除哪个,但链表/指针,只能一个一个往后找,就像是在黑暗的单行道上行车,你只能往前走,所以就要设计一个
leetcode707
在构造函数的时候拖了很多时间
leetcode 206翻转链表
我一开始的思路:
class Solution {
public:
//从头到尾打印整个链表
void printlinks(ListNode* head)
{
ListNode* cur=head;
for(;cur->next!=nullptr;cur=cur->next)
{
cout<<cur->val<<"->";
}
cout<<cur->val<<endl<<endl;
}
ListNode* reverseList(ListNode* head) {
ListNode* front=head;
ListNode* rear=head;
ListNode* cur=nullptr;
ListNode* temp=nullptr;
if(head==nullptr||head->next==nullptr)
return head;
for(;rear->next!=nullptr;rear=rear->next)
{
//cout<<rear->val<<"->";
}
cout<<endl;
cur=front->next;
temp=front;
temp->next=nullptr;
while(cur!=rear)
{
//cout<<cur->val<<"->";
temp=cur;
cur=cur->next;
temp->next=front;
front=temp;
//cout<<cur->val<<"->";
}
cur->next=temp;
return rear;
}
};
思考:主要是在如何反转、步骤逻辑上(一共用了4个指针)//
对边界的处理(开头和结尾,这四个指针怎么安排)//
如果元素只有1个或者2 个怎么办
改进后代码:
ListNode* reverseList(ListNode* head) {
ListNode* front=head;
ListNode* cur=nullptr;
ListNode* temp=nullptr;
cur=front->next;
front->next=nullptr;
while(cur)
{
temp=cur;
cur=cur->next;
temp->next=front;
front=temp;
}
//printlinks(temp);
return temp;
}
递归版本
思考:1.怎样通过递归,让next指向前一个节点呢??????
代码随想录版本:
感觉非常的简洁没有臃肿,思路上先进***(他用temp去保存cur->next,这一点很重要)***
值得学习的逻辑:
1.处理开头,通过pre=NULL,cur->next=pre;可以让head指向null,同时temp能保存第二个节点;
2.末尾处,cur=NULL推出循环,此时pre(pre总是落后于cur)指向最后一个节点
ListNode* reverseList(ListNode* head) {
ListNode* temp; // 保存cur的下一个节点
ListNode* cur = head;
ListNode* pre = NULL;
/*
开始cur指向head;
1.temp指向cur->next用于"保存"下一个节点
2.cur反转当前指向(通过pre"保存"前一个节点)
3.更新pre和cur
4.开启下一轮循环,直到cur指向了末节点的next既NULL;
*/
while(cur) {
temp = cur->next; // 保存一下 cur的下一个节点,因为接下来要改变cur->next
cur->next = pre; // 翻转操作
// 更新pre 和 cur指针
pre = cur;
cur = temp;
}
return pre;
}
感悟:
写的程序要简洁,逻辑决定步骤,每个步骤要通用性强;
还有就是,一定要按照机器(程序的逻辑)去思考,链表对于机器或者指针来讲是一条单行道