拜读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);
    } 
}
       札记:还是经典算法转换到代码上的功夫问题,多练,别怕麻烦!




posted @ 2013-08-31 19:02  兔爷爱吃炸酱面  阅读(280)  评论(0编辑  收藏  举报