码迷,mamicode.com
首页 > 编程语言 > 详细

《算法:第四版》练习1.1部分答案

时间:2015-03-07 11:29:50      阅读:860      评论:0      收藏:0      [点我收藏+]

标签:

 以下答案纯属个人愚见,作为IT新手,算法代码中难免有逻辑漏洞和其他不足之处,欢迎朋友你点评拍砖,交流争辩能极大开阔思维,愿一起加油进步!^_^

1.1.19  在计算机上运行以下程序:

 1 public class Fibonacci {
 2 
 3     public static long F(int N) {
 4         if(0 == N)
 5             return 0;
 6         if(1 == N)
 7             return 1;
 8         return F(N - 1) + F(N - 2);
 9     }
10 
11     public static void main(String[] args) {
12         for(int N = 0; N < 100; ++N)
13             StdOut.println(N + "  " + F(N));
14     }
15 
16 }

计算机用这段程序在一个小时之内能够得到F(N) 结果的最大N 值是多少?开发F(N) 的一 个更好的实现,用数组保存已经计算过的值。 

技术分享
 1 public class Fibonacci {
 2 
 3     // Fibonacci数列计算,时间空间复杂度优化版
 4     private static int M = 100;
 5     private static long[] fib = new long[M];
 6     public static long fibonacciOptimization(int N) {
 7         if(0 == N)
 8             fib[0] = 0;
 9         else if(1 == N)
10             fib[1] = 1;
11         else
12             fib[N] = fib[N - 1] + fib[N -2];
13         return fib[N];
14     }
15 
16     public static void main(String[] args) {
17         for(int N = 0; N < 100; ++N) {
18             fib[N] = fibonacciOptimization(N);
19             StdOut.println(N + "\t" + fib[N]);
20         }
21     }
22 
23 }
View Code

 

1.1.20  编写一个递归的静态方法计算 ln( N! ) 的值。 

技术分享
 1     public static long factorial(int M) {
 2         if(0 == M || 1 == M)
 3             return 1;
 4         else
 5             return M * factorial(M - 1);
 6     }
 7 
 8     public static double ln(int N) {
 9         return Math.log(factorial(N));
10     }
11 
12     public static void main(String[] args) {
13         double val = ln(4);
14         StdOut.println(val);
15     }
View Code

 

1.1.21  编写一段程序,从标准输入按行读取数据,其中每行都包含一个名字和两个整数。然后用printf() 打印一张表格,每行的若干列数据包括名字、两个整数和第一个整数除以第二个整数的结果,精确到小数点后三位。可以用这种程序将棒球球手的击球命中率或者学生的考试分数制成表格。

技术分享
 1     public static void main(String[] args) {
 2         int M = 3;
 3         int index = 0;
 4         String[] strs = new String[M];
 5         while(index < M)
 6             strs[index++] = StdIn.readLine();
 7         for(int i = 0; i < strs.length; ++i) {
 8             String[] arr = strs[i].split("\\s+");
 9             double temp = Double.parseDouble(arr[1]) / Double.parseDouble(arr[2]);
10             StdOut.printf("%-10s   %-10s   %-10s   %-13.3f\n", arr[0], arr[1], arr[2], temp);
11         };
12     }
View Code

 

1.1.22  使用1.1.6.4 节中的rank() 递归方法重新实现BinarySearch 并跟踪该方法的调用。每当该方法被调用时,打印出它的参数lo 和hi 并按照递归的深度缩进。提示:为递归方法添加一个参数来保存递归的深度。 

技术分享
 1     /**
 2      * 递归查找关键词的索引
 3      * @param key
 4      * @param arr
 5      * @param low
 6      * @param high
 7      * @return
 8      */
 9     public static int rank(int key, int[] arr, int low, int high, int depth) {
10         printCallInfo(low, high, depth);
11         if(low > high)
12             return -1;
13         int mid = low + ((high - low) >> 1);
14         if(key < arr[mid])
15             return rank(key, arr, low, mid - 1, depth + 1);
16         else if(key > arr[mid])
17             return rank(key, arr, mid + 1, high, depth + 1);
18         else
19             return mid;
20     }
21 
22     /**
23      * 二分查找 : 递归描述
24      * @param key
25      * @param arr
26      * @return
27      */
28     public static int binarySearch(int key, int[] arr, int depth) {
29         return rank(key, arr, 0, arr.length - 1, depth);
30     }
31 
32     /**
33      * 打印缩进
34      * @param indents    缩进数
35      */
36     private static void printIndent(final int indents) {
37         for(int i = 0; i < indents; ++i)
38             StdOut.print("----------");
39     }
40 
41     /**
42      * 打印调用信息
43      * @param low
44      * @param high
45      * @param depth
46      */
47     private static void printCallInfo(int low, int high, int depth) {
48         StdOut.print(depth + "\t");
49         printIndent(depth);
50         StdOut.println(low + "\t" + high);
51     }
52 
53     public static void main(String[] args) {
54         int N = 1024;
55         int[] arr = new int[N];
56         for(int i = 0; i < N; ++i)
57             arr[i] = StdRandom.uniform(N * 50);
58         // 排序
59         Arrays.sort(arr);
60         // 从随机数组中随机抽取一个元素作为关键字
61         // 输出随机数组
62         StdOut.print("seq = ");
63         for(int i = 0 ; i < N; ++i)
64             StdOut.print(arr[i] + "\t");
65         int key = arr[StdRandom.uniform(N)];
66         StdOut.println("\nkey = " + key);
67         StdOut.println("---------------------------------------------------------------------------------------");
68         binarySearch(key, arr, 0);
69     }
View Code

 

