标签:
练习
1.2.1 编写一个Point2D的用例,从命令行接受一个整数N.在单位正方形中生成N个随机点,然后计算两点之间的最近距离. /*查阅Point2D的API*/
public class H1_2_01 { public static void main(String[] args) { int N=1000; Point2D[] arr=new Point2D[N]; for(int i=0;i<N;i++) arr[i]=new Point2D(Math.random(), Math.random()); double mindis=Double.POSITIVE_INFINITY; //mindis--store the minimum distance for(int i=0;i<N-1;i++) for(int j=i+1;j<N;j++) { double dis=arr[i].distanceTo(arr[j]); if(mindis>dis) mindis=dis; } StdOut.printf("the minimum distance is: %.5f\n",mindis); } }
1.2.2 编写一个Interval1D的用例,从命令行接受一个整数N.从标准输入中读取N个间隔(每个间隔由一对double值定义)并打印出所有相交的间隔对
public class H1_2_02 { public static void main(String[] args) { int N=10; Interval1D[] arr=new Interval1D[N]; for(int i=0;i<N;i++) { StdOut.println("please input an interval1D."); double lo=StdIn.readDouble(); double hi=StdIn.readDouble(); while(lo>hi) //消除不合理的输入 { StdOut.println("the input is illegal, please input again."); lo=StdIn.readDouble(); hi=StdIn.readDouble(); } arr[i]=new Interval1D(lo, hi); } for(int i=0;i<N-1;i++) for(int j=i+1;j<N;j++) { if(arr[i].intersects(arr[j])) StdOut.printf("the interval %s is intersected to the interval %s\n",arr[i].toString(),arr[j].toString()); } } }
1.2.3 编写一个Interval2D的用例,从命令行接受参数N、min和max.生成N个随机的2D间隔,其宽和高均匀的分布在单位正方形中的min和max之间.用StdDraw画出他们并打印出橡胶的间隔对的数量以及包含关系的间隔对数量
public class H1_2_3 { public static void main(String[] args) { int N=20; double min=0.05; double max=0.1; int containCnt=0;int intersectCnt=0; Interval2D[] arr=new Interval2D[N]; Interval1D[] arrx=new Interval1D[N]; Interval1D[] arry=new Interval1D[N]; for(int i=0;i<N;i++) { double x=StdRandom.uniform(0.0,1-max); arrx[i]=new Interval1D(x, x+StdRandom.uniform(min, max)); double y=StdRandom.uniform(0.0,1-max); arry[i]=new Interval1D(y, y+StdRandom.uniform(min,max)); arr[i]=new Interval2D(arrx[i], arry[i]); StdDraw.setPenColor(StdDraw.BOOK_BLUE); arr[i].draw(); } for(int i=0;i<N-1;i++) for(int j=i+1;j<N;j++) { if(arr[i].intersects(arr[j])) { intersectCnt++; if(iscontains(arrx[i],arry[i], arrx[j], arry[j])) containCnt++; } } StdOut.printf("the intersect interval2D=%d, the contain interval2D=%d\n", intersectCnt,containCnt); } public static boolean iscontains(Interval1D x1,Interval1D y1,Interval1D x2,Interval1D y2) //判断是否存在包含关系 { if(x1.left()<=x2.left()&&x1.right()>=x2.right()&&y1.left()<=y2.left()&&y1.right()>=y2.right()) return true; if(x2.left()<=x1.left()&&x2.right()>=x1.right()&&y2.left()<=y1.left()&&y2.right()>=y1.right()) return true; return false; } }
注:另一种解决思路是在Interval2D类中添加判断是否存在包含关系的实例函数
1.2.4 主要考察字符串不可变---因此对字符串重新"赋值"其实是指向了新的对象而不是改变原有值
1.2.6 编写一个程序检查两个给定的字符串s和t是否互为回环变位(如果字符串s中的字符循环移动任意位置之后能够得到另一个字符串t,那么s就被称为t的回环变位) /*掌握字符串的灵活用法*/
public class H1_2_06 { public static void main(String[] args) { StdOut.println(cirRotation("ACTGACG", "TGACGAC")); } public static boolean cirRotation(String s,String t) { String temp=s+s; //该语句起到很大的简便判断作用 if(temp.indexOf(t)!=-1&&s.length()==t.length()) return true; return false; } }
作者网站上给出的答案:Solution: (s.length() == t.length()) && (s.concat(s).indexOf(t) >= 0)
1.2.9 修改BinarySearch,使用Counter统计在查找中被检查的键的总数并在查找结束后打印该值.
public class H1_2_09 { public static void main(String[] args) { Counter cnt=new Counter("count"); int[] arr={1,4,5,6,7,8,9}; Arrays.sort(arr); int key=9; rank(key,arr,cnt); StdOut.println(cnt.toString()); } public static int rank(int key,int[] a,Counter cnt) { int lo=0; int hi=a.length-1; while(lo<=hi) { cnt.increment(); //每次进入循环代表一次检查 int mid=lo+(hi-lo)/2; if(key<a[mid]) hi=mid-1; else if(key>a[mid]) lo=mid+1; else return mid; } return -1; } }
1.2.10 编写一个类VisualCounter,支持加一和减一操作.它的构造函数接受两个参数N和max,其中N指定了操作的最大次数,max指定了计数器的最大绝对值.作为副作用,用图形显示每次计数器变化后的值.
先根据要求列出"需求"API /*明确类所需要的数据,方法等*/
VisualCounter(int N,int max) | 构造函数 |
increment() | 加一操作 |
decrement() | 减一操作 |
public class VisualCounter { private int cnt=0; private int opN=0; private int max; private int N; public VisualCounter(int N,int max) { this.N=N; this.max=max; StdDraw.setXscale(0,N); StdDraw.setYscale(-max-0.1,max+0.1); StdDraw.setPenColor(StdDraw.BOOK_BLUE); } public void increment() { if(cnt<max&&opN<N) { cnt++; opN++; StdDraw.filledRectangle(opN-0.5, cnt/2.0, 0.9/2, Math.abs(cnt)/2.0); //采用柱状图体现变化后的值 } } public void decrement() { if(-cnt<max&&opN<N) { cnt--; opN++; StdDraw.filledRectangle(opN-0.5, cnt/2.0, 0.9/2, Math.abs(cnt)/2.0); } } public static void main(String[] args) { int N=10;int max=5; VisualCounter vc=new VisualCounter(N, max); int i=0; while(i<N) { if(StdRandom.bernoulli(0.5)) //采用等可能出现进行测试 vc.increment(); else vc.decrement(); i++; } } }
1.2.11&1.2.12 根据Date的API实现一个SmartDate类型,在日期非法时抛出一个异常,并为SmartDate添加一个方法dayOfTheWeek(),为日期中每周的日返回Monday到Sunday中的适当值.(可以假定时间是21世纪) /*此题可了解构造函数直接如何调用,闰年的判断,蔡勒公式判断星期以及抛出异常的使用~ 此题重要!*/
Date的API如下
SmartDate(int month,int day,int year) | 创建一个日期 |
SmartDate(String str) | 创建一个日期 |
int day() | 日 |
int month() | 月 |
int year() | 年 |
String dayOfTheWeek() | 当日为星期几 |
public class SmartDate { private int year; private int month; private int day; public SmartDate(int y,int m,int d) { if(!isIllegal(y,m,d)) throw new IllegalArgumentException("illegal date!!"); else { year=y; month=m; day=d; } } public SmartDate(String date) { String[] fields=date.split("/"); int m=Integer.parseInt(fields[0]); int d=Integer.parseInt(fields[1]); int y=Integer.parseInt(fields[2]); // this(y,m,d); ---不可行,必须要写在第一行,因此此处不可用 if(!isIllegal(y,m,d)) throw new IllegalArgumentException("illegal date!!"); else { year=y; month=m; day=d; } } public int year() { return year; } public int month() { return month; } public int day() { return day; } public String toString() { return month()+"/"+day()+"/"+year(); } //运用蔡勒公式---判断改日的星期 public String dayOfWeek() { int w=(year/100/4-2*(year/100)+year%100+year%100/4+26*(month+1)/10+day-1)%7; switch(w) { case 1: return "Monday"; case 2: return "Tuesday"; case 3: return "Wednesday"; case 4: return "Thursday"; case 5: return "Friday"; case 6: return "Saturday"; default: return "Sunday"; } } //判断是否合法 private boolean isIllegal(int y,int m,int d) //判断日期是否合法:三方面--年月日 { if(y<1||m<1||m>12||d<0||d>31) return false; int[] monthOfDay={0,31,-1,31,30,31,30,31,31,30,31,30,31}; if(isLeapYear(y)) monthOfDay[2]=29; else monthOfDay[2]=28; if(monthOfDay[m]<d) return false; return true; } private boolean isLeapYear(int year) //判断是否为闰年 { if(year%100!=0&&year%4==0) return true; else if(year%100==0&&year%400==0) return true; else return false; } public static void main(String[] args) { SmartDate sd=new SmartDate(2015,9,1); StdOut.println(sd.toString()+" "+sd.dayOfWeek()); } }
1.2.13&1.2.14 用我们对Date的实现作为模板实现Transaction类型 /*euqal()重载---一般分为①是否同引用②是否为空③类型是否相同④3同强转⑤内容是否同*/
根据表1.2.6给出的TransactionAPI如下(去掉compareTo)
Transaction(String who, SmartDate when, double amount) | 创建一笔交易 |
Transaction(String transaction) | 创建一笔交易 |
String who() | 客户名 |
Date when() | 交易日期 |
double amount() | 交易金额 |
String toString() | 对象的字符串表示 |
boolean equals(Object that) | 该笔交易和that是否相同 |
public class Transaction { private String name; private SmartDate date; private double num; public Transaction(String who,SmartDate when,double amount) { name=who.toString(); date=new SmartDate(when.year(), when.month(), when.day()); num=amount; } public Transaction(String trans) { String[] fields=trans.split("\\s+"); name=fields[0]; date=new SmartDate(fields[1]); num=Double.parseDouble(fields[2]); } public String who() { return name; } public SmartDate when() { return date; } public double amount() { return num; } public String toString() { return "name:"+name+", date:"+date.toString()+", amount:"+num; } public boolean equals(Object x) //判断是否相等 { if(this==x) return true; if(x==null) return false; if(this.getClass()!=x.getClass()) return false; Transaction that=(Transaction) x; return that.date.equals(date)&&that.amount()==num&&that.who()==name; } public static void main(String[] args) { SmartDate date=new SmartDate(1996,12,5); Transaction tran=new Transaction("Bob",date,1000); StdOut.println(tran.toString()); } }
提高题
1.2.15 文件输入.基于String的split()方法实现In中的静态方法readInts().
public class H1_2_15 { public static int[] readInts(String name) { In in=new In(name); String input=in.readAll(); String[] words=input.split("\\s+"); int[] ints=new int[words.length]; for(int i=0;i<words.length;i++) ints[i]=Integer.parseInt(words[i]); return ints; } public static void main(String[] args) { int[] ints=readInts("h1_2_15.txt"); for(int a:ints) StdOut.printf("%d ",a); } }
1.2.16 有理数.为有理数实现一个不可变数据类型Rational,支持加减乘除操作 /*从中思考如何自己来写出一个API大纲然后实现之*/
Rational(int numerator, int denominator) | |
Rational plus(Rational b) | 该数与b之和 |
Rational minus(Rational b) | 该数与b之差 |
Rational times(Rational b) | 该数与b之积 |
Ratioanl divides(Rational b) | 该数与b之商 |
boolean equals(Rational that) | 该数与that相等吗 |
String toString() | 对象的字符串表示 |
public class Rational { private long numerator; private long denominator; public Rational(int numerator,int denominator) { if(denominator<0) //为后续方便,始终将分母变为正数 { numerator=-1*numerator; denominator=-1*denominator; } long cd=gcd(Math.abs(numerator),Math.abs(denominator)); //化为分数的最简形式 this.numerator=numerator/cd; this.denominator=denominator/cd; } public long getnumerator() { return numerator; } public long getdenominator() { return denominator; } public Rational plus(Rational b) { long num=b.getnumerator(); long den=b.getdenominator(); long tempnum=num*denominator+numerator*den; long tempden=den*denominator; long cd=gcd(Math.abs(tempnum),Math.abs(tempden)); this.numerator=tempnum/cd; this.denominator=tempden/cd; return this; } public Rational minus(Rational b) { long num=b.getnumerator(); long den=b.getdenominator(); long tempnum=numerator*den-num*denominator; long tempden=den*denominator; long cd=gcd(Math.abs(tempnum),Math.abs(tempden)); this.numerator=tempnum/cd; this.denominator=tempden/cd; return this; } public Rational times(Rational b) { long num=b.getnumerator(); long den=b.getdenominator(); long tempnum=numerator*num; long tempden=den*denominator; long cd=gcd(Math.abs(tempnum),Math.abs(tempden)); this.numerator=tempnum/cd; this.denominator=tempden/cd; return this; } public Rational divides(Rational b) { long num=b.getnumerator(); long den=b.getdenominator(); long tempnum=numerator*den; long tempden=num*denominator; long cd=gcd(Math.abs(tempnum),Math.abs(tempden)); this.numerator=tempnum/cd; this.denominator=tempden/cd; return this; } public boolean equals(Rational that) { if(this==that) return true; if(that==null) return false; return this.numerator==that.getnumerator()&&this.denominator==that.getdenominator(); } public String toString() { if(denominator==1) return numerator+""; else return numerator+"/"+denominator; } private long gcd(long x,long y) { if(y==0) return x; long temp=x%y; return gcd(y,temp); } public static void main(String[] args) { Rational rat1=new Rational(10, 30); Rational rat2=new Rational(2, 5); StdOut.printf("plus: %s\n",rat1.plus(rat2).toString()); StdOut.printf("minus: %s\n",rat1.minus(rat2).toString()); //ps:此处rat1已经为+rat2后的值 StdOut.printf("times: %s\n",rat1.times(rat2).toString()); StdOut.printf("divides: %s\n",rat1.divides(rat2).toString()); StdOut.printf("equals?: %s\n",rat1.equals(rat2)); } }
1.2.18 累加器的方差. var()---计算方差, stddev()---计算标准差 /*回顾1.1.34中内容---此处采用的求均值和方差的方式很好,记忆之*/
public class Accumulator { private double m; //m---均值 private double s; //s---总和 private int N; //N---个数 public void addDataValue(double x) { N++; s=s+1.0*(N-1)/N*(x-m)*(x-m); //见后续推导 m=m+(x-m)/N; //即(x-m)/N可以理解为将x与m的偏离程度平均分散给N个 } public double mean() { return m; } public double var() { return s/(N-1); } public double stddev() { return Math.sqrt(this.var()); } }
以上答案中错误和不合理之处希望大家指出O(∩_∩)O~
注:里面很多来源于《算法》作者给的库
标签:
原文地址:http://www.cnblogs.com/Tinyshine/p/4775168.html