链表理论及与数组的区别
①链表是通过指针串联在一起的线性结构,包括数据域和指针域两个部分。常见的链表类型有:单向链表、双向链表以及环形链表。
②与数组的区别:数组在内存中是连续的,而链表则是非连续的,链表通过指针域的指针连接在内存中的各个节点。
③定义链表:
struct ListNode{
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *ptr) : val(x), next(ptr) {}
};
题目一 :203移除链表元素
①本人的解法:首先找到需要返回的头节点的位置,再从该头节点的位置开始遍历整个链表,最后返回头节点,详细代码如下所示:
/**
* 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 && head->val == val){
head = head->next;
}
if(!head)
return head;
ListNode *now = head;
ListNode *prev = new ListNode(-1,head);
while(now){
if(now->val == val){
prev->next = now->next;
now = now->next;
}
else{
prev = now;
now = now->next;
}
}
return head;
}
};
②虚拟节点解法:这种方法更加便利,修改头节点和非头节点的方式做到了统一,且在C/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* removeElements(ListNode* head, int val) {
ListNode *dummyNode = new ListNode(-1,head);
ListNode *cur = dummyNode;
while(cur->next){
if(cur->next->val == val){
ListNode *temp = cur->next;
cur->next = cur->next->next;
delete temp;
}
else{
cur = cur->next;
}
}
head = dummyNode->next;
delete dummyNode;
return head;
}
};
题目二 :707设计链表
第一遍做没思路,链表对象中如何放入结点并保存???用什么数据结构来完成呢?
看了提示之后,写出如下代码:
// class ListNode {
// public:
// int val;
// ListNode *next;
// ListNode(int x) : val(x), next(nullptr) {}
// };
class MyLinkedList {
public:
MyLinkedList() {
size = 0;
dummyNode = new ListNode(-1);
}
int get(int index) {
if(index > (size - 1) || index < 0)
return -1;
ListNode *curr = dummyNode;
while(index--){
curr = curr->next;
}
return curr->next->val;
}
void addAtHead(int val) {
ListNode* newHead = new ListNode(val);
newHead->next = dummyNode->next;
dummyNode->next = newHead;
size++;
return;
}
void addAtTail(int val) {
ListNode *curr = dummyNode;
while(curr->next){
curr = curr->next;
}
curr->next = new ListNode(val);
size++;
return;
}
void addAtIndex(int index, int val) {
if(index > size)
return;
ListNode *curr = dummyNode;
while(index--){
curr = curr->next;
}
ListNode* tempNode = new ListNode(val);
tempNode->next = curr->next;
curr->next = tempNode;
size++;
return;
}
void deleteAtIndex(int index) {
if(index >= size)
return;
ListNode *curr = dummyNode;
while(index--){
curr = curr->next;
}
ListNode *temp = curr->next;
curr->next = curr->next->next;
delete temp;
size--;
return;
}
private:
int size;//用于记录链表的长度
ListNode* dummyNode;//虚拟节点
};
/**
* 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);
*/
题目三:206反转链表
①双指针法:这个方法是我一开始就想到的,也写出了具体的代码,结果如下:
/**
* 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* temp = nullptr;
ListNode* prev = nullptr;
ListNode* curr = head;
while(curr){
temp = curr->next;
curr->next = prev;
prev = curr;
curr = temp;
}
return prev;
}
};
②递归解法:该解法的思路与双指针法是一样的,只是代码写法不同,代码可以总结如下:
/**
* 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* prev, ListNode* curr) {
if(!curr)
return prev;
ListNode* temp = curr->next;
curr->next = prev;
return reverse(curr, temp);
}
ListNode* reverseList(ListNode* head) {
return reverse(nullptr, head);
}
};