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])
);
}
}
}