203.移除链表元素
思路
两种方法:一是直接在原链表上操作;二是设置虚拟头结点。
解题方法
第一种:直接在原链表上操作,将头结点和非头结点分开操作;第二种,设置虚拟头结点,统一操作,因为最后要返回头结点,所以需要临时设立一个指针,指向(虚拟)头结点,最后返回虚拟头结点的next;
复杂度
时间复杂度:O(n)
空间复杂度:O(1)
Code
第一种
/**
* 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!=NULL&&head->val==val)
{
head=head->next;
}
ListNode *cur=head;
while(cur!=NULL&&cur->next!=NULL)
{
if(cur->next->val==val)
{
cur->next=cur->next->next;
}
else
{
cur=cur->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 *dummyhead=new ListNode(0);
dummyhead->next=head;
ListNode *cur=dummyhead;
while(cur->next!=NULL)
{
if(cur->next->val==val)
{
cur->next=cur->next->next;
}
else
{
cur=cur->next;
}
}
return dummyhead->next;
}
};
707.设计链表
解题方法
第一种:直接使用原来的链表进行操作
第二种:使用虚拟头结点
复杂度
时间复杂度:涉及Index的为O(index),其余为O(1);
空间复杂度:O(n);
Code
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>(_size-1)||(index<0))return -1;
LinkedNode *cur=_dummyHead->next;
while(index)
{
cur=cur->next;
index--;
}
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<0)index=0;
LinkedNode *newnode=new LinkedNode(val);
LinkedNode *cur=_dummyHead;
while(index)
{
cur=cur->next;
index--;
}
newnode->next=cur->next;
cur->next=newnode;
_size++;
}
void deleteAtIndex(int index) {
if(index>=_size||index<0){
return;
}
LinkedNode *cur=_dummyHead;
while(index)
{
cur=cur->next;
index--;
}
cur->next=cur->next->next;
_size--;
}
void printLinkedList() {
LinkedNode* cur = _dummyHead;
while (cur->next != nullptr) {
cout << cur->next->val << " ";
cur = cur->next;
}
cout << endl;
}
private:
int _size;
LinkedNode* _dummyHead;
};
/**
* 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.反转链表
思路
首先想到的是暴力解法。但是太过浪费内存空间。定义一个新链表,实现链表的翻转。
解题方法
第一种:双指针写法。定义两个指针:cur,pre;cur指向头结点,pre初始化为NULL。定义一个临时的节点来保存cur->next;然后翻转,cur->next=pre;pre=cur;cur=tmp;
第二种:递归写法。和双指针的逻辑相同。只不过采用递归函数来写。
复杂度
时间复杂度:O(n)
空间复杂度:第一种O(1) 第二种O(n)
Code
双指针写法
/**
* 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 *cur=head;
ListNode *pre=NULL;
ListNode *tmp;
while(cur)
{
tmp=cur->next;
cur->next=pre;
pre=cur;
cur=tmp;
}
return pre;
}
};
递归写法
/**
* 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 *pre,ListNode *cur)
{
if(cur==NULL)return pre;
ListNode *tmp=cur->next;
cur->next=pre;
return reverse(cur,tmp);
}
ListNode* reverseList(ListNode* head) {
return reverse(NULL,head);
}
};