/**
* 现有N个人绕着一个足够大的园桌按顺时针坐成一圈, 每个人都有一个编号,编号从0开始,
* 从0号的人开始按顺时针报数,报的数从1开始, 凡是报的数字是7的倍数,或数字中有7, 这个人就从桌子上离开,
* 按顺时针方向后面的人继续进行报数.依此进行下去,最终桌上会剩下的最后一个人,问最后剩下的这个人的编号是几?
* 请编写一个C程序解决.如果用C++语言, 你又如何解决?
*
**/
#include "timer.h"
#include <stdio.h>
#include <string>
#include <cstddef>
#include <assert.h>
#include <iostream>
#include <exception>
#include <stdexcept>
class Element
{
public:
unsigned long _data;
Element* _pre;
Element* _next;
Element() : _pre ( NULL ), _next ( NULL ), _data ( 0 ) {}
};
Element* CreatCircularList ( unsigned long N );
bool DeleteElementList ( Element *p );
/** N 个数,数到的数是base的整数倍,或是此数里含有base,就移除*/
// 为了降低难度,此处假设base 是7, pHead 是包含 N个元素的循环链表
void Detect7 ( Element* pHead, unsigned long base );
//判断num中是否存在 7, true, exist
bool CheckSeven ( unsigned long num );
Element* gRelease = NULL;
int main ( int argc, char **argv )
{
unsigned long N;
printf ( "How long do you want? please enter a positive number: " );
scanf ( "%d", &N );
gRelease = new Element;
assert ( gRelease );
Element* pHead = CreatCircularList ( N );
assert ( pHead );
// init the list
for ( int i = 0; i != N ; ++i ) {
pHead->_data = i;
pHead = pHead->_next;
}
TimeStart();
Detect7 ( pHead, 7 );
TimeStop();
printf ( "process time is : %f us \n", GetElapsedTime() );
DeleteElementList ( gRelease );
#ifdef _WIN32
system ( "pause" );
#endif
}
Element* CreatCircularList ( unsigned long N )
{
assert ( N > 0 );
TimeStart();
Element *head = new Element;
assert ( head != NULL );
Element *cur = NULL;
cur = head;
try {
for ( unsigned long i = 0; i != N - 1; ++i ) {
//
Element * temp = new Element;
assert ( temp != NULL );
temp->_pre = cur; // temp point to previous
cur->_next = temp; // previous point to temp
cur = cur->_next;
}
cur->_next = head; // circular linked list
head->_pre = cur;
} catch ( const std::bad_alloc& err ) {
printf ( "%s \n", err.what() );
return NULL;
}
TimeStop();
printf ( "Allocate memory time is : %f us \n", GetElapsedTime() );
return head;
}
// release Element List
bool DeleteElementList ( Element *p )
{
assert ( p != NULL );
Element * rel = p;
// int num = 0;
while ( rel->_next ) {
Element * temp = rel;
rel = rel->_next;
delete temp;
//++num;
}
delete rel;
// printf ( "内存释放 %d 次\n", num );
return true;
}
void Detect7 ( Element* pHead, unsigned long base )
{
assert ( pHead > 0 );
assert ( base > 0 );
Element* pRelease = gRelease;
Element* pCurrent = pHead;
for ( unsigned long i = 1;; ++i ) {
if ( i == -1 ) {
printf ( "over flow \n" );
return;
}
if ( pCurrent->_data == pCurrent->_next->_data ) {//判断是否是最后一个元素
printf ( "The last member is %d \n", pCurrent->_data );
//for release
pRelease->_next = pCurrent;
pRelease = pRelease->_next;
pRelease->_next = NULL;
return;
}
if ( i % 7 == 0 ) { //判断是否是7 的倍数
pCurrent->_pre->_next = pCurrent->_next;
pCurrent->_next->_pre = pCurrent->_pre;
//for release
pRelease->_next = pCurrent;
pRelease = pRelease->_next;
pCurrent = pCurrent->_next;
continue;
}
if ( CheckSeven ( i ) ) { //判断是否包含7
pCurrent->_pre->_next = pCurrent->_next;
pCurrent->_next->_pre = pCurrent->_pre;
//for release
pRelease->_next = pCurrent;
pRelease = pRelease->_next;
pCurrent = pCurrent->_next;
continue;
}
pCurrent = pCurrent->_next;
}
return;
}
//判断num中是否存在 7, true, exist
bool CheckSeven ( unsigned long num )
{
if ( num <= 0 ) return false;
unsigned long ret = num;
unsigned long remainder = 0;
remainder = ret % 10; //求个位上的数字是几
if ( remainder == 7 )
return true;
else
CheckSeven ( num / 10 );
}
#include "timer.h"
i64 time_start ;
i64 time_stop ;
i64 time_freq ;
void TimeStart()
{
#if _WIN32
QueryPerformanceFrequency ( ( LARGE_INTEGER * ) &time_freq );
QueryPerformanceCounter ( ( LARGE_INTEGER * ) &time_start );
#elif __linux__
time_freq = 1000;
struct timeval s;
gettimeofday ( &s, 0 );
time_start = ( i64 ) s.tv_sec * 1000 + ( i64 ) s.tv_usec / 1000;
#endif
}
void TimeStop()
{
#if _WIN32
QueryPerformanceCounter ( ( LARGE_INTEGER * ) &time_stop );
#elif __linux__
struct timeval s;
gettimeofday ( &s, 0 );
time_stop = ( i64 ) s.tv_sec * 1000 + ( i64 ) s.tv_usec / 1000;
#endif
time_stop -= time_start;
}
double GetElapsedTime()
{
// unit: us
return ( double ) time_stop * 1000000 / ( double ) time_freq;
}