Java用循环链表解决约瑟夫环问题(循环报数)

题目描述:输入1个数字和多个字符,中间均以空格隔开。假设数字范围为m(1-9),后面字符个数为n。假设n个字符围成一圈,从第一个字母开始循环报数,当数到m以后,第m个字符就出列,知道这n个字符全都出列。最后按照出列的顺序输出这些字符,中间仍以空格隔开。取值范围:m为1-9,n为1-20。

样例输入:3 a b c d e f g h i

样例输出:c f i d h e b g a


用循环列表来解决上述问题,就是对于一个链表,尾节点的下一节点指向头节点。

代码如下:

import java.util.*;
public class CycleNum {
	//静态内部节点类,
	private static class Node{
		public String data;
		public Node next;
		public Node(String s1){
			this.data=s1;
		}
	}
	public static void main(String[] args){
		Scanner sc=new Scanner(System.in);
		int m=sc.nextInt();
		ArrayList<String> al=new ArrayList<String>();
		while(sc.hasNext()){
			al.add(sc.next());
		}
		sc.close();
		int n=al.size();
		//初始化链表
		Node header=new Node(al.get(0));
		Node pointer=header;
		for(int i=1;i<n;i++){
			pointer.next=new Node(al.get(i));
			pointer=pointer.next;
		}
		//尾节点的下一节点为头节点
		pointer.next=header;
		//输出链表
		while(pointer.next!=pointer){//如果循环列表中,退出循环
			for(int i=1;i<m;i++){
				pointer=pointer.next;
			}
			System.out.print(pointer.next.data+" ");
			pointer.next=pointer.next.next;//该语句将输出的节点从循环列表中解除链接
		}
		System.out.print(pointer.data);
	}
}

注意:在以上代码中控制台输入“ctrl+z”来结束输入。

下面以四个元素 a b c d 为例画图来展示一次循环的过程(请无视字丑):

《Java用循环链表解决约瑟夫环问题(循环报数)》


另外,上述代码中使用静态内部类是为了创建Node节点时无需将内部类的实例绑定在外部类的实例上。

同样我们也可以使用非静态的内部类来描述Node类:

import java.util.*;
public class CycleNum {
	public class Node{
		public String data;
		public Node next;
		public Node(String s){
			this.data=s;
		}
	}
	public static void main(String[] args){
		Scanner sc=new Scanner(System.in);
		int m=sc.nextInt();
		List<String> al=new ArrayList<String>();
		while(sc.hasNext()){
			al.add(sc.next());
		}
		sc.close();
		//初始化链表
		CycleNum cn=new CycleNum();
		Node header=cn.new Node(al.get(0));
		Node pointer=header;
		for(int i=1;i<al.size();i++){
			pointer.next=cn.new Node(al.get(i));
			pointer=pointer.next;
		}
		pointer.next=header;
		//输出链表
		while(pointer.next!=pointer){
			for(int i=1;i<m;i++){
				pointer=pointer.next;
			}
			System.out.print(pointer.next.data+" ");
			pointer.next=pointer.next.next;
		}
		System.out.print(pointer.data);	
	}
}

附静态内部类和非静态内部类的区别:

(1):静态内部类可以创建静态的成员而非静态的内部类不可以

(2):静态内部类只可以访问外部类中的静态成员变量与成员方法而非静态的内部类即可以访问外部类所有的成员方法与成员变量

(3):在创建静态内部类时不需要将静态内部类的实例绑定在外部类的实例上

(4):使用静态内部类,多个外部类的对象可以共享同一个内部类的对象。使用普通内部类,每个外部类的对象都有自己的内部类对象,外部对象之间不能共享内部类的对象

    原文作者:约瑟夫环问题
    原文地址: https://blog.csdn.net/sinat_26888717/article/details/48222787
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