1.1.27  二项分布。估计用以下代码计算binomial(100, 50) 将会产生的递归调用次数:

1 public static double binomial(int N,int k, double p) {
2         if(N == 0 && k == 0)
3             return 1.0;
4         if(N < 0 || k < 0)
5             return 0.0;
6         return (1.0 - p) * binomial(N-1, k, p) + p * binomial(N-1, k-1, p);
7     }

将已经计算过的值保存在数组中并给出一个更好的实现。

技术分享
 1     private static int binom_N = 100;
 2 
 3     private static int binom_k = 50;
 4 
 5     private static double[][] binom = new double[binom_N + 1][binom_k + 1];
 6 
 7     private static double binomial(int N, int k, double p) {
 8         if(N < 0 || k < 0) {
 9             return 0.0;
10         } else if(N == 0 && k == 0) {
11             if(binom[N][k] == -1.0)
12                 binom[N][k] = 1.0;
13         } else {
14             if (binom[N][k] == -1.0)
15                 binom[N][k] = (1.0 - p) * binomial(N - 1, k, p) + p * binomial(N - 1, k - 1, p);
16         }
17         return binom[N][k];
18     }
19 
20     public static void main(String[] args) {
21         // 数组binom初始化
22         for(int i = 0; i < binom_N + 1; ++i)
23             for(int j = 0; j < binom_k + 1; ++j)
24                 binom[i][j] = -1.0;
25         // 计算概率
26         double res = binomial(binom_N, binom_k, 0.25);
27         StdOut.println(res);
28     }
View Code

 

1.1.28  删除重复元素。修改BinarySearch 类中的测试用例来删去排序之后白名单中的所有重复元素。

 

1.1.29  等值键。为BinarySearch 类添加一个静态方法rank(),它接受一个键和一个整型有序数组(可能存在重复键)作为参数并返回数组中小于该键的元素数量,以及一个类似的方法count() 来返回数组中等于该键的元素的数量。注意:如果i 和j 分别是rank(key,a) 和count(key,a)的返回值,那么a[i..i+j-1] 就是数组中所有和key 相等的元素。看法:只有当key在数组中时才这样子。

技术分享
 1 /**
 2  * 二分查找统计
 3  * @param key   待查找关键字
 4  * @param arr   待查找数组
 5  * @return  返回小于key的个数即比等于key的第一个元素的索引值,若找不到则返回-1
 6  */
 7 private static int countLowers(int key, int[] arr) {
 8     int low = 0;
 9     int high = arr.length - 1;
10     while(low <= high) {
11         int mid = low + ((high - low) >> 1);
12         if(key < arr[mid])
13             high = mid - 1;
14         else if(key > arr[mid])
15             low = mid + 1;
16         else {
17             while(mid > 0 && arr[mid] == arr[mid - 1])              // 注意判断条件的先后顺序
18                 -- mid;
19             return mid;
20         }
21     }
22     return low;     // -1; 根据算法原理可知low是小于key的个数
23 }
24 
25 /**
26  * 统计与key相等的个数
27  * @param key   待查找关键字
28  * @param arr   待查找数组
29  * @return  返回与key相等的个数
30  */
31 private static int countEquals(int key, int[] arr) {
32     int lowers = countLowers(key, arr);
33     int idx = lowers;
34     if(idx == arr.length || key != arr[idx])                        // 注意判断条件的先后顺序
35         return 0;
36 
37     int cnt = 1;
38     while((idx < arr.length - 1) && (arr[idx] == arr[idx + 1])) {   // 注意判断条件的先后顺序
39         ++ cnt;
40         ++ idx;
41     }
42     return cnt;
43 }
44 
45 public static void main(String[] args) {
46     // 从文件读取数据
47     In in = new In("./data/tinyW.txt");
48     int[] whiteList = in.readAllInts();
49     // 排序并打印输出
50     Arrays.sort(whiteList);
51     for(int idx = 0; idx < whiteList.length; ++idx)
52         StdOut.print(whiteList[idx] + "\t");
53     StdOut.println();
54     // 从控制台读取关键字
55     int key = StdIn.readInt();
56     int lowers = countLowers(key, whiteList);
57     StdOut.println("小于\t" + key + "\t的个数是:\t" + lowers);
58     int equals = countEquals(key, whiteList);
59     StdOut.println("等于\t" + key + "\t的个数是:\t" + equals);
60 }
View Code

 

