代码随想录算法训练营第三天| 203.移除链表元素 707.设计链表 206.反转链表
203.移除链表元素
链表定义
struct ListNode
{
int val;
ListNode* next;
ListNode(): val(0), next(NULL) {};
ListNode(int x): val(x), next(NULL) {};
ListNode(int x, ListNode* next): val(x), next(next) {};
}
1.在原链表上移除链表元素
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
while(head!= NULL && head->val == val)
{
ListNode* tmp = head;
head = head->next;
delete tmp;
}
ListNode* cur = head;
while(cur != NULL)
{
if(cur->next != NULL && cur->next->val == val)
{
ListNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
}
else
cur = cur->next;
}
return head;
}
};
为什么是
if(cur->next != NULL && cur->next->val == val)
而不是
if(cur->next->val == val)
考虑一个例子,4->5->6,
要删除6的话,到最后一步,cur->next是NULL,访问cur->next->val会报空指针错误
指针
ListNode* node;
这个node里面储存的就是地址了,所以可以有以下操作
ListNode* head
ListNode* node;
node = head
-> 和 .
箭头(->):左边必须为指针;
点号(.):左边必须为实体。
//实体
ListNode node1;
node1.val = 2;
//指针
ListNode node2;
node2->val = 2;
NULL
NULL就是传说中的空指针
delete
delete ptr -- 代表用来释放内存,且只用来释放ptr指向的内存。
ptr为指针
2.添加虚拟头结点法
/**
* 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;
ListNode* dummy_head = new ListNode();
dummy_head->next = head;
ListNode* cur = dummy_head;
while(cur != NULL)
{
if(cur->next != NULL && cur->next->val == val)
{
ListNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
}
else
cur = cur->next;
}
//return head;
return dummy_head->next;
}
};
为什么是
ListNode* dummy_head = new ListNode();
而不是
ListNode* dummy_head;
错误原因:没有实例化,而接下来的代码里要调用dummy_head里的东西,所以会报错
为什么是
return dummy_head->next;
而不是
return head;
因为之前的head有可能被释放掉了
707.设计链表
mydemo-未添加内存释放
class MyLinkedList {
public:
//结点结构体
struct LinkedNode {
int val;
LinkedNode* next;
LinkedNode(): next(NULL) {};
LinkedNode(int val):val(val), next(NULL){};
};
LinkedNode* dummyhead;
int size;
MyLinkedList() {
dummyhead = new LinkedNode(); //不要忘记实例化
size = 0;
}
int get(int index) {
LinkedNode* cur = dummyhead;
if(index>=0 && index<size)
{
while(index--)
cur = cur->next;
return cur->next->val;
}
else
return -1;
}
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 != NULL)
{
cur = cur->next;
}
cur->next = newnode;
size++;
}
void addAtIndex(int index, int val) {
LinkedNode* newnode = new LinkedNode(val);
LinkedNode* cur = dummyhead;
if(index>=0 && index<=size)
{
while(index--)
{
cur = cur->next;
}
newnode->next = cur->next;
cur->next = newnode;
size++;
}
}
void deleteAtIndex(int index) {
LinkedNode* cur = dummyhead;
if(index>=0 && index<size)
{
while(index--)
{
cur = cur->next;
}
cur->next = cur->next->next;
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);
*/
mydemov2--内存释放版
void deleteAtIndex(int index) {
LinkedNode* cur = dummyhead;
if(index>=0 && index<size)
{
while(index--)
{
cur = cur->next;
}
LinkedNode* tmp = cur->next;
cur->next = cur->next->next;
size--;
//内存释放
delete tmp;
}
}
206 反转链表
1.双指针法
/**
* 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 = NULL;
ListNode* cur = head;
while(cur != NULL) //可以写成 while(cur)
{
ListNode* temp = cur->next;
cur->next = pre;
pre = cur;
cur = temp;
}
return pre;
}
};
暂存cur->next;
ListNode* temp = cur->next;
key:改变方向
cur->next = pre;
双指针向前移动(注意顺序)
pre = cur;
cur = temp;
如果顺序搞错了:
cur = temp;
pre = cur
//pre移动到的就不是cur之前的位置了,就错了
2.递归代码:
正确代码:
/**
* 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* cur, ListNode* pre)
{
if(cur==NULL) return pre;
ListNode* temp = cur->next;
cur->next = pre;
return reverse(temp, cur);
}
ListNode* reverseList(ListNode* head) {
ListNode* pre = NULL;
ListNode* cur = head;
return reverse(cur, pre);
}
};
报错:C++不能函数里面定义函数
/**
* 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 = NULL;
ListNode* cur = head;
void reverse(ListNode* cur, ListNode* pre)
{
if(cur)
{
ListNode* temp = cur->next;
cur->next = pre;
pre = cur;
cur = temp;
}
}
reverse(cur, pre);
return pre;
}
};
Line 19: Char 13: error: function definition is not allowed here
报错:为啥这样写,所有案例的输出都是 []
/**
* 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) {}
* };
*/
void reverse(ListNode* cur, ListNode* pre);
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* pre = NULL;
ListNode* cur = head;
reverse(cur, pre);
return pre;
}
};
void reverse(ListNode* cur, ListNode* pre)
{
if(cur)
{
ListNode* temp = cur->next;
cur->next = pre;
pre = cur;
cur = temp;
reverse(cur,pre);
}
}
- 链表的结构确实发生了反转,但是,reverseList函数里的pre指针并没有被重新赋值成反转链表的pre的地址。
- void reverse(ListNode* cur, ListNode* pre),这样传进去的是地址
所以可以改写成reverse(head, Null)可以更加清晰的看到传进去的是地址,所以pre并没有被重新赋值
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* pre = NULL;
ListNode* cur = head;
//reverse(cur, pre);
reverse(head, NULL);
return pre;
}
};