LeetCode 203 移除链表元素
题目链接:203. 移除链表元素
做题情况:由于自己以前见过这些题目,所以大致知道思路,只是很多细节问题自己没有把控住,代码实现能力有待提高。自己当时一开始就想到加入虚拟头节点(隐隐约约记得数据结构中说过虚拟头节点在链表中增删操作中很方便),然后去按照这种思路实现,但是需要自己很快解决的问题,而自己写加通过共花费了半个小时左右,下面是自己独立实现ac的代码:
/**
* 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* virtualhead=new ListNode(-1,head);//此处命名不规范,一看就不专业,应该命名为dummyHead,new申请节点的时候,做两步走好,清晰,像卡哥这样
// ListNode* dummyHead = new ListNode(0);
//dummyHead->next = head;
ListNode* cur=virtualhead;
while(cur!=nullptr&&cur->next!=nullptr){//此处第一个判断条件可以不要的
if(cur->next->val==val){
cur->next=cur->next->next;//删除节点没有释放内存,不好的习惯
continue;
}
cur=cur->next;
}
return virtualhead->next;//虚拟头节点内存没有释放
}
};
//内存释放最后自己写了个,但是自己写的时候很别扭,要习惯这些操作,毕竟以后自己相当一位c++后端工程师,这个很重要
看了卡哥视频和代码随想录书相关部分后,发现自己写的这个带虚拟头节点的版本代码书写实现有很多需要改的地方,虽然ac了,详见上述给的注释。
题目思路:
思路一:直接使用原来的链表进行移除节点操作,这时候要区分头节点和非头节点的处理方法,自己仿照实现且ac代码:
/**
* 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) {
//对于头节点的删除逻辑
while(head!=nullptr&&head->val==val){//if和while的使用还是很讲究的,注意
ListNode* temp=head;
head=head->next;
delete temp;
}
//对于非头节点的删除逻辑
ListNode* cur=head;
while(cur!=nullptr&&cur->next!=nullptr){//此处while循环第一个判断条件
if(cur->next->val==val){
ListNode* temp=cur->next;
cur->next=cur->next->next;
delete temp;
}else{
cur=cur->next;
}
}
return head;
}
};
思路二:使用一个虚拟头节点进行移除节点操作,这时候头节点和非头节点处理方法一样,自己仿照实现且ac代码:
/**
* 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* dummyhead=new ListNode();
dummyhead->next = head;
ListNode* cur=dummyhead;
while(cur->next!=nullptr){
if(cur->next->val==val){
ListNode* temp=cur->next;
cur->next=cur->next->next;
delete temp;
}else{
cur=cur->next;
}
}
ListNode* temp=dummyhead->next;
delete dummyhead;
return temp;
}
};
LeetCode 707 设计链表
题目链接:707. 设计链表
做题情况:自己在这道题目上面花了一个小时去独立完成,但是最后没有ac出来,边看卡哥视频和代码随想录书相关部分边修改自己程序中的bug,真的看了好久才把这两个地方找出来才ac掉(自己写的主要在addAtIndex那里两个自己犯错误的地方,找了好久),具体见下面代码:
//自己写的这个命名还得改下,不然好别扭,以及new申请空间的初始化值的时候也得改下,以及上一题说的两部走等等,详细参见卡哥的代码
/**
* 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 MyLinkedList {
public:
MyLinkedList() {
virtualhead = new ListNode(-1, nullptr);
length=0;
}
int get(int index) {
if(index<0||index>=length)return -1;
ListNode* cur=virtualhead;
index=index+1;
while(index--){
cur=cur->next;
}
return cur->val;
}
void addAtHead(int val) {
ListNode* addnode =new ListNode(val, virtualhead->next);
virtualhead->next=addnode;
length++;
}
void addAtTail(int val) {
ListNode* cur=virtualhead;
while(cur->next!=nullptr){
cur=cur->next;
}
ListNode* addnode =new ListNode(val, nullptr);
cur->next=addnode;
length++;
}
//下述这两个错误卡了我好久,得学会打断点调试
//注意这里面前两个判断条件成立后执行完则返回,此处也可以不调用函数的,直接参照卡哥那个写法最好,而且思路更清晰更方便
void addAtIndex(int index, int val) {
if(index<0){
addAtHead(val);
return;
}
if(index==length){
addAtTail(val);
return;
}
if(index>length)return;
ListNode* cur=virtualhead;
while(index--){
cur=cur->next;
}
ListNode* addnode =new ListNode(val, cur->next);//还有这里的cur->next而不是cur->next->next,注意逻辑,结合实例进行编程
cur->next=addnode;
length++;
}
void deleteAtIndex(int index) {
if(index<0||index>=length)return;
ListNode* cur=virtualhead;
while(index--){
cur=cur->next;
}
ListNode* temp=cur->next;
cur->next = temp->next;
delete temp;
length--;
}
private:
ListNode* virtualhead;//采用虚拟头节点
int length;
};
/**
* 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);
*/
以后得多调试和结合实例编程,不要看错误和心里想,这样效率极低,而且还容易出错
LeetCode 206 反转链表
题目链接:206. 反转链表
做题情况:自己拿到这道题目就想到暴力解法,去申请内存空间来进行反转,当时知道可以在原链表上操作,可是想了十几分钟都没有思路,看了卡哥视频和代码随想录书相关部分后,自己才知道原来这么简单,自己太菜了。在原链表上进行操作主要两种实现方法:①双指针法 ②递归写法,感觉这道题目自己得记住具体思路和实现了,感觉很巧妙,就是这么简单而自己却想不到,具体ac代码:
/**
* 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* cur=head;
while(cur!=nullptr){
ListNode* temp=cur->next;
cur->next=pre;
pre=cur;
cur=temp;
}
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* cur){
if(cur==nullptr)return pre;
ListNode* temp=cur->next;
cur->next=pre;
return reverse(cur,temp);
}
ListNode* reverseList(ListNode* head) {
return reverse(nullptr, head);
}
};
递归写法实际上也是参照双指针写法来的,卡哥讲解得很明白
今天自己独立做三道题目花了一个半小时,ac出第一道,第二道没ac出来(就是自己所说的上面两个自己犯的错误,这两个错位找了好久),第三道题目除了暴力就没想到双指针法具体思路,包看视频和书以及写博客共花了五个小时左右,呜呜,效率低下的一天
贵在坚持,加油,共勉