11:两个单链表相交的一系列问题
/*
* struct ListNode{
int val;
ListNode *next;
ListNode(int x):val(x),next(nullptr){}
};*/
class Solution {
public:
//获取两链表的相交节点
ListNode* getIntersectNode(ListNode *head1,ListNode *head2){
if(head1==NULL||head2==NULL)
return NULL;
ListNode *loop1=getLoopNode(head1);
ListNode *loop2=getLoopNode(head2);
if(loop1==NULL&&loop2==NULL)//返回两个无环链表的相交节点
return noLoop(head1,head2);
if(loop1!=NULL&&loop2!=NULL)//两个有环链表的相交节点
return bothLoop(head1,loop1,head2,loop2);
return NULL;//其他情况链表不可能相交
}
//判断链表有无环,有则返回第一个进入环的节点
ListNode* getLoopNode(ListNode *head){
if(!head||!head->next||!head->next->next)
return NULL;
ListNode *slow=head->next;
ListNode *fast=head->next->next;
while (slow!=fast){
if(fast->next==NULL||fast->next->next==NULL)
return NULL;
slow=slow->next;
fast=fast->next->next;
}
fast=head;//fast重新指向head
while (slow!=fast){
slow=slow->next;
fast=fast->next;
}
return slow;
}
//判定两个无环链表是否相交,相交则返回第一个相交顶点
ListNode* noLoop(ListNode *head1,ListNode *head2){
if(!head1||!head2)return NULL;
ListNode *cur1=head1;
ListNode *cur2=head2;
int n=0;//计数
while (cur1->next!=NULL){
n++;
cur1=cur1->next;
}
while (cur2->next!=NULL){
n--;
cur2=cur2->next;
}
if(cur1!=cur2)
return NULL;//end1!=end2,说明两个链表不相交,直接返回NULL
cur1=n>0?head1:head2;//n>0说明第一条链表长
cur2=cur1==head1?head2:head1;
n=n>0?n:-n;
while (n!=0){
n--;//长链表先走
cur1=cur1->next;
}
while (cur1!=cur2){
cur1=cur1->next;
cur2=cur2->next;
}
return cur1;
}
//判断两个有环链表是否相交,相交则返回一个相交节点
ListNode* bothLoop(ListNode *head1,ListNode *loop1,ListNode *head2,ListNode *loop2){
ListNode *cur1=loop1;
ListNode *cur2=loop2;
if(cur1==cur2){
// 链表类似 -O
cur1=head1;
cur2=head2;
int n=0;
while (cur1!=loop1){//计算到入环节点的距离
n++;
cur1=cur1->next;
}
while (cur2!=loop2){
n--;
cur2=cur2->next;
}
cur1=n>0?head1:head2;
cur2=cur1==head1?head2:head1;
n=n>0?n:-n;
while (n!=0){//长的先走
n--;
cur1=cur1->next;
}
while (cur1!=cur2){
cur1=cur1->next;
cur2=cur2->next;
}
return cur1;
}
else{
cur1=loop1->next;
while (cur1!=loop1){
if(cur1==loop2)
return cur1;
cur1=cur1->next;
}
return NULL;
}
}
};
12:将单链表的每K个节点之间逆序
class Solution{
public:
//利用栈结构解法
ListNode* reverseKNode1(ListNode *head,int k){
if(k<2)return head;
stack<ListNode*>stack;
ListNode *newHead=head,*cur=head;
ListNode *pre=NULL;
ListNode *temp=NULL;
while (cur!=NULL){
temp=cur->next;
stack.push(cur);
if(stack.size()==k){
pre=resign1(stack,pre,temp);//一段的结尾,也是下一段的前驱
newHead=newHead==head?cur:newHead;
}
cur=temp;
}
return newHead;
}
//第一种方法辅助函数,实现元素逆序
ListNode* resign1(stack<ListNode*>&stack,ListNode *left,ListNode *right){
ListNode *cur=stack.top();
stack.pop();
if(left!=NULL)//与左边已经逆过序的相连
left->next=cur;
ListNode *temp=NULL;
while (!stack.empty()){//弹出栈实现逆向连接
temp=stack.top();
stack.pop();
cur->next=temp;
cur=temp;
}
cur->next=right;//与右边下一段相连
return cur;
}
//不利用栈结构,在原链表中直接调整
ListNode* reverseKNode2(ListNode *head,int k){
if(k<2)return head;
ListNode *cur=head;
ListNode *start,*pre,*temp;
int count=1;
while (cur!=NULL){
temp=cur->next;
if(count==k){
start=pre==NULL?head:pre->next;
head=pre==NULL?cur:head;
resign2(pre,start,cur,temp);
pre=start;
count=0;
}
count++;
cur=temp;
}
return head;
}
//变量记录每组的开始和结束节点,以及上组最后一个节点left,下一组开始节点right
void resign2(ListNode *left,ListNode *start,ListNode *end,ListNode *right){
ListNode *pre=start;
ListNode *cur=start->next;
ListNode *temp=NULL;
while (cur!=right){//逆序
temp=cur->next;
cur->next=pre;
pre=cur;
cur=temp;
}
if(left!=NULL)//连接前后两段
left->next=end;
start->next=right;
}
};
13:删除链表中重复出现的节点
class Solution{
public:
//第一种方法,利用hash表,时间复杂度和空间复杂度均为O(n)
ListNode* removeRep1(ListNode *head){
if(head==NULL)
return;
set<int>set;
ListNode *pre=head;
ListNode *cur=head->next;
set.emplace(head->val);//head是肯定保留的
while (cur!=NULL){
//集合中已经存在,直接跳过
if(set.count(cur->val)==1)
pre->next=cur->next;
else{
//添加到集合中
set.emplace(cur->val);
pre=cur;
}
cur=cur->next;
}
return head;
}
//类似选择排序,时间复杂度O(n**2),空间复杂度O(1)
ListNode* removeRep2(ListNode *head){
ListNode *cur=head;
ListNode *pre=NULL;
ListNode *temp=NULL;
while (cur!=NULL){//外层循坏
pre=cur;
temp=cur->next;
while (temp!=NULL){//内层循环
if(cur->val==temp->val)
pre->next=temp->next;
else
pre=temp;
temp=temp->next;//遍历
}
cur=cur->next;
}
return head;
}
};
14:在单链表中删除指定值的节点
class Solution{
public:
//在链表中删除指定值的节点,利用栈
//时间与空间复杂度都是O(n)
ListNode* removeValue1(ListNode *head,int num){
stack<ListNode*>stack;
while (head!=NULL){
if(head->val!=num)//值不等则压入栈
stack.push(head);
head=head->next;
}
//上述while结束后Head为NULL
while (!stack.empty()){
ListNode *node=stack.top();
stack.pop();
node->next=head;
head=node;
}
return head;
}
//第二种方法直接删除
ListNode* removeValue2(ListNode *head,int num){
if(head==NULL)return NULL;
while (head!=NULL){
if(head->val!=num)
break;
head=head->next;//得到newHead
}
ListNode *pre=head;
ListNode *cur=head->next;
while (cur!=NULL){
if(cur->val==num)
pre->next=cur->next;
else
pre=cur;
cur=cur->next;
}
return head;
}
};
15:将搜索二叉树转化成双向链表