算法(fourth edition)课后练习1.1

1.1.29 等值键

本质上是对于二分算法的拓展

这里默认数组为升序排列,找到中间值之后,只需满足“中间值”比“键值”小(大),中间的下(上)一个值比“键值”大(小),"中间值"与键值“相等”要考虑到值重复的情况,同时边界的问题也要考虑在内.

重复值的统计就相对来说简单一些,这里的思路是立足一点向前和向后统计累加,应该有更加优雅的解法.

// 返回小于键值的元素数量
public static int rankOfKey(int key, int[] a) {
        int lo = 0;
        int hi = a.length - 1;
        int mid = 0;
        while (lo <= hi) {
            mid = lo + (hi - lo) / 2;
            if (a[mid] < key) {
                lo = mid + 1;
                if (lo > hi || a[lo] > key) return lo;
            }
            else if (a[mid] > key) {
                hi = mid - 1;
                if (hi < 0)                 hi = 0;
                if (hi == 0 || a[hi] < key) return hi;
            }
            else {
                while (a[mid] == key)
                    if (mid > 0) mid--;
                    else         return 0;
                return mid + 1;
            }
        }
        return -1;
    }

    //返回等于该键值的数量
    public static int count(int key, int[] a) {
        int lo = 0;
        int hi = a.length - 1;
        int count = 0;
        int start;
        while (lo <= hi) {
            int mid = lo + (hi - lo) / 2;
            if (a[mid] < key) lo = mid + 1;
            else if (a[mid] > key) hi = mid - 1;
            else {
                count++;
                start = mid;
                while (mid < a.length - 1 && a[++mid] == key) count++;
                while (start > 0 && a[--start] == key) count++;
                return count;
            }
        }
        return 0;
    }

1.1.30 数组练习

判断i,j是否互质,创建数组并赋值,利用阿基米德算法来解决这个问题。

import edu.princeton.cs.algs4.StdOut;

public class ArraysPra {
    public static void main(String[] args) {
        Boolean[][] a = createArray(10);
        for (int i = 0; i < a.length - 1; i++) {
            for (int j = 0; j < a.length - 1; j++) {
                StdOut.println("i: " + i + " j: " + j + " " + a[i][j]);
            }
        }
    }

    public static Boolean[][] createArray(int n) {
        Boolean[][] a = new Boolean[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (i == 0 || j == 0) a[i][j] = true;
                else if (archimedes(i, j) <= 1) a[i][j] = true;
                else a[i][j] = false;
            }
        }
        return a;
    }

    // 阿基米德算法,求解最大公约数
    public static int archimedes(int m, int n) {
        // StdOut.println("m: " + m + " n: " + n);
        if (m % n == 0) return n;
        else return archimedes(n, m % n);
    }

}
    

1.1.31 随机连接

这里主要是熟悉api的调用,书中提到的绘图方法。(不过这熟悉的三角计算是怎么回事?)

import edu.princeton.cs.algs4.StdDraw;
import edu.princeton.cs.algs4.StdRandom;

import java.awt.Color;

public class Link {

    public static void randomConnection(int n, double p) {
        double r = 0.4;
        double x0 = 0.5;
        double y0 = 0.5;
        double angle = 360.0 / n;
        double[][] points = new double[n][2];
        StdDraw.setPenRadius(0.01);
        StdDraw.setPenColor(Color.gray);

        for (int i = 0; i < n; i++) {
            points[i][0] = x0 + r * Math.cos(angle * i * Math.PI / 180);
            points[i][1] = y0 + r * Math.sin(angle * i * Math.PI / 180);
            StdDraw.point(points[i][0], points[i][1]);
        }

        for (int i = 0; i < n - 1; i++) {
            for (int j = i + 1; j < n; j++) {
                if (StdRandom.bernoulli(p))
                    StdDraw.line(points[i][0], points[i][1], points[j][0], points[j][1]);
            }
        }

    }

    public static void main(String[] args) {
        if (args.length == 2) {
            randomConnection(
                    Integer.parseInt(args[0]),
                    Double.parseDouble(args[1])
            );
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章