单链表相关面试笔试题
2014-08-09 19:16
447 查看
1.链表节点结构定义
struct node { node * next ; int val ; node(int x):val(x),next(NULL){} };
/** 从数组中构造单项链表 **/ node * construct_list(int a[] ,int n){ node * head=NULL; node * p=NULL; node * q=NULL; for(int i=0;i<n;++i){ p= new node(a[i]); if(q!=NULL) q->next=p; if(i==0){ head=p; }; q=p; p=p->next; } return head; } /** 顺序输出单链表 **/ void output(struct node * head){ if(head == NULL){ cout<<"empty list !\n"; return ; } node * p = head; while(p!= NULL){ cout<<p->val<<" "; p=p->next; } cout<<"\n"; }
2.链表的逆序输出以及链表的逆序操作
/** 逆序输出单链表,递归 **/ void reverse_output(struct node * head){ if(head == NULL){ return ; }else { node * p = head; reverse_output(p->next); cout<<p->val<<" "; } } /** 逆转单链表 思路:将node 一个个从链表中卸下来,然后逆序重组 **/ node * reverse_list(node * head){ if (head ==NULL ||head->next==NULL)return head; node * p=NULL, *q=NULL,*t=NULL; p=head; q=head->next; p->next=NULL; while(q){ t=q; q=q->next; t->next=p; p=t; } return p; }
//感觉这样可以少一个变量,但是不是很容易理解,主要是我们需要改变指针的值 void reverse_list1(node * *head){ if (*head ==NULL ||(*head)->next==NULL)return ; node *q=NULL,*t=NULL; q=(*head)->next; (*head)->next=NULL; while(q){ t=q; q=q->next; t->next=(*head); (*head)=t; } }
3.判断链表中是否有环,有的话找出环的入口
/* 判断链表是否有环,如果有的话,找出环的入口 找环的入口2(x+y)=nr +(x+y) --> x=nr-y :其中x为开始到入口的步长,y为入口到首次相遇的步长 r为环的长度 */ bool has_cicle(node * head){ bool has_cicle = false; if(head == NULL || head->next == NULL )return has_cicle; node * slow = head ,*fast = head ;//同一个起跑线 while(true){ slow = slow->next; fast = fast->next; if(fast) fast = fast->next; if(slow==NULL||fast==NULL)break; if(slow==fast){ has_cicle=true; break; } } if(has_cicle==true){//找到环的入口 node * start = head ; node * encounter = slow; while(start!=slow){ start=start->next; slow=slow->next; } cout<<"entry point :"<<start->val<<" \n" ; } return has_cicle; }
4.链表中的倒数第K个数
/** 找到单链表中的倒数第K个元素问题,只给出单链表的头指针 也是利用快慢两个指针,first指针首先走k步之后 如果再次之前first已经走完了那么就说明没有找到这样的值 否则,first 和second指针开始一起走,等到first指针走到最后, second 指针恰好走到了倒数第k个元素 **/ node * find_post_k_element(node * head,int k){ node * first = head ; node * second =NULL; while(first!=NULL&&k>0){ k--; first=first->next; } if(k>0) return NULL; else{ second= head; while (first){//当first在第k+1个元素的时候 second元素在第1个元素,相隔正好是k个元素 first=first->next; second=second->next; } } return second; }
5.求链表中间的元素
/** 找出链表的中间元素 好吧,还是两个指针吧,步长两倍关系即可 **/ node * find_mid_element(node * head){ if(head==NULL||head->next == NULL){ return head; } node * single = head; node * double_step = head; while(double_step){ double_step=double_step->next; if(double_step) double_step=double_step->next; if(double_step) single=single->next;//注意指针走动的顺序 } return single; }
6.有序链表的合并问题,包括递归和非递归的实现
/** 两个升序链表的合并问题,非递归 **/ node * merge_lists(node * head1 ,node * head2){ if(head1 == NULL)return head2; if(head2 == NULL)return head1; node * head = NULL; node * temp = NULL; while(true){ while(head1&&head2&&head1->val<=head2->val){//head1 head 2都得判断是否为空 if(temp == NULL){ temp = head1; head = temp; } else{ temp->next = head1; temp = temp->next;//指针要走动的 } head1 = head1->next; } while(head2&&head1&&head2->val<=head1->val){ if(temp == NULL) { temp = head2 ; head= temp; }else{ temp ->next = head2; temp=temp->next; } head2 = head2->next; } if(head1 == NULL){ while(head2){ temp ->next = head2; temp=temp->next; head2 = head2->next; } break; } if(head2 == NULL){ while(head1){ temp ->next = head1; head1 = head2->next; temp=temp->next; } break; } if(head1==NULL&&head2==NULL)break; } return head; } //递归版本 node * merge_lists1(node * head1 , node * head2){ node * head = NULL; if(head1 == NULL)return head2; if(head2 == NULL)return head1; if(head1->val<=head2->val){ head = head1; head ->next = merge_lists1(head1->next,head2); }else{ head = head2 ; head ->next = merge_lists1(head1,head2->next); } return head; }
7.删除单链表中的重复数据,链表无序
常见的这个题目分为两个要求,一是在空间复杂度O(1),另一个则是木有限制,一般而言空间有限制的情况下只能通过暴力的遍历解决了,但是如果没什么限制的话使用hash表来帮助操作是比较省时的,时间复杂度为O(n),貌似C++11中才有的hash表可以用,代码如下:/** 未排序的链表中的重复值的删除 1.不限制空间复杂度 2.空间复杂度在O(1)的实现 **/ //复杂度 O(n*n) void remove_duplicate1(node * head){ if(head==NULL||head->next==NULL)return; node * first =head,*second =NULL,* t = NULL; while(first){ second=first->next; t=first; while(second){ if(second->val==first->val){ t->next=second->next; delete second; second=t->next; }else{ t=second; second=second->next; } } first=first->next; } } void remove_duplicate2(node * head){ if(head==NULL||head->next==NULL)return; hash<int>h; h(head->val)=true; node * p = head->next,*q=head; while(p){ if(h(p->val)==true){ q->next=p->next; delete p; p=q->next; }else{ h(p->val)=true; q=p; p=p->next; } } }
相关文章推荐
- 笔试面试,单链表相关(3)遍历一次找中间结点、倒数第K个结点
- 笔试面试单链表相关(2)在任意位置前插入结点、逆置链表
- <笔试><面试>单链表相关(1)从尾到头打印链表、删除一个无头链表的非尾结点
- 【笔试面试】链表相关操作
- <笔试><面试>单链表相关(1)从尾到头打印链表、删除一个无头链表的非尾结点
- 面试笔试系列之二 链表相关
- 笔试面试单链表相关(2)在任意位置前插入结点、逆置链表
- 笔试面试,单链表相关(3)遍历一次找中间结点、倒数第K个结点
- <笔试><面试>C/C++单链表相关(4)判断两链表是否相交,求交点(链表不带环/可能带环)
- <笔试><面试>C/C++单链表相关(4)判断两链表是否相交,求交点(链表不带环/可能带环)
- 二叉树相关笔试面试问题集锦
- 面试笔试问题总结(七)—Linux指令及操作系统相关
- C语言链表在笔试面试中常考问题总结
- 链表相关面试题目 反转 合并
- C语言链表在笔试面试中常考问题总结
- 【笔试面试——31】链表11——检测两个链表是否相交
- 链表相关面试算法题 java实现
- [互联网面试笔试汇总C/C++-17] 链表交点,链表环问题汇总
- 找工作知识储备(1)---从头说catalan数及笔试面试里那些相关的问题
- 软件相关职位经典面试笔试题目分析