34岁!100天!学会Java编程(Day45-Day48)—数据结构和基本算法

冻成狗

我觉得自动驾驶汽车最有前途的方向是,在早上起来上班的时候,能提前自动暖车。

为什么要学习数据结构和算法?

老实说拿起书的时候我也没想明白,它很枯燥,看不到明显的作用,让人昏昏欲睡。为了给自己打劲,我查了查别人为什么要学习数据结构和算法,有说锻炼编程思维的,有说提高程序性能的,还有总结成公式的:编程=数据结构+算法。几乎所有程序员都一副过来人的口吻说,好好学,不然你会后悔的。我这人的优点之一,就是听人劝,吃饱饭,我主动接受思想教育,继续学了下去。
在网上买的教程,为了免运费,凑了两本¥101,一本《数据结构与算法经典问题解析》,一本《算法竞赛入门经典》,然后两本书的风格差了半个地球,导致看完一本,还得倒时差才能看进去另外一本。好吧,不为自己看困了找借口。下面上图:


数据结构、算法与思想

(一)例一:斐波那契数列(四)(五)(2)

已知:斐波那契数列的特点,f(n)=f(n-1)+f(n-2);f(1)=1;f(2)=1;
求:任意给定正整数n,求长度为n的斐波那契数列
设计:理论上递归和递推可以相互转化,分别使用正向递推和逆向递归求解;数列长度不定,且该数列仅用于查询,使用单向链表。

public class Algorithm {
 static List fibonacci1=new LinkedList<>();
 static List fibonacci2=new LinkedList<>();
 public static void main(String[] args) {
   int n=21;
  for(int i=1;i<=n;i++){fibonacci1.add(fib1(i));}
  for(int i=0;i   for(int i=1;i<=n;i++){fibonacci2.add(fib2(i));}
  for(int i=0;i   }
//递推解法;时间复杂度O(n),空间复杂度O(1),编程复杂度:中
  public static int fib1(int n){
    if(n<=2)return 1;
    int f1=1,f2=1;
    int f=0;
    for(int i=3;i<=n;i++){
      f=f1+f2;
      f1=f2;
      f2=f;
    }
    return f;
  }
//递归解法;时间复杂度O(n),空间复杂度O(n),编程复杂度:易
 public static int fib2(int n){
  if(n<=2)return 1;
  return fib1(n-1)+fib1(n-2);
 }
}

(二)例二:生存者游戏(A)(五)(1)(2)

已知:n个人站成一圈,顺时针编号为1~n。有两个刽子手,A从1开始逆时针数,B从n开始顺时针数。在每一轮中,刽子手A走过k个人就停下来,刽子手B走过m个人就停下来(两人可停在同一个人面前),然后开枪。最后若只剩一个人,则结束。
求:输入正整数n,k,m,问最后是否有人活下来,活下来的是谁?
设计:采用自顶向下的编程,先写框架,再写伪代码,最后细节实现,考验将问题抽象的能力。数据结构开始设想双向循环链表,不过这个没有现成的类库,自己动手实现了一个,不太稳定,且编程复杂度较高,需要较多时间调试。本问题主要想练习抽象思维,遂放弃双向循环数组,改用数组实现。

抽象层
函数survivor(n,k,m){
1.初始状态设置。数组结构存储n个人(内化属性为活着(1)和死去(0));两个刽子手(内化属性为位置、方向、步长);幸存者人数。
2.递推。一次行刑为一次迭代,行刑后n个人的状态和两个刽子手的状态作为下一次迭代的输入。
3.结束判据。幸存者人数0||1,结束迭代。输出幸存者。
}
伪代码
 private class surv{} //定义圈子里的人
 private class headsman{} //定义刽子手
 public int execute(act,A,B){} //定义一轮行刑动作,输出死亡人数
public void Survivor(int n,int k,int m){
 surv[] act=new surv[n];
 headsman A;
 headsman B;
 survivor_num=n;
 while(survivor_num>1)){} //递推
  survivor_num=survivor_num-execute(act,A,B);
 for(int i=1;i<=n;i++)if(surv[i].status)System.out.println(i);
}
细节实现
private class surv{
 public boolean status=true;
}
private class headsman{
 public int pos;
 public int clock;
 public int step;
 public headsman(int pos,boolean clock,int step){
  this.pos=pos;
  if(clock)this.clock=1;else this.clock=-1;
  this.step=step;
 }
 public int next(){
  return pos=pos+clock;
 }
}
public static int execute(surv[] act,headsman A,headsman B){
 for(int j=1;j<=A.step;j++){
  do{A.next();if(A.pos==0)A.pos=act.length-1;}
  while(!act[A.pos].status);
 }
 for(int j=1;j<=B.step;j++){
  do{B.next();if(B.pos==act.length)B.pos=1;}
  while(!act[B.pos].status);
 }
 act[A.pos].status=false;
 if(A.pos!=B.pos){
  act[B.pos].status=false;
  return 2;
 }else return 1;
}
public static void Survivor(int n,int k,int m){
 surv[] act=new surv[n+1];
 for(int i=1;i<=n;i++)act[i]=test.new surv();
 headsman A=test.new headsman(1,false,k);
 headsman B=test.new headsman(n,true,m);;
 int survivor_num=n;
 while(survivor_num>1)survivor_num=survivor_num-execute(act,A,B);
 for(int i=1;i<=n;i++)if(act[i].status)System.out.println(i);
}
注:两个私有类的实例化需要外部类的实例,因此代码中的test为外部类的实例,异地实现须更换为自己的外部类实例。

结果:在外部类的main方法中输入Survivor(21,3,4);得到的幸存者是11。

今天有点困了,改天再补几个案例

参考书目

你可能感兴趣的:(34岁!100天!学会Java编程(Day45-Day48)—数据结构和基本算法)