拜读Robert Sedgewick的《算法 第4版》——1.1基础编程模型

       这一阵子,一直在学习算法,苦于能力有限,《算法导论》一时还难以消化,所以又买了一本Robert Sedgewick的《算法》拜读,这本书的风格比较适合我,而且讲解的比较容易懂,于是正在潜心地钻研。为了见证这一段学习过程,于是东施效颦,学着写博客记录下我学习算法的一些体会,以及对一些经典代码的整理,希望自己能够坚持下来!在学习本书的第一章时就有幸在网上看到了一些很好的博客,在此恭敬地呈上:http://www.cnblogs.com/viinye/category/430254.html,本文记录当中也有不少是借鉴此博客的,谨此说明,也以此作为一种激励,鞭策自己学得更好!

1.1基础编程模型


    ex1.1.3 从命令行得到三个整数参数。如果他们都相等则打印equal,否则打印not equal。

public class print {
	
    public static void main(String[] args)
    {
        int N1 = Integer.parseInt(args[0]);
        int N2 = Integer.parseInt(args[1]);
        int N3 = Integer.parseInt(args[2]);

        String Notification = "equal";
         if (N1 != N2) Notification = "not equal";
         if (N2 != N3) Notification = "not equal";
         System.out.println(Notification);
    }
}

     札记:这里主要说明在eclipse中如何输入args[]参数:选择Run→Run Configurations...→选中(x)=Arguments选项卡→在Program arguments输入框中输入1 1 1(中间空格隔开)。


     ex1.1.14 编写一个静态方法lg(),接受一个整型参数N,返回不大于log2N的最大整数。不使用Math库。

     

public class print {
    private static int lg(int N)
    {
        int product = 1;
        int x = -1;
        if (N < 1) throw new RuntimeException("Error, N should be larger than 0");
        else 
        while (product <= N) //*,把等于的情况也纳入进来,从而避免了在如23>5这种情况的自增导致输出结果为3的情况
        {
            product *= 2;
            x++;
        }

        return x;
    }
    
    public static void main(String args[])
    {
        int N = Integer.parseInt(args[0]);
        System.out.print(lg(N));
    }
}
      札记:这里不要拘泥于log2N,要根据具体问题转换思想。

      推演: log2N ≥ x

                2^(log2N) ≥ 2^x

                N ≥ 2^x;

      N为传入的参数,x为所求,于是乘以2是作为递变阶。


    ex1.1.15编写一个静态方法histogram(),接受一个整型数组a[]和一个整数M为参数并返回一个大小为M的数组,其中第i个元素为整数i在参数数组中出现的次数。如果a[]中的值均在0到M-1之间,返回数组中的所有元素之和应该和a.length相等。

public class print {
    private static int[] histogram(int a[] , int M){
    	if (M > a.length) System.out.println("We don't have enough data in the input array");
    	int R[]=new int[M];
    	int count;
    	for(int i=0;i<M;i++)
    	{
    		count=0;
    		for(int j=0;j<a.length;j++)
    		{
    			if(a[j]==i)
    			{
    				count++;
    			}
    		}
    		R[i]=count;
    	}
    	return R;
    }
    public static int sum(int R[]){
    	int sum=0;
    	for(int i=0;i<R.length;i++){
    		sum+=R[i];
    	}
    	for (int i = 0; i < R.length; i++)
            System.out.println("Value of element " + i + " is " + R[i]);
    	return sum;
    }
    
    public static void main(String args[])
    {
        int a[]={1,2,3,2,3,4,4,5,6};
        int M=7;
        int R[]=new int[M];
        R=histogram(a, M);
        System.out.print("返回数组中所有元素之和与a.length相等?"+(sum(R)==a.length));
    }
}

      札记:做好需求分析是最关键的一步!


   ex1.1.19 题中给了一个利用递归实现菲波纳契数列,要求开发一个更好的实现,用数组保存已经计算过的值

public class Fibonacci{
      
    public static long F(int N)
    {
        if (N == 0) return 0;
        if (N == 1) return 1;
        
        long[] f = new long[N+1];//'Cause we need to deal with f[N] and f[0], N+1 elements are necessary
        f[0] = 0;
        f[1] = 1;
        
        for (int i = 2; i <= N; i++)//i must calculate to N so that f[N] can be reached
        {
            f[i] = f[i-1] + f[i-2];
            
        }
        return f[N];
    }
     
