Day3 203.移除链表元素 707.设计链表 206.反转链表
今日学习时长:3h
链表基础
链表的初始化
struct ListNode{
int val;
ListNode *next;
ListNode(int x): val(x), next(NULL){}
}
203 移除链表元素
初始解答
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
while(head != nullptr && head -> val == val){
head = head -> next;
//头结点单独处理
}
ListNode* pre = head;
while(pre != nullptr && pre -> next != nullptr){
if(pre -> next -> val == val){
pre -> next = pre -> next -> next;
//不能移到下一个节点,出现连续的节点的val满足条件会有遗漏的情况出现
//cpp需要处理删除的节点
}else{
pre = pre -> next;
}
}
return head;
}
};
特殊用例:
- 开头head的val为val
- 结尾head的val为val
- 连续几个节点的val为val
示例解答(虚拟头结点)
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点
dummyHead->next = head; // 将虚拟头结点指向head,这样方面后面做删除操作
ListNode* cur = dummyHead;
while (cur->next != NULL) {
if(cur->next->val == val) {
ListNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
} else {
cur = cur->next;
}
}
head = dummyHead->next;//返回时,要返回虚拟头结点的next
delete dummyHead;
return head;
}
};
707 设计链表
漏洞百出的写法
class MyLinkedList {
public:
ListNode * head;
ListNode * tail;
int length;
MyLinkedList() {
head = nullptr;
tail = nullptr;
length = 0;
}
int get(int index) {
if(index < 0 || index > length - 1) return -1;
int pre = 0;
ListNode * cur = head;
for(int i = 0; i < index; i++){
cur = cur -> next;
}
return cur -> val;
}
void addAtHead(int val) {
ListNode * add = new ListNode(val);
add -> next = head;
head = add;
if(tail == nullptr) tail = add;
length ++;
}
void addAtTail(int val) {
ListNode *add = new ListNode(val);
if(tail == nullptr){
head = add;
tail = add;
}else{
tail -> next = add;
tail = tail -> next;
}
length ++;
}
void addAtIndex(int index, int val) {
if(index <= 0) {
addAtHead(val);
return;
}
if(index == length) {
addAtTail(val);
return;
}
int count = 0;
ListNode * cur = head;
ListNode * add = new ListNode(val);
while(count < index - 1){
cur = cur -> next;
count ++;
}
add -> next = cur -> next;
cur -> next = add;
length ++;
}
void deleteAtIndex(int index) {
if(get(index) == -1) return;
length --;
if(index == 0){
ListNode * tmp = head;
head = head -> next;
delete tmp;
return;
}
int count = 0;
ListNode * cur = head;
while(count < index - 1){
cur = cur -> next;
count ++;
}
ListNode * tmp = cur -> next;
cur -> next = tmp -> next;
//delete tmp;
if(length == 0) {
tail = nullptr;
head = nullptr;
}
}
};
/**
* 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);
*/
length没有及时加减
count在while循环中没有自增
tail在addAtHead中没有更新和添加
etc
链表写了不少次,但还是很生疏写不对
尝试用虚拟头结点书写+没有尾结点
class MyLinkedList {
public:
struct LinkedNode {
int val;
LinkedNode* next;
LinkedNode(int val):val(val), next(nullptr){}
};
MyLinkedList() {
_dummyHead = new LinkedNode(0);
_size = 0;
}
int get(int index) {
if(index < 0 || index > (_size - 1)){
return -1;
}
LinkedNode * cur = _dummyHead -> next;
while(index --){
// index为0时不会进入循环
cur = cur -> next;
}
return cur -> val;
}
void addAtHead(int val) {
LinkedNode* newNode = new LinkedNode(val);
newNode -> next = _dummyHead -> next;
_dummyHead -> next = newNode;
_size ++;
}
void addAtTail(int val) {
LinkedNode * newNode = new LinkedNode(val);
LinkedNode* cur = _dummyHead;
while(cur -> next != nullptr){
cur = cur -> next;
}
cur -> next = newNode;
_size ++;
}
void addAtIndex(int index, int val) {
if(index > _size) return;//勿漏题目条件
if(index == _size) {
addAtTail(val);
return;//没有及时return 造成了重复在tail末尾增加
}
if(index <= 0) {
addAtHead(val);
return;
}
LinkedNode* newNode = new LinkedNode(val);
LinkedNode* cur = _dummyHead;
while(index --){
cur = cur -> next;
}
newNode -> next = cur -> next;
cur -> next = newNode;
_size ++;
}
void deleteAtIndex(int index) {
if(get(index) == -1) return;
LinkedNode* cur = _dummyHead;
while(index --){
cur = cur -> next;
}
LinkedNode* tmp = cur -> next;
cur -> next = tmp -> next;
delete tmp;
_size --;
}
private:
LinkedNode* _dummyHead;
int _size;
};
标程中可以借鉴的地方
void addAtIndex(int index, int val) {
if(index > _size) return;
if(index < 0) index = 0;
LinkedNode* newNode = new LinkedNode(val);
LinkedNode* cur = _dummyHead;
while(index--) {
cur = cur->next;
}
newNode->next = cur->next;
cur->next = newNode;
_size++;
}
将所有情况通过更改index转化为一种
206 反转链表
初始解法——记录数值
class Solution {
public:
ListNode* reverseList(ListNode* head) {
int a[5005];
int size = 0;
ListNode* cur = head;
while(cur != nullptr){
a[size] = cur -> val;
size ++;
cur = cur -> next;
}
ListNode* newList= new ListNode(0);
cur = newList;
for(int i = 0; i < size; i++){
ListNode * newNode = new ListNode(a[size - 1 - i]);
cur -> next = newNode;
cur = cur -> next;
}
return newList -> next;
}
};
双指针法
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* temp; // 保存cur的下一个节点
ListNode* cur = head;
ListNode* pre = NULL;
while(cur) {
temp = cur->next; // 保存一下 cur的下一个节点,因为接下来要改变cur->next
cur->next = pre; // 翻转操作
// 更新pre 和 cur指针
pre = cur;
cur = temp;
}
return pre;
}
};
递归法
class Solution {
public:
ListNode* reverse(ListNode* pre,ListNode* cur){
if(cur == NULL) return pre;
ListNode* temp = cur->next;
cur->next = pre;
// 可以和双指针法的代码进行对比,如下递归的写法,其实就是做了这两步
// pre = cur;
// cur = temp;
return reverse(cur,temp);
}
ListNode* reverseList(ListNode* head) {
// 和双指针法初始化是一样的逻辑
// ListNode* cur = head;
// ListNode* pre = NULL;
return reverse(NULL, head);
}
};