1.1.30  数组练习。编写一段程序,创建一个N×N 的布尔数组a[][]。其中当i 和j 互质时(没有相同因子),a[i][j] 为true,否则为false。

技术分享
 1 /**
 2  * 判断两数是否互质,若两数的最大公约数是1则两数互质
 3  * @param a
 4  * @param b
 5  * @return  若互质则true,否则false
 6  */
 7 private static boolean isCoprime(int a, int b) {
 8     for(int i = 2; i < Math.sqrt(a); ++i) {
 9         if(a % i == 0 && b % i == 0)
10             return false;
11     }
12     return true;
13 }
14 
15 /**
16  * 使用2300多年前的欧几里得算法求解两数的最大公约数
17  * @param p 数一
18  * @param q 数二
19  * @return  最大公约数
20  */
21 private static int gcd(int p, int q) {
22     if(q == 0)
23         return p;
24     int r = p % q;
25     return gcd(q, r);
26 }
27 
28 private static boolean[][] boolArray(int N) {
29     // 创建NxN的布尔二维数组
30     boolean[][] boolArr = new boolean[N][N];
31     for(int i = 1; i <= N; ++i)
32         for(int j = 1; j <= N; ++j)
33             if(1 == gcd(i, j))
34                 boolArr[i - 1][j - 1] = true;
35             else
36                 boolArr[i - 1][j - 1] = false;
37     return boolArr;
38 }
39 
40 public static void main(String[] args) {
41     int N = 5;
42     boolean[][] boolArr = boolArray(N);
43     for(int i = 0; i < N; ++i) {
44         for (int j = 0; j < N; ++j)
45             StdOut.print(boolArr[i][j] + "\t");
46         StdOut.println();
47     }
48 }
View Code

 

1.1.31  随机连接。编写一段程序,从命令行接受一个整数N 和double 值p(0 到1 之间)作为参数,在一个圆上画出大小为0.05 且间距相等的N 个点,然后将每对点按照概率p 用灰线连接。

技术分享
 1 /**
 2  * 画圆
 3  * @param x 圆心x坐标
 4  * @param y 圆心y坐标
 5  * @param r 半径r
 6  */
 7 private static void drawCircle(double x, double y, double r) {
 8     StdDraw.setXscale(0, 2 * x);
 9     StdDraw.setYscale(0, 2 * y);
10     StdDraw.setPenRadius(0.003);
11     StdDraw.setPenColor(StdDraw.BOOK_LIGHT_BLUE);
12     StdDraw.circle(x, y, r);
13 }
14 
15 /**
16  * 在圆上描点
17  * @param x0 圆心x坐标
18  * @param y0 圆心y坐标
19  * @param r 半径r
20  * @param N N个点
21  */
22 private static double[][] drawPoints(double x0, double y0, double r, int N) {
23     double[][] points = new double[N][2];
24     StdDraw.setPenRadius(0.005);
25     StdDraw.setPenColor(StdDraw.BOOK_RED);
26     for(int idx = 0; idx < N; ++idx) {
27         double x = x0 + r * Math.cos(2 * Math.PI * idx / N);
28         double y = y0 + r * Math.sin(2 * Math.PI * idx / N);
29         StdDraw.point(x, y);
30         points[idx][0] = x;
31         points[idx][1] = y;
32     }
33     return points;
34 }
35 
36 /**
37  * 以概率p随机连接顶点集points中的点
38  * @param points    点集
39  * @param p 概率p
40  */
41 private static void randomLinkPoints(double[][] points, double p) {
42     StdDraw.setPenRadius(0.002);
43     StdDraw.setPenColor(StdDraw.LIGHT_GRAY);
44     int length = points.length;
45     for(int i = 0; i < length; ++i)
46         for(int j = 0; j < length; ++j)
47             if(true == StdRandom.bernoulli(p))
48                 StdDraw.line(points[i][0], points[i][1], points[j][0], points[j][1]); // 应该再建立一个包含x坐标和y坐标的数据结构
49 }
50 
51 /**
52  * 在圆上画N个点然后每两点间以概率p连接
53  * @param N N个点
54  * @param p 概率p
55  */
56 private static void randomLink(int N, double p) {
57     double x = 10.0;
58     double y = 10.0;
59     double r = 9.0;
60     drawCircle(x, y, r);
61     double[][] points = drawPoints(x, y, r, N);
62     randomLinkPoints(points, p);
63 }
64 
65 public static void main(String[] args) {
66     randomLink(20, 0.2);
67 }
View Code

                                                                 技术分享



^_^

《算法:第四版》练习1.1部分答案

标签:

原文地址:http://www.cnblogs.com/gotodsp/p/4319865.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!