一、设计链表
1.题目
2.思路
这道题用虚拟头结点来做代码量会少点且容易理解
这道题目设计链表的五个接口:
- 获取链表第index个节点的数值(对于直接读取函数,实现时直接让指针指向该位置就行)
- 在链表的最前面插入一个节点(1.题目没有给head这个指针,则不需要操作 2.直接用虚拟头结点即可操作 3.链表长度需要增加)
- 在链表的最后面插入一个节点(1.cur指针需要先指向虚拟头结点,为了防止链表为空!2.链表长度需要增加)
- 在链表第index个节点前面插入一个节点(1.cur指针需要先指向虚拟头结点,为了找到插入位置前一个节点)
- 删除链表的第index个节点(释放指针内存后需要定义为空指针,防止成为野指针)
3.代码
class MyLinkedList {//类的知识有点遗忘了
public:
//定义链表
struct LinkedNode{
int val;
LinkedNode* next;
LinkedNode(int val):val(val),next(nullptr){}//个构造函数的初始化列表
};
MyLinkedList() {//初始化链表
vitalhead = new LinkedNode(0);//使用虚拟头结点
_size = 0;//作用:统计链表长度
}
int get(int index) {// 直接读current的值
if(index < 0 || index > (_size-1)){
return -1;
}
LinkedNode* current = vitalhead->next;
while(index--){
current = current->next;
}
return current->val;
}
void addAtHead(int val) {//需要移动头结点吗?
LinkedNode* temp = new LinkedNode(val);
temp->next = vitalhead->next;
vitalhead->next = temp;
_size++;//重要!!!
}
void addAtTail(int val) {
LinkedNode* current = vitalhead;//防止是空的
LinkedNode* temp = new LinkedNode(val);//默认没有指向
while(current->next != NULL){
current = current->next;
}
current->next = temp;
_size++;
}
void addAtIndex(int index, int val) {
if(index < 0) index = 0;
if(index > _size) return;//如果 index 等于链表的长度,那么该节点会被追加到链表的末尾
LinkedNode* current = vitalhead;//这个位置要注意是虚拟结点,为了找添加位置的前一个节点
LinkedNode* temp = new LinkedNode(val);
while(index--){
current = current->next;
}
temp->next = current->next;
current->next = temp;
_size++;
}
void deleteAtIndex(int index) {
if(index < 0 || index > (_size-1)){
return ;//返回空
}
LinkedNode* current = vitalhead;
while(index--){//
current = current->next;
}//找到前一个结点
LinkedNode* temp = current->next;
current->next = current->next->next;
delete temp;//释放空间
temp = nullptr;
//delete命令指示释放了temp指针原本所指的那部分内存,
//被delete后的指针temp的值(地址)并非就是NULL,而是随机值。也就是被delete后,
//如果不再加上一句temp=nullptr,tmp会成为乱指的野指针
//如果之后的程序不小心使用了tmp,会指向难以预想的内存空间
_size--;
}
void printLinkedList(){
LinkedNode* current = vitalhead;
while(current->next != NULL){
cout<<current->next->val<<" ";
current = current->next;
}
cout << endl;
}
private:
int _size;
LinkedNode* vitalhead;
};
/**
* 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);
*/
二、翻转链表
1.题目
2.思路
2.1 双指针
注意后面的更新顺序
2.2 递归算法
思路和双指针差不多
3.代码
双指针代码
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* current = head;
ListNode* pre = NULL;
ListNode* temp;
while(current){
temp = current->next;
current->next = pre;
pre = current;
current = temp;
}
return pre;
}
};
递归算法
class Solution {
public:
ListNode* refunc(ListNode* cur,ListNode* pre){
if(cur == nullptr) return pre;
ListNode* temp = cur->next;
cur->next = pre;
return refunc(temp,cur);
}
ListNode* reverseList(ListNode* head) {
return refunc(head,nullptr);
}
};