您的位置:首页 > 职场人生

单链表相关面试笔试题

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;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: