今天做了一道vivo的开发笔试题,题目是约瑟夫环问题
题目背景:
约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
题目要求编写程序,给定n、m计算出列人员的先后顺序
思路:
代码片段:
import java.util.List;
import java.util.ArrayList;
import java.lang.Integer;
import java.util.Scanner;
class Joseph
{
public void joseph(int m,int n){
int step=m,index=0,length=n;
ArrayList<Integer> circle = new ArrayList<>();
circle.ensureCapacity(n);
for(int i=0;i<n;i++){
circle.add(0);
}
while(length>0){
while(step>0){
if(circle.get(index)==0)
step--;
if(step>0){
index++;
if(index>=n)
index=0;
}
}
circle.set(index,1);
length--;
step=m;
System.out.println("被踢出的人"+index);
}
}
public static void main(String[] args)
{
int m,n;
Scanner s = new Scanner(System.in);
System.out.println("请输入有多少个人:");
n=s.nextInt();
System.out.println("请输入要数多少下:");
m=s.nextInt();
Joseph j=new Joseph();
long startTime = System.currentTimeMillis(); //获取开始时间
j.joseph(m,n);
long endTime = System.currentTimeMillis(); //获取结束时间
System.out.println("程序运行时间:" + (endTime - startTime) + "ms");
}
}
一开始我是用的ArrayList的结构来做的,然后我就改成用LinkedList来做一下,做法几乎一模一样,只是不用去判断每个单元的值是否为0或1,因为链表直接把他们删除了
代码片段:
import java.util.List;
import java.util.LinkedList;
import java.lang.Integer;
import java.util.Scanner;
class JosephLinked
{
public void joseph(int m,int n){
int step=m,index=0;
List<Integer> circle=new LinkedList<>();
for(int i=0;i<n;i++)
circle.add(i);
while(circle.size()>0){
while(step>0){
step--;
if(step>0){
index++;
if(index>=circle.size())
index=0;
}
}
circle.remove(index);
step=m;
System.out.println("被踢出的人"+index);
}
}
public static void main(String[] args)
{
int m,n;
Scanner s = new Scanner(System.in);
System.out.println("请输入有多少个人:");
n=s.nextInt();
System.out.println("请输入要数多少下:");
m=s.nextInt();
Joseph j=new Joseph();
long startTime = System.currentTimeMillis(); //获取开始时间
j.joseph(m,n);
long endTime = System.currentTimeMillis(); //获取结束时间
System.out.println("程序运行时间:" + (endTime - startTime) + "ms");
}
}
小结:
1、这个算法题的难点主要是当你遍历一遍数组之后要怎么回到最初的位置最恰当,这里搞不好就会卡死;
2、ArrayList和LinkedList的操作方式对于使用者来说是几乎一模一样的,你直接把List<Integer> circle=new LinkedList<>();
换成List<Integer> circle=new ArrayList<>();
代码也能直接跑起来,因为他们都继承同一个接口List,但他们的底层实现则是大不相同,一个数组一个链表,自然两个集合的区别也是和数组和链表的区别大致一样;