数据结构之数羊问题
1.有50只羊,从第一个开始数,每隔三个取出一只羊,然后继续隔三个取出,问最后那一只羊是哪一只。
分析:先不考虑什么循环结构之类的,就想到什么写什么,到最后你会发现规律。
(1)先定义一个数组,里面存储的内容的是小羊的编号。并且定义按照数组下标值增加和查询,删除数组值的方法
public class Array01 {
int maxSize;
int [] a;
int nElems;
public Array01(int m) {
maxSize=m;
a=new int [maxSize];
nElems=0;
}
public void setElem(int x) { //增加
a[nElems++]=x;
}
public int getElem(int y) { //查询
return a[y];
}
public void delete (int h) { //删除
int temp;
temp=a[h];
for(int i=h;i<nElems-1;i++ ) {
a[i]=a[i+1];
}
nElems--;
System.out.print(temp+" ");
}
}
(2)初始化小羊数组
public static void main(String[] agrs) { int n=50; //n是小羊的个数 int m=3; //m是间隔 Array01 arr=new Array01(n); //初始化小羊数组 for(int i=0;i<n;i++) { //给每个小羊设置编号,即给数组赋值1-n arr.setElem(i+1); System.out.print(arr.getElem(i)+" "); } System.out.println();
}
(3)先考虑如果没有超出数组界限的情况下,该怎么选取和删除小羊。
int p=0;//记录开始数的位置
p=p+(m-1);
arr.delete(p%arr.nElems);
通过上面的代码,你会发现数组会减去一个数,而这个数正好是3。然后再复制粘贴p=p+(m-1); arr.delete(p%arr.nElems);这两串代码,你会发现事情继续按照预想的那样执行。所以。
public class Array01 { int maxSize; int [] a; int nElems; public Array01(int m) { maxSize=m; a=new int [maxSize]; nElems=0; } public void setElem(int x) { a[nElems++]=x; } public int getElem(int y) { return a[y]; } public void delete (int h) { int temp; temp=a[h]; for(int i=h;i<nElems-1;i++ ) { a[i]=a[i+1]; } nElems--; System.out.print(temp+" "); } public static void main(String[] agrs) { int n=50; int m=3; Array01 arr=new Array01(n); System.out.print("原羊:"); for(int i=0;i<n;i++) { arr.setElem(i+1); System.out.print(+arr.getElem(i)+" "); } System.out.println(); int p=0;//记录开始数的位置 System.out.print("取掉的羊:"); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); System.out.println(); System.out.print("剩下的羊:"); for(int i=0;i<arr.nElems;i++) System.out.print(arr.getElem(i)+" "); System.out.println(); } }
执行结果:
原羊: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
取掉的羊:3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 1
剩下的羊:2 4 5 7 8 10 11 13 14 16 17 19 20 22 23 25 26 28 29 31 32 34 35 37 38 40 41 43 44 46 47 49 50
(4)这样我们就第一次遍历完了整个数组。还有剩余的养,剩余的养会组成一个新的数组,对于我们来说又可以像上面那一步一样,寻找和删除,因为规律是一样的。
p=0; System.out.print("取掉的羊:"); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); p=p+(m-1); arr.delete(p%arr.nElems); System.out.println(); System.out.print("剩下的羊:"); for(int i=0;i<arr.nElems;i++) System.out.print(arr.getElem(i)+" "); System.out.println();
结果:
原羊: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
取掉的羊:3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 1
剩下的羊:2 4 5 7 8 10 11 13 14 16 17 19 20 22 23 25 26 28 29 31 32 34 35 37 38 40 41 43 44 46 47 49 50
取掉的羊:5 10 14 19 23 28 32 37 41 46 50
剩下的羊:2 4 7 8 11 13 16 17 20 22 25 26 29 31 34 35 38 40 43 44 47 49
(5)按照这个规律,我想都知道该怎么做了,复制粘贴代码,自己目测是否已经遍历了整个数组,决定需要复制的代码量。
public class Array01{
int maxSize;
int [] a;
int nElems;
public Array01(int m) {
maxSize=m;
a=new int [maxSize];
nElems=0;
}
public void setElem(int x) {
a[nElems++]=x;
}
public int getElem(int y) {
return a[y];
}
public void delete (int h) {
int temp;
temp=a[h];
for(int i=h;i<nElems-1;i++ ) {
a[i]=a[i+1];
}
nElems--;
System.out.print(temp+" ");
}
public static void main(String[] agrs) {
int n=50;
int m=3;
Array01 arr=new Array01(n);
System.out.print("原羊:");
for(int i=0;i<n;i++) {
arr.setElem(i+1);
System.out.print(+arr.getElem(i)+" ");
}
System.out.println();
//第一个外层
int p=0;//记录开始数的位置
System.out.print("取掉的羊:");
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
System.out.println();
System.out.print("剩下的羊:");
for(int i=0;i<arr.nElems;i++)
System.out.print(arr.getElem(i)+" ");
System.out.println();
//第二个外层
p=0;
System.out.print("取掉的羊:");
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
System.out.println();
System.out.print("剩下的羊:");
for(int i=0;i<arr.nElems;i++)
System.out.print(arr.getElem(i)+" ");
System.out.println();
//第三个外层
p=0;
System.out.print("取掉的羊:");
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
System.out.println();
System.out.print("剩下的羊:");
for(int i=0;i<arr.nElems;i++)
System.out.print(arr.getElem(i)+" ");
System.out.println();
//第四个外层
p=0;
System.out.print("取掉的羊:");
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
System.out.println();
System.out.print("剩下的羊:");
for(int i=0;i<arr.nElems;i++)
System.out.print(arr.getElem(i)+" ");
System.out.println();
//第五个外层
p=0;
System.out.print("取掉的羊:");
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
System.out.println();
System.out.print("剩下的羊:");
for(int i=0;i<arr.nElems;i++)
System.out.print(arr.getElem(i)+" ");
System.out.println();
//
p=0;
System.out.print("取掉的羊:");
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
arr.delete(p%arr.nElems);
System.out.println();
System.out.print("剩下的羊:");
for(int i=0;i<arr.nElems;i++)
System.out.print(arr.getElem(i)+" ");
System.out.println();
//第六个外层
p=0;
System.out.print("取掉的羊:");
p=p+(m-1);
arr.delete(p%arr.nElems);
p=p+(m-1);
int end=arr.getElem(p%arr.nElems);
arr.delete(p%arr.nElems);
System.out.println();
System.out.print("剩下的羊:");
for(int i=0;i<arr.nElems;i++)
System.out.print(arr.getElem(i)+" ");
System.out.println();
System.out.println("最后一次取的羊:"+end);
}
}
结果:
原羊: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
取掉的羊:3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 1
剩下的羊:2 4 5 7 8 10 11 13 14 16 17 19 20 22 23 25 26 28 29 31 32 34 35 37 38 40 41 43 44 46 47 49 50
取掉的羊:5 10 14 19 23 28 32 37 41 46 50
剩下的羊:2 4 7 8 11 13 16 17 20 22 25 26 29 31 34 35 38 40 43 44 47 49
取掉的羊:7 13 20 26 34 40 47 4
剩下的羊:2 8 11 16 17 22 25 29 31 35 38 43 44 49
取掉的羊:11 22 31 43 2
剩下的羊:8 16 17 25 29 35 38 44 49
取掉的羊:17 35 49
剩下的羊:8 16 25 29 38 44
取掉的羊:25 44
剩下的羊:8 16 29 38
取掉的羊:29 16
剩下的羊:8 38
最后一次取的羊:16
从这个过程我们可以知道哪个是核心代码,哪个是核心属性
2.将循环的部分用循环语句写出
public class Array02 { int maxSize; int [] a; int nElems; public Array02(int m) { maxSize=m; a=new int [maxSize]; nElems=0; } public void setElem(int x) { a[nElems++]=x; } public int getElem(int y) { return a[y]; } public void delete (int h) { int temp; temp=a[h]; for(int i=h;i<nElems-1;i++ ) { a[i]=a[i+1]; } nElems--; System.out.print(temp+" "); } public static void main(String[] agrs) { int end=0; int n=50; int m=3; Array01 arr=new Array01(n); System.out.print("原羊:"); for(int i=0;i<n;i++) { arr.setElem(i+1); System.out.print(+arr.getElem(i)+" "); } System.out.println(); while(arr.nElems>=m) { int p=0;//记录开始数的位置 System.out.print("取掉的羊:"); while(p<arr.nElems) { p=p+(m-1); if(arr.nElems==3) end=arr.getElem(p%arr.nElems); arr.delete(p%arr.nElems); } System.out.println(); System.out.print("剩下的羊:"); for(int i=0;i<arr.nElems;i++) System.out.print(arr.getElem(i)+" "); System.out.println(); } System.out.println("最后一次取的羊:"+end); } }
有三个地方,第一是外层循环什么时候结束(当数组的长度小于3时结束),第二是里面的循环什么时候结束(当p超过数组末尾时结束),第三是最后取值怎么取(当数组只有三个数时就是取值的最佳时期)。
3.整理通用的
public class Array01 { int maxSize; int [] a; int nElems; public Array01(int m) { maxSize=m; a=new int [maxSize]; nElems=0; } public void setElem(int x) { a[nElems++]=x; } public int getElem(int y) { return a[y]; } public void delete (int h) { int temp; temp=a[h]; for(int i=h;i<nElems-1;i++ ) { a[i]=a[i+1]; } nElems--; System.out.print(temp+" "); } public static void main(String[] agrs) { int end=0; //放置最后取的羊的编号 int n=50;//羊的总个数 int m=3; //隔几个数取值 int p;//移动的标记,选定从哪开始数起 Array01 arr=new Array01(n); System.out.print("原羊:"); for(int i=0;i<n;i++) { arr.setElem(i+1); System.out.print(+arr.getElem(i)+" "); } System.out.println(); while(arr.nElems>=m) { p=0;//记录开始数的位置 System.out.print("取掉的羊:"); while(p<arr.nElems) { p=p+(m-1); if(arr.nElems==m) end=arr.getElem(p%arr.nElems); arr.delete(p%arr.nElems); } System.out.println(); System.out.print("剩下的羊:"); for(int i=0;i<arr.nElems;i++) System.out.print(arr.getElem(i)+" "); System.out.println(); } System.out.println("最后一次取的羊:"+end); } }