数据结构之数羊问题

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);
    
        
        
    }

    

}

 

posted @ 2017-09-29 18:47  S-Mustard  阅读(525)  评论(0编辑  收藏  举报