链表类面试题型之一——约瑟夫环

链表类面试题型之一——约瑟夫环

 

在笔试面试中,链表类是经常重点考的题型。本系列是本人为了准备笔试与面试,综合各类书与博客,整理所得。

希望在此过程中,希望可以深刻理解各种题型,督促自己的学习进步,并且分享给大家。如有错误,非常希望得到指点,不甚感激。

 

题目描述:

  有一个数组a[N]顺序存放0~N-1,要求每隔两个数删掉一个数,到末尾时循环至开头继续进行,求最后一个被删掉的数的原始下标位置。以8个数(N=7)为例:{0,1,2,3,4,5,6,7},0->1->2(删除)->3->4->5(删除)->6->7->0(删除),如此循环直到最后一个数被删除。

输入描述:

  每组数据为一行一个整数n(小于等于1000),为数组成员数,如果大于1000,则对a[999]进行计算。

输出描述:

  一行输出最后一个被删掉的数的原始下标位置。

 

本题也是来自于华为的一条上机题, 也是一个很经典的问题:约瑟夫环问题,相比大家都不陌生。对于约瑟夫环问题,解法也是有很多,比如数组,链表,队列或是直接推导出数学公式。本文,采用了比较普遍的循环链表。对于循环链表,此问题也是最为典型的应用。

实现的步骤也是比较清晰:建立链表,按照步数循环删除结点,直到仅剩一个结点时,为要找的结果。需注意的是在建立链表或是插入,删除操作时,均应对第一个结点特别注意。

实现代码如下:

struct node{
    int data;
    node* next;
}; 

int del_n(int n, int interval){
    node *head, *curr, *temp;
    //生成头结点 
    head = (node*)malloc(sizeof(node));
    head->data = 0;
    head->next = NULL;
    curr = head;
    
    //读入n个数 
    for(int i=0; i<n; i++){
        temp = (node*)malloc(sizeof(node));
        head->data++;
        temp->data = i;
        if(curr == head){//第一个结点 
            temp->next = temp; 
        }else{
            temp->next = curr->next;
        }
        curr->next = temp;
        curr = temp;
    }
    //删除结点 
    temp = head->next;
    while(head->data > 1){
        for(int i=0; i<interval; i++){
            curr = temp;
            temp = temp->next;
        }
        
        curr->next = temp->next;
        temp = temp->next;
        head->data--;
        count++;
    }
    
    return temp->data;
}

对于使用队列的方式,实现约瑟夫环问题,将在下文实现。

不足之处,敬请谅解,欢迎交流。

对于题目与解法的来源,本人尽量给出出处,尊重原创,方便大家寻找。

posted @ 2017-03-24 22:33  在一起的风景  阅读(264)  评论(0)    收藏  举报