约瑟夫问题

C卷,100分)- 约瑟夫问题(Java & JS & Python & C)

题目描述

输入一个由随机数组成的数列(数列中每个数均是大于 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[]:输出的数值出列顺序

用例

输入 3,1,2,4 4 7
输入 4
输入 7
输出 2,3,1,4
说明 输入第一行是初始数列intput_array第二行是初始数列的长度len第三行是初始计数值m输出数值出列顺序

题目解析

本题就是约瑟夫环的变种题。

约瑟夫环的解题有多种方式,比较容易理解和实现的可以使用双端队列。

即intput_array当成双端队列,从队头取出元素,判断此时计数是否为m:

  • 若是,则将取出的元素加入output_arr,并将取出的元素的值赋值给m,然后len–,计数重置为1
  • 若不是,则将取出的元素塞回intput_array的队尾,仅计数++

但是本题JS是基于数组实现的双端队列,因此每次头部元素出队,都意味着一次O(n)复杂度的数组元素前移一位操作,这是非常影响性能的。

对于Java,Python都有内置的双端队列结构,因此可以直接复用,对于C,可以自己实现双端队列结构。

因此JS语言我们可以选择循环链表来模拟约瑟夫环。

循环链表本身就实现了环形结构,其head.prev = tail,tail.next = head。

且循环链表删除节点的复杂度是O(1)。

唯一的遗憾是,JS没有原生的循环链表结构,我们需要自己实现。但是我们只需要实现最简单的循环链表即可,即只实现循环链表的尾部新增节点操作即可。而删除操作可以在实际业务中完成。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
class Solution{


public static void main(String[] args) {

Scanner sc = new Scanner(System.in);
Integer[] input_array =
Arrays.stream(sc.nextLine().split(",")).map(Integer::parseInt).toArray(Integer[]::new);
int len = Integer.parseInt(sc.nextLine());
int m =Integer.parseInt(sc.nextLine());

System.out.println(getResult(input_array,len,m));
System.out.println(getResult1(input_array,len,m));
}


public static String getResult1(Integer[] input_arr, int len, int m) {
LinkedList<Integer> dq = new LinkedList<>(Arrays.asList(input_arr));

ArrayList<Integer> output_arr = new ArrayList<>();

int i = 1;
while (len > 0) {
Integer out = dq.removeFirst();

if (i == m) {
output_arr.add(out);
m = out;
i = 1;
len--;
} else {
dq.add(out);
i++;
}
}

StringJoiner sj = new StringJoiner(",");
for (Integer ele : output_arr) {
sj.add(ele + "");
}
return sj.toString();
}


public static String getResult(Integer[] input_array,int length,int m){
LinkedList<Integer> dq = new LinkedList<>(Arrays.asList(input_array));
ArrayList<Integer> output_array = new ArrayList<>();
int i = 0;
int len = length;
while(len > 0){
Integer out = dq.removeFirst();
if(m == i){
output_array.add(out);
m =out;
i = 1;
len--;
}else{
dq.add(out);
i++;
}

}
StringJoiner sj = new StringJoiner(",");
for(Integer s : output_array){
sj.add(s+"");
}


return sj.toString();
}


}



__END__