写在开头:
这段文字编辑于2020年6月18日,20:39分,加班…
这篇博客是我2017年初,初学Java的时候写的,题目是“数三退一问题”,题目的来源是马士兵老师2005、2006年在尚学堂的时候录的那版最经典的Java视频,好像是在第三章讲的。但是那会儿我还不知道,这个就是一个初版的约瑟夫环问题。
今年春天跳槽找工作,面试百度,一面是远程面试,在一个叫做“ShowMeBug”的面试平台上写代码,然后面试官让写一个约瑟夫环问题,后来才知道,就是数N退一问题。
所以说,不要小看任何一段代码,无论多短多简单,你永远也不知道可能未来的某一天就会用得到。
现在已经毕业一年了,真心感觉到生活不易,不知道自己在Java这一行能如何,也不知道自己35,40岁之后还能不能在这一行保持核心竞争力,还能不能有实力和精力继续在程序员这一行业里坚持下去。
写在这篇文章前面我也不知道要说些什么,可能只是来自一个工作一年的程序员的感慨吧。
原文
问题描述:
假设有500个孩子,手拉手围成一个圈,从第一个孩子开始报数,第一个孩子报1,第二个孩子报2,第三个孩子报3,那个第三个孩子退出这个圈,然后第四个孩子继续报1,第五个孩子报2…每个数到3的孩子都退出这个圈,直到圈内只剩1个孩子,问这个孩子是第几个孩子?
这个问题有两种解法,第一种方法是采用数组的方式:首先建立一个布尔类型的数组,数组内的值为true的位置表示该位置的孩子在圈内,数组内的值为false的位置表示该位置的孩子由于数到了3退出了这个圈,然后采用while循环,并设置一个计数器,当计数器数到3时该位置的值变为false,直到圈内只有一个孩子,再遍历一次数组并输出这个位置。
解释起来语言可能比较难以理解,我们直接看代码:
public class CountThreeQuit {
public static void main(String[] args) {
boolean[] a = new boolean[500];
for(int i=0; i<a.length; i++) {
a[i] = true;
}//将数组初始化为true
int leftCount = a.length;
int index = 0; //下标计数器
int count = 0; //计数器
while(leftCount > 1) {
if(a[index] == true) {
count++;
if(count == 3) {
leftCount--;
a[index] = false;
count = 0;
}
}
index++;
if(index == a.length)
index = 0;
}
for(int i=0; i<a.length; i++) {
if(a[i] == true)
System.out.println(i);
//再次遍历,寻找值为true的位置
}
}
}
这段代码最后输出的值为435,代表着最后剩下的孩子下标为435,即第436个孩子。
第二种思想是面向对象的思想,首先我们看这个题目中一共有两个类:孩子、孩子围成的圈,那我们就定义出Kid和KidCircle两个类,并在KidCircle中定义出add和delete的方法,我们同样看代码:
public class Count3Quit {
public static void main(String[] args) {
KidCircle kc = new KidCircle(500);
int countNum = 0;
Kid k = kc.first;
/*
for(int i=0; i<500; i++) {
k.id = i;
k = k.right;
}
*/
while(kc.count > 1) {
countNum++;
if(countNum == 3) {
countNum = 0;
kc.delete(k);
}
k = k.right;
}
System.out.println(kc.first.id);
}
}
class Kid { //定义Kid类
int id;
Kid left;
Kid right;
}
class KidCircle { //定义KidCircle类
int count;
Kid first;
Kid last;
public KidCircle(int n) {
//count = n;
for(int i=0; i<n; i++) {
add();
}
}
public void add() {//增添分多钟情况增添
Kid k = new Kid();
k.id = count;
if(count <= 0) {
first = k;
last = k;
k.left = k;
k.right = k;
} else {
last.right = k;
first.left = k;
k.right = first;
k.left = last;
last = k;
}
count++;
}
public void delete(Kid k) {
if(count == 0) {
System.out.println("You have no kids in the KidCircle,So you should not delete any more!");
}
else if(count <= 1) {
first = last = null;
} else{
k.left.right = k.right;
k.right.left = k.left;
}
if(k == first) first = k.right;
else if(k == last) last = k.left;
count--;
}
}
这样程序运行之后同样输出435。