华为招聘机试整理16:约瑟夫环应用
题目:约瑟夫环应用
输入一个由随机数组成的数列(数列中每个数均是大于0的整数,长度已知),和初始计数值m。从数列首位置开始计数,计数到m后,将数列该位置数值替换计数值m,并将数列该位置数值出列,然后从下一位置从新开始计数,直到数列所有数值出列为止。如果计数到达数列尾段,则返回数列首位置继续计数。请编程实现上述计数过程,同时输出数值出列的顺序
比如: 输入的随机数列为:3,1,2,4,初始计数值m=7,从数列首位置开始计数(数值3所在位置)
第一轮计数出列数字为2,计数值更新m=2,出列后数列为3,1,4,从数值4所在位置从新开始计数
第二轮计数出列数字为3,计数值更新m=3,出列后数列为1,4,从数值1所在位置开始计数
第三轮计数出列数字为1,计数值更新m=1,出列后数列为4,从数值4所在位置开始计数
最后一轮计数出列数字为4,计数过程完成。
输出数值出列顺序为:2,3,1,4。
要求实现函数:
void array_iterate(int len, int input_array[], int m, int output_array[])
【输入】 int len:输入数列的长度;
int intput_array[]:输入的初始数列
int m:初始计数值
【输出】 int output_array[]:输出的数值出列顺序
【返回】 无
题目分析:
①这道题其实就是约瑟夫环的一个变形,以前问题是要求出最后剩下的数字,现在是要求出列顺序,其实也就是要求删除的数字的顺序,以前问题中最后剩下的数字当然也就是最后删除的了。
②这道题还有一个不一样的地方是,以前是0-n的数列,现在是具体输入的整型数组,所以不能用以前那个数学递归公式解决了。
③这道题还有不一样的地方在于它计数值一直再发生变化,这个是与原来约瑟夫环最大的区别,所以我们要设置一个新的变量cnt1更新m。
=======================================================================
参考代码:
//约瑟夫环应用.cpp
//2014.7.11 hepanhui
#include <iostream>
#include <list>
using namespace std;
void array_iterate(int len, int input_array[], int m, int output_array[])
{
if(len < 1 || m < 1)
return;
unsigned int i = 0;
int cnt = 0;
int cnt1 = m;
list<int> numbers;
for(i = 0; i < len; i++)
numbers.push_back(input_array[i]);
list<int>::iterator current = numbers.begin();
while(numbers.size() > 0)
{
for(int i = 1;i < cnt1; ++i)
{
current++;
if(current == numbers.end())
current = numbers.begin();
}
list<int>::iterator next = ++current;
if(next == numbers.end())
next = numbers.begin();
-- current;
cnt1 = *current;
output_array[cnt++] = *current;
numbers.erase(current);
current = next;
}
output_array[cnt++] = '\0';
}
int main()
{
int len = 4;
int input_array[] = {3, 1, 2, 4};
int output_array[5];
int m = 7;
array_iterate(len,input_array, m, output_array);
for(int i = 0; i < len-1; i++)
cout << output_array[i] << " ";
cout << output_array[len-1] << endl;
return 0;
}
调试中易犯的错误:
①注意看清题目,题目是一直更新计数值
②注意接收的整型数组不能设为int output_array[4]因为我们最后有cnt++,所以会报错,综上所述,我觉得初始化数组时,还是最好设置为maxn,这样避免出错。