『算法』读书笔记 1.2 Java语法 - 练习代码总结
Chapter 1
本章结构
1.1Java语法
1.2数据抽象 练习部分
1.3集合类抽象数据类型:背包 (Bags) 、队列 (Queues) 、栈 (Stacks)
1.4面向操作的抽象数据类型
1.5连通性问题-Case Study: Union - Find ADT
1.2.1 编写一个Point2D的用例,从命令行接受一个整数N。在单位正方形内生成N个随机点,然后计算两点之间的最近距离
问题:用例中所采用的双层循环计算两点之间距离的方法有无更好的实现?
1: public class ShortDistance {
2: public static void main(String[] args)
3: {
4: int N = Integer.parseInt(args[0]);
5: Point2D[] p = new Point2D[N];
6: double min = 1.00;
7:
8: //Generation of N points
9: for (int i = 0; i < N; i++)
10: {
11: double x = Math.random();
12: double y = Math.random();
13: p[i] = new Point2D(x, y);
14: p[i].draw();
15: }
16:
17: //Calculation of minimum distance between two points
18: for (int i =0; i < N; i++)
19: {
20: for (int j = 0; j < N; j++)
21: {
22: if (i != j)
23: {
24: if (p[i].distanceTo(p[j]) < min )
25: {
26: min = p[i].distanceTo(p[j]);
27: }
28: }
29: }
30:
31: }
32: StdOut.print("the minimum distance is " + min);
33: }
34:
35: }
ex1.2.3 编写一个Interval1D的用例,从命令行接受一个整数N。从标准输入中读取N个间隔(每个间隔由一对double值定义)并打印出所有相交的间隔对
总结:
1.从标准输入中读取数据可以直接利用double[] d = StdIn.readDoubles()实现
2.双层遍历循环中,外层范围限制为[0,N/2),内层范围限制为[N/2,N),这样可以避免循环后再处理重复比较的问题
1: public class Interval1DClient
2: {
3: public static void main(String[] args)
4: {
5: int N = Integer.parseInt(args[0]);
6: Interval1D[] interval = new Interval1D[N];
7: double[] d = StdIn.readDoubles();
8:
9: for (int i = 0; i < N; i++)
10: {
11: interval[i] = new Interval1D(d[2*i], d[2*i+1]);
12: // StdDraw.line(interval[i].left(), .5, interval[i].right(), 5);
13: }
14:
15: /*
16: * The following codes are for test only
17: for (int i = 0; i < N; i++)
18: {
19: //interval[i] = new Interval1D(d[2*i], d[2*i+1]);
20: StdDraw.line(interval[i].left(), .5, interval[i].right(), .5);
21: }
22: */
23:
24: for (int i = 0; i < N / 2; i++)
25: {
26: for (int j = N / 2; j < N; j++)
27: {
28: if (i != j)
29: if (interval[i].intersects(interval[j]))
30: {
31: StdDraw.line(interval[i].left(), .5, interval[i].right(), .5);
32: StdOut.println("Interval[" + i + "] intersects with interval[" + j + "].");
33: }
34:
35: }
36: }
37:
38: }
39: }
ex1.2.9 修改BinarySearch,使用COunter统计在键数被查找的次数并在查找全部结束后打印该值
1: import java.util.Arrays;
2:
3: public class BinarySearchCount {
4:
5: // precondition: array a[] is sorted
6: public static int rank(int key, int[] a, Counter keys) {
7: int lo = 0;
8: int hi = a.length - 1;
9: keys.increment();
10: while (lo <= hi) {
11: // Key is in a[lo..hi] or not present.
12: int mid = lo + (hi - lo) / 2;
13: if (key < a[mid]) hi = mid - 1;
14: else if (key > a[mid]) lo = mid + 1;
15: else return mid;
16: }
17: return -1;
18: }
19:
20: public static void main(String[] args) {
21: Counter keys = new Counter("keys");
22: int[] whitelist = In.readInts(args[0]);
23:
24: Arrays.sort(whitelist);
25:
26: // read key; print if not in whitelist
27: while (!StdIn.isEmpty()) {
28: int key = StdIn.readInt();
29: if (rank(key, whitelist, keys) == -1)
30: StdOut.println(key);
31: }
32: StdOut.println("Summary: " + keys + " examined");
33: }
34: }
ex1.2.10 编写一个VisualCounter类,支持加一和减一操作。它的构造函数接受两个参数N和max,其中N指定了操作的最大次数,max指定了计数器的最大绝对值。作为副作用,用图像显示每次计数器变化后的值。
总结:
1.构造函数中应该把绘图相关的参数给初始化,例如X和Y轴的取值范围以及笔触的大小
2.Y轴的取值范围特别注意,为正负max,因为要考虑绝对值空间
1: public class VisualCounter {
2: private int count;//Record the times
3: private int val;//Record value of the Counter
4: private int x = 0;
5: int maxOperation;
6: int maxVal;
7:
8: public VisualCounter(int N, int max)
9: {
10: maxOperation = N;
11: maxVal = max;
12: StdDraw.setXscale(0, N);
13: StdDraw.setYscale(-max, max);
14: StdDraw.setPenRadius(.05);
15: }
16:
17: public int tally()
18: { return count; }
19:
20: public void increment()
21: {
22: if (count < maxOperation && val < maxVal)
23: {
24: count++;
25: val++;
26: x++;
27: StdDraw.point(x, val);
28: }
29: }
30:
31: public void decrement()
32: {
33: if (count < maxOperation && val > -maxVal)
34: {
35: count++;
36: val--;
37: x++;
38: StdDraw.point(x, val);
39: }
40: }
41:
42: //Test Client
43: public static void main(String[] args)
44: {
45: VisualCounter VC = new VisualCounter(10, 20);
46:
47:
48: VC.increment();
49: VC.increment();
50: VC.decrement();
51: VC.decrement();
52: VC.decrement();
53: VC.decrement();
54: VC.decrement();
55: VC.decrement();
56: VC.decrement();
57: VC.decrement();
58: VC.decrement();
59: VC.decrement();
60:
61:
62:
63: StdOut.println(VC.tally());
64:
65:
66: }
67:
68: }
ex1.2.11 根据Date的API实现一个SmartDate类型,在日期非法时抛出一个异常
ex1.2.12 为SmartDate添加一个方法dayOfTheWeek(),为日期中每周的日返回Monday、Tuesday、Wednesday、Thursday……假定是21世纪
总结:
1.学习Switch Case语句中多个值匹配同一个代码块的写法
2.Zeller公式可以用来计算dayOfTheWeek
问题:日期合法性判断有无更好的实现?
1: public class SmartDate {
2: private final int month;
3: private final int day;
4: private final int year;
5: public int dayOfTheWeek;
6:
7: public SmartDate(int m, int d, int y)
8: {
9: month = m;
10: day = d;
11: year = y;
12: if (month < 13 && month >0 )
13: {
14: switch(month)
15: {
16: case 1:
17: case 3:
18: case 5:
19: case 7:
20: case 8:
21: case 10:
22: case 12:
23: if (day > 31 || day < 1)
24: throw new RuntimeException("Error: illegal Date");
25: break;
26:
27: case 4:
28: case 6:
29: case 9:
30: case 11:
31: if (day > 30 || day < 1)
32: throw new RuntimeException("Error: illegal Date");
33: break;
34:
35: case 2:
36: if (year % 4 == 0)
37: {
38: if (day > 29 || day < 1)
39: throw new RuntimeException("Error: illegal Date");
40: }
41: else if (day > 28 || day < 1)
42: throw new RuntimeException("Error: illegal Date");
43: }
44: }
45: else throw new RuntimeException("Error: illegal Date");
46: }
47:
48: public int month()
49: { return month; }
50: public int day()
51: { return day; }
52: public int year()
53: { return year; }
54: public void dayOfTheWeek()
55: {
56: dayOfTheWeek = (year+(year/4)-15+(26*(month+1)/10)+day-1)%7;//using Zeller formula to obtain the value
57: switch(dayOfTheWeek)
58: {
59: case 1:
60: StdOut.println("Monday");
61: break;
62: case 2:
63: StdOut.println("Tuesday");
64: break;
65: case 3:
66: StdOut.println("Wednesday");
67: break;
68: case 4:
69: StdOut.println("Thursday");
70: break;
71: case 5:
72: StdOut.println("Friday");
73: break;
74: case 6:
75: StdOut.println("Saturday");
76: break;
77: case 7:
78: StdOut.println("Sunday");
79: break;
80: }
81: }
82:
83:
84: public static void main(String[] args)
85: {
86: SmartDate SD = new SmartDate(Integer.parseInt(args[0]),Integer.parseInt(args[1]),Integer.parseInt(args[2]));
87: SD.dayOfTheWeek();
88: }
89:
90: }