题目链接 点击打开链接
小孩报数问题
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 12011 | Accepted: 5513 |
Description
有N个小孩围成一圈,给他们从1开始依次编号,现指定从第W个开始报数,报到第S个时,该小孩出列,然后从下一个小孩开始报数,仍是报到S个出列,如此重复下去,直到所有的小孩都出列(总人数不足S个时将循环报数),求小孩出列的顺序。
Input
第一行输入小孩的人数N(N<=64)
接下来每行输入一个小孩的名字(人名不超过15个字符)
最后一行输入W,S (W < N),用逗号","间隔
接下来每行输入一个小孩的名字(人名不超过15个字符)
最后一行输入W,S (W < N),用逗号","间隔
Output
按人名输出小孩按顺序出列的顺序,每行输出一个人名
Sample Input
5 Xiaoming Xiaohua Xiaowang Zhangsan Lisi 2,3
Sample Output
Zhangsan Xiaohua Xiaoming Xiaowang Lisi
分析:循环报数,数据结构中得用到循环链表,由于有删除操作,需要快速找到节点的前驱节点,所以选择双循环链表,由于有固定的移动操作,所以不采用头结点,代码如下:
import java.io.*;
import java.util.*;
import java.util.*;
import java.util.*;
public class Main {
public static void main(String []arsgs){
Scanner cin = new Scanner(new BufferedInputStream(System.in)) ;
PrintWriter cout = new PrintWriter(System.out) ;
List<String> answer = new Solve(cin.nextInt() , cin).ssolve() ;
for(String name : answer){
cout.println(name);
}
cout.flush() ;
cout.close() ;
}
}
class NNode{
String name ;
NNode next , pre;
NNode(){
next = pre = null ;
}
}
class Solve{
NNode head ;
int w , s ;
public Solve(int n , Scanner cin ){
make(n) ;
NNode now = head ;
for(int i =1 ; i<= n ; i++){ //不带头结点,方便计算,不需要处理空链表
now.name = cin.next() ;
now = now.next ;
}
String[] p = cin.next().split(",");
w = Integer.parseInt(p[0]) ;
s = Integer.parseInt(p[1]) ;
}
//建立双循环链表 ,
public void make(int n){
head = new NNode() ;
NNode now = head ;
for(int i =1 ; i< n ;i++){
now.next = new NNode() ;
now.next.pre = now ;
now = now.next ;
}
now.next = head ;
head.pre = now ;
}
//移动s步 , 返回移动s步后的节点
NNode move(NNode now , int step){
for(int i=1 ;i <= step ; i++)
now = now.next ;
return now ;
}
//删除节点
//由于删除节点p,须找到其前驱节点,如果用单循环链表,则需耗时O(n),原因在于每个节点只有一个指向后继的指针域,
//所以用空间换取时间,增加一个存储其前驱的指针域,用双向循环链表数据结构
NNode delete(NNode now){ //返回删除节点的下一位节点
now.pre.next = now.next ;
now.next.pre = now.pre ;
return now.next ;
}
List<String> ssolve(){
List<String> answer = new ArrayList<String>() ;
NNode now = move(head , w -1) ;
while(now.next != now){
now = move(now , s-1) ;
answer.add(now.name) ;
now = delete(now) ;
}
answer.add(now.name) ; //添加最后一个节点
return answer ;
}
}