    public static void main(String[] args)
    {
        for (int N = 0; N < 100; N++)
            StdOut.println(N + " " + F(N));
    }
}

      札记:经过改进后的算法效率提升明显。注意:数列增长速度很快,int类型以及不能很好的满足需求,宜采用long或大数据类型。


    ex1.1.20 编写一个递归的静态方法计算ln(N!)的值

public class Calln {
    
    private static double ln(int N)
    {
        int product = 1;
        if (N == 0) return 0;
        if (N == 1) return 1;
         
        for (int i = 2; i <= N; i++)
            product *= i ;
        return Math.log(product); //Don't know whether ln(N!) can be solved in this way. 
    }
    
    public static void main(String[] args)
    {
        int N = Integer.parseInt(args[0]);
        double value = ln(N);
        StdOut.print(value);
    }
}

      札记:在13行利用了Math.log函数库进行对数运算,如果不使用这个库应该如何处理?其实,以已经有了现成的直接用就行,不然下一个API,研究Math.log的具体内容;


    ex1.1.21 从标准输入按行读取数据,其中每行都包含一个名字和两个整数。然后用printf()打印一张表格,每行的若干列数据包括名字、两个整数和第一个整数除以第二个整数的结果,精确到小数点后三位。

public class StudentGrade {
    
     public static void main(String[] args)
     {
         //Read all data from Standard Input and store them in String s
         String[] s = StdIn.readStrings();
         
         //Deal with data by person
         int N = s.length / 3;
         for (int i = 0; i < N; i++)
         {
             String name = s[3*i];
             int mathGrade = Integer.parseInt(s[3*i+1]);
             int averageGrade = Integer.parseInt(s[3*i+2]);
             double percentage = (double)mathGrade / (double)averageGrade; //Pay attention to the conversion
             StdOut.printf("%s" + " | " + "%d" + " | " + "%d" + " | " + "%.3f\n", name, mathGrade, averageGrade, percentage); 
         }
     }
}

      札记:1.readStrings()的读取结果为字符串数组,凡是遇到空格或换行时自动创建新数组

               2. 异常 ArrayIndexOutOfBoundsException Thrown to indicate that an array has been accessed with an illegal index. The index is either negative or greater than or equal to the size of the array.

               3.整型除以整型结果仍为整型,即便是将结果赋值给double。必须先强制转换需要计算的整数。


     ex1.1.22 使用rank()递归方法重新实现BinarySearch并跟踪该方法的调用。每当该方法调用时,打印出它的从参数lo和hi,并按照递归的深度缩进。

public class ln {
    public static int i=0;
    public static int rank(int key , int[] a){
    	return rank( key , a , 0 , a.length-1 );
    }
    public static int rank(int key , int[] a ,int lo , int hi ){
    	//如果可以存在于a[]中,他的索引就不会小雨lo且不会大于hi
    	if(lo > hi) 
    	{
    		i++;
    		for(int j=0;j<i;j++)
    		{
    			System.out.print(" ");
    		}
    		System.out.print("lo="+lo+" hi="+hi);
    		return -1;
    	}
    	int mid = lo+(hi-lo)/2;
    	if( key < a[mid])
    	{
    		i++;
    		for(int j=0;j<i;j++)
    		{
    			System.out.print("-");
    		}
    		System.out.println("lo="+lo+" hi="+hi);
    		return rank(key , a , lo , mid-1);
    	}
    	else if(key > a[mid])
    	{
    		i++;
    		for(int j=0;j<i;j++)
    		{
    			System.out.print("-");
    		}
    		System.out.println("lo="+lo+" hi="+hi);
    		return rank(key , a , mid+1 , hi);
    	}
    	else
    	{
    		i++;
    		for(int j=0;j<i;j++)
    		{
    			System.out.print("-");
    		}
    		System.out.println("lo="+lo+" hi="+hi);
    		return mid;
    	}
    }
    public static void main(String args[]){
    	int a[]={1,2,3,4,5,6,7,8,9,10,11,12,13};
    	rank(2, a);
    }
}

      札记:经典的一些算法要谙熟其过程,可以整理好,方便以后使用或温习。


    ex1.1.23 为BinarySearch的测试用例添加一个参数:+打印出标准输入中不在白名单上的值;—则打印出标准输入中在白名单上的值

