链表
5.2打卡
题目链接:leecode203 移除链表元素
在刚开始一共想了两种写法,但是第一种写法真的是一个很低级的错误,分类讨论头节点情况时。删除头节点时的操作,因为在第一次操作的时候总是报错,
5。
/**
* 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* current = head;
while(current){
//分情况讨论,如果是头节点
if(current->val == val){
ListNode* tmp = current;
current = tmp->next;
delete tmp;
}
//如果不是头节点
else if(current->next!=nullptr && current->next->val == val){
ListNode *tmp = current->next;
current->next = tmp->next;
delete tmp;
}
else{
current = current->next;
}
}
return head;
}
};
经过不断的测试才发现,错误的源头。这个报错告诉的我们是,我们在使用一个已经被delete的节点。确实是这样子的,我们仔细看,我们用current指向了头节点,所以当测试用例出现【7,7,7,7】,7的时候我们会把链表删干净,这时候如果返回头节点的话,这里的头节点已经被我们删除了!,所以只能返回current。所以以下写法是正确的不适用虚拟头节点的写法
/**
* 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){
ListNode* tmp = head;
head = head->next;
delete tmp;
}
ListNode* current = head;
while(current!=nullptr && current->next!=nullptr){
if(current->next->val == val)
{
ListNode* tmp = current->next;
current->next = tmp->next;
delete tmp;
}
else
{
current = current->next;
}
}
return head;
}
};
下面介绍一种使用虚拟头节点的方法
/**
* 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* dummyNode = new ListNode(0);
dummyNode->next = head;
ListNode* current = dummyNode;
while(current->next!=nullptr){
if(current->next->val == val){
ListNode* tmp = current->next;
current->next = tmp->next;
delete tmp;
}
else current = current->next;
}
return dummyNode->next;
}
};
第二种方法是比较推荐的方法,建立虚拟头节点,这样就不用考虑分情况的问题了。
题目链接:
leecode707 设计链表
这道题有几个需要注意的点就是,一定要设置size参数,因为很多测试用例,会删除一些根本不存在的数据。而且在添加,删减的时候也一定记得判断index和size之间的关系!代码如下
class MyLinkedList {
public:
struct LinkedNode {
int val;
LinkedNode* next;
LinkedNode(int val):val(val), next(nullptr){}
};
int size;
LinkedNode* dummyNode;
MyLinkedList() {
dummyNode = new LinkedNode(0);
size = 0;
}
int get(int index) {
if(index > size-1 || index < 0) return -1;
LinkedNode* current = dummyNode;
while(index-->=0){
current = current->next;
}
return current->val;
}
void addAtHead(int val) {
LinkedNode* pN = new LinkedNode(val);
pN->next = dummyNode->next;
dummyNode->next = pN;
size++;
}
void addAtTail(int val) {
LinkedNode* pN = new LinkedNode(val);
LinkedNode* cur = dummyNode;
if(size == 0) dummyNode->next = pN;
else{
while(cur->next!=nullptr){
cur = cur->next;
}
cur->next = pN;
}
size++;
}
void addAtIndex(int index, int val) {
if(index <= size){
//在第index之前添加,等于在index-1之后添加一个
int new_index = index-1;
LinkedNode* pN = new LinkedNode(val);
LinkedNode* current = dummyNode;
while(new_index-->=0){
current = current->next;
}
pN->next = current->next;
current->next = pN;
size++;
}
}
void deleteAtIndex(int index) {
if(index < size){
int new_index = index-1;
LinkedNode* current = dummyNode;
while(new_index-->=0){
current = current->next;
}
LinkedNode* tmp = current->next;
current->next = tmp->next;
delete tmp;
size--;
}
}
};
/**
* 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);
*/