DAY3 链表part01
今日任务
● 链表理论基础
● 203.移除链表元素
● 707.设计链表
● 206.反转链表
链表理论基础
文章链接:https://programmercarl.com/%E9%93%BE%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html
1、循环链表用于解决约瑟夫环的问题
2、自定义链表结点的结构体
1 struct LinkNode 2 { 3 int val; 4 LinkNode* next; 5 LinkNode():val(0),next(NULL) {}//初始化函数1; 6 LinkNode(int x):val(x),next(NULL) {}//初始化函数2; 7 LinkNode(int x,LinkNode *next):val(0),next(next) {}//初始化函数3; 8 }//自定义结构体时自选
LinkNode *head= new Linknode(x);
3、若使用C++默认的初始化函数,则初始化不能赋值
LinkNode *head= new Linknode();//即初始化函数1
203.移除链表元素
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode() : val(0), next(nullptr) {} 7 * ListNode(int x) : val(x), next(nullptr) {} 8 * ListNode(int x, ListNode *next) : val(x), next(next) {} 9 * }; 10 */ 11 class Solution { 12 public: 13 ListNode* removeElements(ListNode* head, int val) { 14 ListNode* dummy=new ListNode(0); 15 dummy->next=head; 16 ListNode*p=dummy; 17 while(p->next!=NULL) 18 { 19 if(p->next->val==val) 20 { 21 ListNode* q=p->next; 22 p->next=p->next->next; 23 delete(q);//注意释放 24 } 25 else p=p->next; 26 } 27 head=dummy->next; 28 return head; 29 } 30 };
重点掌握虚拟头节点dummy的用法
题目链接/文章讲解/视频讲解::https://programmercarl.com/0203.%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8%E5%85%83%E7%B4%A0.html
707.设计链表
1 class MyLinkedList { 2 public: 3 struct LinkNode 4 { 5 int val; 6 LinkNode* next; 7 LinkNode(int x):val(x),next(NULL){}; 8 }; 9 MyLinkedList() { 10 dummy=new LinkNode(0); 11 cnt=0; 12 }//掌握类的语法 13 14 int get(int index) { 15 if(index<0||index>=cnt) return -1; 16 else 17 { 18 LinkNode*p=dummy->next; 19 while(index--) 20 { 21 p=p->next; 22 }//p定位到下标为index的位置 23 return p->val; 24 } 25 } 26 27 void addAtHead(int val) { 28 LinkNode*newNode=new LinkNode(val); 29 newNode->next=dummy->next; 30 dummy->next=newNode; 31 cnt++; 32 } 33 34 void addAtTail(int val) { 35 LinkNode*newNode=new LinkNode(val); 36 LinkNode*p=dummy; 37 while(p->next!=NULL) p=p->next; 38 p->next=newNode; 39 cnt++; 40 } 41 42 void addAtIndex(int index, int val) { 43 if(index<0||index>cnt) return; 44 else if(index==cnt) 45 { 46 addAtTail(val); 47 } 48 else if(index==0) addAtHead(val); 49 else 50 { 51 //定位到下标为index的结点前一个结点52 LinkNode*p=dummy; 53 while(index--) 54 { 55 p=p->next; 56 } 57 LinkNode* newNode=new LinkNode(val); 58 newNode->next=p->next; 59 p->next=newNode; 60 cnt++; 61 } 62 } 63 64 void deleteAtIndex(int index) { 65 if(index<0||index>=cnt) return ; 66 else{ 67 LinkNode*p=dummy; 68 while(index--) 69 p=p->next;//p指向下标为index的结点前一个结点 70 71 LinkNode*q=p->next; 72 p->next=p->next->next; 73 delete(q); 74 cnt--; 75 } 76 } 77 private: 78 LinkNode*dummy=new LinkNode(0); 79 int cnt;//定义全局变量 80 }; 81 82 /** 83 * Your MyLinkedList object will be instantiated and called as such: 84 * MyLinkedList* obj = new MyLinkedList(); 85 * int param_1 = obj->get(index); 86 * obj->addAtHead(val); 87 * obj->addAtTail(val); 88 * obj->addAtIndex(index,val); 89 * obj->deleteAtIndex(index); 90 */
题目链接/文章讲解/视频讲解:https://programmercarl.com/0707.%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8.html
206.反转链表
思路:
解法一:双指针法
1 class Solution { 2 public: 3 ListNode* reverseList(ListNode* head) { 4 ListNode* temp; // 保存cur的下一个节点 5 ListNode* cur = head; 6 ListNode* pre = NULL; 7 while(cur) { 8 temp = cur->next; // 保存一下 cur的下一个节点,因为接下来要改变cur->next 9 cur->next = pre; // 翻转操作 10 // 更新pre 和 cur指针 11 pre = cur; 12 cur = temp; 13 } 14 return pre; 15 } 16 };
解法二:递归 还是一如既往的难以理解
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode() : val(0), next(nullptr) {} 7 * ListNode(int x) : val(x), next(nullptr) {} 8 * ListNode(int x, ListNode *next) : val(x), next(next) {} 9 * }; 10 */ 11 class Solution { 12 public: 13 ListNode* reverse(ListNode* pre,ListNode*cur) { 14 if(cur==NULL) return pre; 15 ListNode*p=cur->next; 16 cur->next=pre; 17 return reverse(cur,p); 18 }//递归函数,注意返回值 19 20 ListNode* reverseList(ListNode*head) 21 { 22 return reverse(NULL,head); 23 }//调用递归的函数 24 };
题目链接/文章讲解/视频讲解:https://programmercarl.com/0206.%E7%BF%BB%E8%BD%AC%E9%93%BE%E8%A1%A8.html
总结:
链表的定义;链表的基本操作;链表反转的两种方法