import java.util.Arrays;
public class BinarySearchNew {
    public static int rank(int key, int[] a)
    {
        int lo = 0;
        int hi = a.length -1;
        while (lo <= hi)
        {
            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;
    }
    public static void main(String[] args)
    {
        int[] whitelist = In.readInts(args[0]);
        String para = args[1]; //new parameter for determining whether to print values in the whitelist or not in the whihtlist
        Arrays.sort(whitelist);
        
        //ATTENTION: selective clause cannot be placed inside while loop
        //if the parameter is set as "+"
        if (para.equals("+"))
            while (!StdIn.isEmpty())
            {
                int key = StdIn.readInt();
                if (rank(key, whitelist) < 0)
                        StdOut.println(key);
                
            }
        
        //if the parameter is set as "-"
        else if (para.equals("-"))
            while (!StdIn.isEmpty())
            {
                int key = StdIn.readInt();
                if (rank(key, whitelist) > 0)
                        StdOut.println(key);
                
            }
    }
}

    ex1.1.24 从命令行接受两个参数,计算它们的最大公约数并打印出每次调用递归方法时的两个参数。

public class Euclid {
    
    private static int gcd(int p, int q)
    {
        System.out.println("p: " + p + ", q:" + q);
        if (q == 0) return p;
        int r = p % q;
        return gcd(q, r);
    }
     
