/*******************************************************************
Copyright(c) 2016, Tyrone Li
All rights reserved.
*******************************************************************/
// 作者:TyroneLi
//
/*
Q1:
圆圈中最后剩下的数字:
0,1,2,...,n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈2中删
除第m个数字,求出这个圆圈里剩下的最后一个数字。(约瑟夫环问题)
S1:
1. 用环形链表模拟圆圈解决,思路直接,但是需要耗费一定的时间效率和空间效率。
时间复杂度O(nm),空间复杂度O(n);
2. 分析每次删除的数字以及剩下的序列的规律,直接找到最后所剩下的数字。
时间复杂度O(n), 空间复杂度O(1);更好
*/
#include <iostream>
#include <algorithm>
#include <list>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>
int lastRemaining(unsigned int n, unsigned int m)
{
if(n < 1 || m < 1)
return -1;
unsigned int i = 0;
std::list<int> data;
for(i = 0; i < n; ++i)
data.push_back(i);
std::list<int>::iterator curIter = data.begin();
// 当链表的指针指向最后一个元素的下一个元素时候,讲迭代器
// 重新指向第一个元素,从而保证可以模拟环状的链表。
while(data.size() > 1)
{
for(int i = 1; i < m; ++i)
{
curIter++;
if(curIter == data.end())
curIter = data.begin();
}
std::list<int>::iterator nextIter = (++curIter);
if(nextIter == data.end())
nextIter = data.begin();
--curIter;
data.erase(curIter);
curIter = nextIter;
}
return (*curIter);
}
int lastRemaining_quick(unsigned int n, unsigned int m)
{
if(n < 1 || m < 1)
return -1;
int last = 0;
for(int i = 2; i <= n; ++i)
last = (last + m) % i;
return last;
}
void test_1()
{
std::cout << "Test 1" << std::endl;
std::cout << "Expect : " << 3 << " Get : " << lastRemaining(5, 3) << std::endl;
std::cout << "Expect : " << 3 << " Get : " << lastRemaining_quick(5, 3) << std::endl;
std::cout << std::endl;
}
void test_2()
{
std::cout << "Test 2" << std::endl;
std::cout << "Expect : " << 0 << " Get : " << lastRemaining(1, 3) << std::endl;
std::cout << "Expect : " << 0 << " Get : " << lastRemaining_quick(1, 3) << std::endl;
std::cout << std::endl;
}
void test_3()
{
std::cout << "Test 3" << std::endl;
std::cout << "Expect : " << 2 << " Get : " << lastRemaining(5, 2) << std::endl;
std::cout << "Expect : " << 2 << " Get : " << lastRemaining_quick(5, 2) << std::endl;
std::cout << std::endl;
}
void test_4()
{
std::cout << "Test 4" << std::endl;
std::cout << "Expect : " << 3 << " Get : " << lastRemaining(6, 3) << std::endl;
std::cout << "Expect : " << 3 << " Get : " << lastRemaining_quick(6, 3) << std::endl;
std::cout << std::endl;
}
void test_5()
{
std::cout << "Test 5" << std::endl;
std::cout << "Expect : " << 4 << " Get : " << lastRemaining(6, 4) << std::endl;
std::cout << "Expect : " << 4 << " Get : " << lastRemaining_quick(6, 4) << std::endl;
std::cout << std::endl;
}
void test_6()
{
std::cout << "Test 6" << std::endl;
std::cout << "Expect : " << -1 << " Get : " << lastRemaining(0, 0) << std::endl;
std::cout << "Expect : " << -1 << " Get : " << lastRemaining_quick(0,0) << std::endl;
std::cout << std::endl;
}
void test_7()
{
std::cout << "Test 7" << std::endl;
std::cout << "Expect : " << 1027 << " Get : " << lastRemaining(4000, 997) << std::endl;
std::cout << "Expect : " << 1027 << " Get : " << lastRemaining_quick(4000, 997) << std::endl;
std::cout << std::endl;
}
void test_lastRemaining()
{
test_1();
test_2();
test_3();
test_4();
test_5();
test_6();
test_7();
}
int main(int argc, char**argv)
{
test_lastRemaining();
return 0;
}