链表必须清楚掌握
链表定义
struct ListNode { int val; ListNode *next; };
创建链表头
ListNode* creat()//创建头 { struct ListNode *node=(struct ListNode *)malloc(sizeof(struct ListNode)); node->next=NULL; return node; }
创建一个新节点(插入时调用)
ListNode* make_node(int num)//建新节点 { struct ListNode *node=(struct ListNode *)malloc(sizeof(struct ListNode)); node->val=num; node->next=NULL; return node; }
插入新节点(尾插法)
ListNode* insert(ListNode* head,int num)//尾插法 { struct ListNode *str=(struct ListNode *)malloc(sizeof(struct ListNode)); str=head; while(str->next) { str=str->next; } str->next=make_node(num); return head; }
插入新节点(头插法)
ListNode* insert(ListNode* head,int num)//头插法 { struct ListNode *str=make_node(num); str->next=head->next; head->next=str; return head; }
主函数举例(遍历输出,头节点不存数据)
int main() { struct ListNode *head=creat(); insert(head,1); insert(head,1); insert(head,2); insert(head,3); insert(head,4); insert(head,4); insert(head,5); struct ListNode *str=head->next; while(str) { cout<<str->val<<" "; str=str->next; } cout<<endl; return 0; }
使用举例
leetcode 206. 反转链表
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* reverseList(ListNode* head) { ListNode* last=NULL; ListNode* now=head; while(now!=NULL) { ListNode* next=now->next; now->next=last; last=now; now=next; } return last; } };
/* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } };*/ class Solution { public: ListNode* start=nullptr; ListNode* now=start; void deal(ListNode* head) { if(head==nullptr) return; if(head->next==nullptr) { start=head; now=start; return ; } deal(head->next); now->next=head; now=now->next; now->next=nullptr; return; } ListNode* ReverseList(ListNode* pHead) { deal(pHead); return start; } };
leetcode 82. 删除排序链表中的重复元素 II
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* deleteDuplicates(ListNode* head) { struct ListNode* pass; struct ListNode* slow; struct ListNode* fast; if(head==NULL||head->next==NULL) return head; //处理头节点要删除的情况 递归删除 int lables=0; while(head!=NULL&&head->next!=NULL&&head->val==head->next->val) { struct ListNode* tmp; tmp=head->next; head->next=tmp->next; delete tmp; lables=1; } if(lables==1) { head=head->next; head=deleteDuplicates(head); } if(head==NULL) return head; pass=head; if(pass==NULL||pass->next==NULL||pass->next->next==NULL) return head; slow=pass->next; fast=slow->next; if(slow->val==fast->val&&fast->next==NULL) { delete slow; delete fast; head->next=NULL; return head; } int lable=0; while(1) { if(fast==NULL&&lable==0) return head; if(fast==NULL&&lable==1) { pass->next=NULL; return head; } if(slow->val!=fast->val&&lable==0)//相邻不等 { pass=slow; slow=fast; fast=fast->next; lable=0; continue; } if(slow->val==fast->val)//slow=fast { struct ListNode* tmp; tmp=fast; fast=fast->next; delete tmp; lable=1; continue; } if(slow->val!=fast->val&&lable==1)//不相邻不相等 { pass->next=fast; slow=fast; fast=fast->next; lable=0; continue; } } return head; } };
leetcode 面试题36. 二叉搜索树与双向链表
要求做成双向循环链表
class Solution { public: Node* start; Node* pre; Node* tail; void loop(Node* node) { if(node==NULL) return ; loop(node->left); if(pre==NULL) start=node; else pre->right=node; node->left=pre; pre=node; tail=node; loop(node->right); return ; } Node* treeToDoublyList(Node* root) { if(!root) return NULL; loop(root); start->left=tail; tail->right=start; return start; } };
牛客网二叉搜索树与双向链表 非循环链表 nullptr
/* struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { } };*/ class Solution { public: TreeNode* start=nullptr; TreeNode* pre=nullptr; void loop(TreeNode* node) { if(node==nullptr) return ; loop(node->left); if(pre==nullptr) start=node; else pre->right=node; node->left=pre; pre=node; loop(node->right); return; } TreeNode* Convert(TreeNode* pRootOfTree) { loop(pRootOfTree); return start; } };
/* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } };*/ class Solution { public: ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) { ListNode* fast; ListNode* slow; fast=pListHead; slow=pListHead; while(k--) { if(fast==nullptr) return nullptr; fast=fast->next; } while(fast!=nullptr) { fast=fast->next; slow=slow->next; } return slow; } };
/* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } };*/ class Solution { public: ListNode* Merge(ListNode* pHead1, ListNode* pHead2) { ListNode* start=new ListNode(-1); ListNode* out=start; while(pHead1&&pHead2) { if((pHead1->val)>(pHead2->val)) { out->next=pHead2; pHead2=pHead2->next; } else { out->next=pHead1; pHead1=pHead1->next; } out=out->next; } out->next=(pHead1?pHead1:pHead2); return start->next; } };
leetcode 面试题26. 树的子结构 牛客网:树的子结构
两次递归,注意比较一次失败以后还要继续比较可能正确答案在后面,leetcode的样例这里有漏洞
/* struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { } };*/ class Solution { public: bool loop(TreeNode* tree1, TreeNode* tree2) { bool x1=false,x2=false; TreeNode* l1=tree1; TreeNode* l2=tree2; if(!l1&&l2) return false; if(!l2) return true; if(l1->val==l2->val) { x1=loop(l1->left,l2->left); x2=loop(l1->right,l2->right); return (x1&&x2); } else return false; } bool judge(TreeNode* tree1, TreeNode* tree2) { bool x=false,x1=false,x2=false; if(tree1==nullptr) return false; if(tree1->val==tree2->val) { x=loop(tree1,tree2); } x1=judge(tree1->left,tree2); x2=judge(tree1->right,tree2); if(x||x1||x2) return true; return false; } bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2) { if(pRoot2==nullptr) return false; return judge(pRoot1,pRoot2); } };
leetcode 面试题52. 两个链表的第一个公共节点 牛客网 两个链表的第一个公共结点
第一个公共结点不是第一个键值相等的节点
/* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } };*/ class Solution { public: ListNode* FindFirstCommonNode( ListNode* headA, ListNode* headB) { ListNode *tmp_L1=headA; ListNode *tmp_L2=headB; int count1=1,count2=1; if(!tmp_L1||!tmp_L2) return NULL; while(tmp_L1->next!=nullptr) { tmp_L1=tmp_L1->next; count1++; } while(tmp_L2->next!=nullptr) { tmp_L2=tmp_L2->next; count2++; } if(count1>count2) { int tmp=count1-count2; while(tmp--) { headA=headA->next; } } else if(count1<count2) { int tmp=count2-count1; while(tmp--) { headB=headB->next; } } while(headA!=nullptr) { if(headA==headB) return headA; headA=headA->next; headB=headB->next; } return nullptr; } };
leetcode 143. 重排链表
思路是先遍历一遍找到链表的中心点(中心点往后的都需要插到前面去)。递归链表,链表返回的时候把返回的节点插到前面去,递归到中点就不插了。
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* heads; int N; void deal(ListNode* node,int now) { if(node==nullptr) return ; deal(node->next,now+1); if(N>now||!heads||!heads->next) return; ListNode* tmp=heads->next;//存 heads->next=node; node->next=tmp; heads=tmp; if(tmp->next==node)//最后一个节点要断开 tmp->next=nullptr; return; } void reorderList(ListNode* head) { ListNode* tmp=head; int count=0; while(tmp!=nullptr) { count++; tmp=tmp->next; } if(count%2==0) count/=2; else count=count/2+1; N=count; heads=head; deal(heads,1); return; } };