    public static void main(String[] args)
    {
        int N1 = Integer.parseInt(args[0]);
        int N2 = Integer.parseInt(args[1]);
        int p = gcd(N1, N2);
        System.out.println("The largest common divisor is " + p);
    } 
}
       札记:还是经典算法转换到代码上的功夫问题,多练,别怕麻烦!




转载于:https://www.cnblogs.com/gitlinux/p/3885766.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编辑推荐  Sedgewick之巨著,与高德纳TAOCP一脉相承  几十年多次修订,经久不衰的畅销书  涵盖所有程序员必须掌握的50种算法 内容简介    《算法(第4)》全面讲述算法和数据结构的必备知识,具有以下几大特色。    1、 算法领域的经典参考书:Sedgewick畅销著作的*,反映了经过几十年演化而成的算法核心知识体系    2、内容全面:全面论述排序、搜索、图处理和字符串处理的算法和数据结构,涵盖每位程序员应知应会的50种算法    3、全新修订的代码:全新的Java实现代码,采用模块化的编程风格,所有代码均可供读者使用    4、与实际应用相结合:在重要的科学、工程和商业应用环境下探讨算法,给出了算法的实际代码,而非同类著作常用的伪代码   5、富于智力趣味性:简明扼要的内容,用丰富的视觉元素展示的示例,精心设计的代码,详尽的历史和科学背景知识,各种难度的练习,这一切都将使读者手不释卷    6、科学的方法:用合适的数学模型精确地讨论算法性能,这些模型是在真实环境中得到验证的   7、与网络相结合:配套网站algs4.cs.princeton.edu提供了本书内容的摘要及相关的代码、测试数据、编程练习、教学课件等资源 作者简介    Robert Sedgewick,斯坦福大学博士,导师为Donald E.Knuth,从1985年开始一直担任普林斯顿大学计算机科学系教授,曾任该系主任,也是AdobeSystems公司董事会成员,曾在Xerox PARC、国防分析研究所(Institute for DefenseAnalyses)和法国国家信息与自动化研究所(INRIA)从事研究工作。他的研究方向包括解析组合学、数据结构和算法的分析与设计、程序可视化等。    KevinWayne,康奈尔大学博士,普林斯顿大学计算机科学系高级讲师,研究方向包括算法的设计、分析和实现,特别是图和离散优化。 目  录 第1章  基础 1.1 基础编程模型 1.1.1 Java程序的基本结构 1.1.2 原始数据类型与表达式 1.1.3  语句 1.1.4  简便记法 1.1.5  数组 1.1.6  静态方法 1.1.7  API 1.1.8  字符串 1.1.9  输入输出 1.1.10  二分查找 1.1.11  展望 1.2  数据抽象 1.2.1  使用抽象数据类型 1.2.2  抽象数据类型举例 1.2.3  抽象数据类型的实现 1.2.4  更多抽象数据类型的实现 1.2.5  数据类型的设计 1.3  背包、队列和栈 1.3.1  API 1.3.2  集合类数据类型的实现 1.3.3  链表 1.3.4  综述 1.4  算法分析 1.4.1  科学方法 1.4.2  观察 1.4.3  数学模型 1.4.4  增长数量级的分类 1.4.5  设计更快的算法 1.4.6  倍率实验 1.4.7  注意事项 1.4.8  处理对于输入的依赖 1.4.9  内存 1.4.10  展望 1.5  案例研究:union-find算法 1.5.1  动态连通性 1.5.2  实现 1.5.3  展望 第2章  排序 2.1  初级排序算法 2.1.1  游戏规则 2.1.2  选择排序 2.1.3  插入排序 2.1.4  排序算法的可视化 2.1.5  比较两种排序算法 2.1.6  希尔排序 2.2  归并排序 2.2.1  原地归并的抽象方法 2.2.2  自顶向下的归并排序 2.2.3  自底向上的归并排序 2.2.4  排序算法的复杂度 2.3  快速排序 2.3.1  基本算法 2.3.2  性能特点 2.3.3  算法改进 2.4  优先队列 2.4.1  API 2.4.2  初级实现 2.4.3  堆的定义 2.4.4  堆的算法 2.4.5  堆排序 2.5  应用 2.5.1  将各种数据排序 2.5.2  我应该使用哪种排序算法 2.5.3  问题的归约 2.5.4  排序应用一览 第3章 查找 3.1 符号表 3.1.1 API 3.1.2 有序符号表 3.1.3 用例举例 3.1.4 无序链表中的顺序查找 3.1.5 有序数组中的二分查找 3.1.6 对二分查找的分析 3.1.7 预览 3.2 二叉查找树 3.2.1 基本实现 3.2.2 分析 3.2.3 有序性相关的方法与删除操作 3.3 平衡查找树 3.3.1 2-3查找树 3.3.2 红黑二叉查找树 3.3.3 实现 3.3.4 删除操作 3.3.5 红黑树的性质 3.4 散列表 3.4.1 散列函数 3.4.2 基于拉链法的散列表 3.4.3 基于线性探测法的散列表 3.4.4 调整数组大小 3.4.5 内存使用 3.5 应用 3.5.1 我应该使用符号表的哪种实现 3.5.2 集合的API 3.5.3 字典类用例 3.5.4 索引类用例 3.5.5 稀疏向量 第4章  图 4.1  无向图 4.1.1  术语表 4.1.2  表示无向图的数据类型 4.1.3  深度优先搜索 4.1.4  寻找路径 4.1.5  广度优先搜索 4.1.6  连通分量 4.1.7  符号图 4.1.8  总结 4.2  有向图 4.2.1  术语 4.2.2  有向图的数据类型 4.2.3  有向图中的可达性 4.2.4  环和有向无环图 4.2.5  有向图中的强连通性 4.2.6  总结 4.3  最小生成树 4.3.1  原理 4.3.2  加权无向图的数据类型 4.3.3  最小生成树的API和测试用例 4.3.4  Prim算法 4.3.5  Prim算法的即时实现 4.3.6  Kruskal算法 4.3.7  展望 4.4  最短路径 4.4.1  最短路径的性质 4.4.2  加权有向图的数据结构 4.4.3  最短路径算法的理论基础 4.4.4  Dijkstra算法 4.4.5  无环加权有向图中的最短路径算法 4.4.6  一般加权有向图中的最短路径问题 4.4.7  展望 第5章  字符串 5.1  字符串排序 5.1.1  键索引计数法 5.1.2  低位优先的字符串排序 5.1.3  高位优先的字符串排序 5.1.4  三向字符串快速排序 5.1.5  字符串排序算法的选择 5.2  单词查找树 5.2.1  单词查找树 5.2.2  单词查找树的性质 5.2.3  三向单词查找树 5.2.4  三向单词查找树的性质 5.2.5  应该使用字符串符号表的哪种实现 5.3  子字符串查找 5.3.1  历史简介 5.3.2  暴力子字符串查找算法 5.3.3  Knuth-Morris-Pratt子字符串查找算法 5.3.4  Boyer-Moore字符串查找算法 5.3.5  Rabin-Karp指纹字符串查找算法 5.3.6  总结 5.4  正则表达式 5.4.1  使用正则表达式描述模式 5.4.2  缩略写法 5.4.3  正则表达式的实际应用 5.4.4  非确定有限状态自动机 5.4.5  模拟NFA的运行 5.4.6  构造与正则表达式对应的 5.5  数据压缩 5.5.1  游戏规则 5.5.2  读写二进制数据 5.5.3  局限 5.5.4  热身运动:基因组 5.5.5  游程编码 5.5.6  霍夫曼压缩 第6章  背景 索引
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值