单链表相关面试笔试题

来源:互联网 发布:linux c 绝对路径 编辑:程序博客网 时间:2024/06/03 22:40

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;        }    }}







0 0
原创粉丝点击