1.Java 程序的基本结构

image.png

2.原始数据类型与表达式

,+、-、 *、/ 都是被重载过的——根据上下文,同样的运算符对不 同类型会执行不同的操作

3.语句

4.简便记法

5.数组

声明、创建并初始化一个数组:

  1. // 完整模式:
  2. double[] a;
  3. a = new double[N];
  4. for (int i = 0; i < N; i++)
  5. a[i] = 0.0
  6. // 简化写法
  7. double[] a = new double[N];
  8. // 声明初始化
  9. int[] a = {1, 1, 2, 3, 5, 8};

使用数组

  1. // 数组中最大元素
  2. double max = a[0];
  3. for (int i = 1; i < a.length; i++) {
  4. if (a[i] > max) {
  5. max = a[i];
  6. }
  7. }
  8. // 数组平均值
  9. int N = a.length;
  10. double sum = 0.0;
  11. for(int i = 0; i < N; i++) {
  12. sum += a[i];
  13. }
  14. double average = sum / N;
  15. // 复制数组
  16. int N = a.length;
  17. double[] b = new double[N];
  18. for (int i = 0; i < N; i++) {
  19. b[i] = a[i];
  20. }
  21. // 反转数组
  22. int N = a.length;
  23. for (int i = 0; i < N/2; i++) {
  24. double temp = a[i];
  25. a[i] = a[N-1-i];
  26. a[N-i-1] = temp;
  27. }
  28. // 矩阵相乘 a[][] * b[][] = c[][]
  29. int N = a.length;
  30. double[][] c = new double[N][N];
  31. for (int i = 0; i < N; i++) {
  32. for (int j = 0; j < N; j ++) {
  33. // 计算 i行 和 j列 的点乘
  34. for (int k = 0; k < N; k++) {
  35. c[i][j] += a[i][k] * b[k][j];
  36. }
  37. }
  38. }

6.静态方法

典型静态方法的实现

  1. // 计算整数绝对值
  2. public static int abs(int x) {
  3. if (x < 0) return -x;
  4. else return x;
  5. }
  6. // 计算浮点数绝对值
  7. public static double abs(double x) {
  8. if (x < 0.0) return -x;
  9. else return x;
  10. }
  11. // 判断一个数是否是素数
  12. public static boolean isPrime(int N) {
  13. if (N < 2) return false;
  14. for (int i = 2; i * i <= N; i++) {
  15. if (N % i == 0)
  16. return false;
  17. return true;
  18. }
  19. }
  20. // 计算平方根(牛顿迭代法) NaN是Float,Double的一个成员常量,用来指示一个Float或Double不是合法的
  21. public static double sqrt(double c) {
  22. if (c < 0) return Double.NaN;
  23. double err = 1e-15;
  24. double t = c;
  25. while (Math.abs(t - c/t) > err * t)
  26. t = (c/t + t) / 2.0;
  27. return t;
  28. }
  29. // 已知直角三角形 垂直边 a, b 求斜边
  30. public static double hypotenuse(double a, double b) {
  31. return Math.sqrt(a*a + b*b);
  32. }
  33. // 计算调和级数
  34. public static double H(int N) {
  35. double sum = 0.0;
  36. for (int i = 1; i <= N; i++) {
  37. sum += 1.0 / i;
  38. }
  39. return sum;
  40. }

递归三条

  1. 递归总有一个最简单的情况—第一段语句就 return
  2. 递归调用总是常识解决 规模更小 的子问题。
  3. 递归调用的父问题和尝试解决的子问题之间没有交集。

举例:二分查找的递归实现

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) {
    // 如果 key 存在于 a[] 中,它的索引不会小于 lo 且不会大于 hi
    if (lo > hi) return -1;
    int mid = lo + (hi - lo) / 2;
    if (key < a[mid]) return rank(key, a, lo, mid - 1);
    else if (key > a[mid]) return rank(key, a, mid + 1, hi);
    else return mid;
}

练习

1.1.1

// (0 + 15) / 2
double result = (0.0 + 15) / 2;
// 2.0e-6 * 10000000.1
double result = 2.0e-6 * 10000000.1;
// true && false || true && true
boolean result = true && false || true && true;

1.1.2

// (1 + 2.2360) / 2
double result = (1 + 2.2360) / 2;   // 1.618
// 1 + 2 + 3 + 4.0
double result = 1 + 2 + 3 + 4.0;   // 10.0
// 4.1 >= 4
boolean result = 4.1 >= 4;   // true
// 1 + 2 + "3"
String result = 1 + 2 + "3";   // 33

1.1.3

int a = StdIn.readInt();
int b = StdIn.readInt();
int c = StdIn.readInt();
boolean result = a == b && b == c;
System.out.println(result);

1.1.4

a java 没有 then 关键字
b 条件语句要加括号
c 
d else 语句不能与 if 一行

1.1.5

public static void isInOne(double a, double b) {
    if (a > 0 && a < 1 && b > 0 && b < 1)
        System.out.println(true);
    else
        System.out.println(false);
}

1.1.6

0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610

1.1.7

a 3.00009
b 499500
c 10000

1.1.8

a b  // println(char x)
b 197  // 进行加法运算时 char 会被转为 int
c e  // int 强转 char

1.1.9

public static String toBinaryString(int N) {
    StringBuilder s = new StringBuilder();
    for (int n = N; n > 0; n /=2) {
        s.insert(0, (n % 2));
    }
    return s.toString();
}

1.1.10

先 new 分配内存

int[] a = new int[10];
for (int i = 0; i < 10; i++) {
    a[i] = i*i;
}
System.out.println(Arrays.toString(a));

1.1.11

public static void main(String[] args) {
    boolean[][] b = new boolean[][]{{true, false, false}, {true, true, true}};
    printBooleanMatrix(b);
}

public static void printBooleanMatrix(boolean[][] b) {
    for (boolean[] booleans : b) {
        for (boolean aBoolean : booleans) {
            System.out.print(aBoolean ? "* " : "  ");
        }
        System.out.println();
    }
}

1.1.12

作用域问题,只打印最后一个循环

1.1.13

public static int[][] transposeMatrix(int[][] matrix) {
    int rows = matrix.length;
    int cols = matrix[0].length;
    int[][] result = new int[cols][rows];
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            result[j][i] = matrix[i][j];
        }
    }
    return result;
}

1.1.14

public static int lg(int n) {
    int sum = 2;
    int result = 0;
    while (sum <= n) {
        result += 1;
        sum *= 2;
    }
    return result;
}

1.1.15

public static int[] histogram(int[] a, int m){
    int[] result = new int[m];
    for (int i = 0; i < m; i++) {
        int count = 0;
        for (int item : a) {
            if (item == i)
                count++;
        }
        result[i] = count;
    }
    return result;
}

1.1.16

返回字符串
311361142246

1.1.17

代码中的基础情况不会被调用返回,直至 StackOverflowError

1.1.18

50    33
65795 6574

1.1.19

斐波那契数列(Fibonacci sequence),又称黄金分割数列
结果是前两个数的和,所以保留前两个数结果就可以

public static void fibonacci(int n) {
    BigInteger[] container = new BigInteger[2];
    for (int i = 0; i < n; i++) {
        int index = i % 2;
        if (i < 2) {
            container[index] = BigInteger.valueOf(i);
        } else {
            container[index] = container[0].add(container[1]);
        }
        System.out.println(container[index]);
    }
}

1.1.20

基础编程模型 - 图2

public static double ln(int n) {
    if (n == 1) {
        return 0;
    }
    return Math.log(n) + ln(n-1);
}

1.1.21

public static void write() {
    int n = StdIn.readInt();
    String[] nameArray = new String[n];
    int[] intArray1 = new int[n];
    int[] intArray2 = new int[n];
    for (int i = 0; i < n; i ++){
        nameArray[i] = StdIn.readString();
        intArray1[i] = StdIn.readInt();
        intArray2[i] = StdIn.readInt();
    }
    System.out.println("| 姓名 | 语文 | 数学 |");
    for (int i = 0; i < n; i ++){
        System.out.println("| " + nameArray[i] + " | " + intArray1[i] + " | " + intArray2[i] + " |");
    }
}

1.1.22

public static int rank(int key, int[] a) {
        return rank(key, a, 0, a.length - 1, 0);
    }

public static int rank(int key, int[] a, int lo, int hi, int deep) {
    // 如果 key 存在于 a[] 中,它的索引不会小于 lo 且不会大于 hi
    System.out.println("lo: " + lo + ", hi: " + hi + ", deep: " + deep);
    if (lo > hi) return -1;
    int mid = lo + (hi - lo) / 2;
    if (key < a[mid]) return rank(key, a, lo, mid - 1, ++deep);
    else if (key > a[mid]) return rank(key, a, mid + 1, hi, ++deep);
    else return mid;
}

1.1.23

public static void main(String[] args) {
    int[] arr = {0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 44};
    int[] whiteList = {6, 7, 9, 10};
    String func = StdIn.readLine();
    for (int item : arr) {
        if (func.equals("+") && rank(item, whiteList) < 0) {
            StdOut.println(item);
        } else if (func.equals("-") && rank(item, whiteList) >= 0) {
            StdOut.println(item);
        }
    }
}

1.1.24

public static void main(String[] args) {
    StdOut.printf("gcd(105,24)=%d",gcd(105,24));
}

public static int gcd(int p,int q) {
    StdOut.printf("p=%d,q=%d\n",p,q);
    if (q==0) return p;
    int r=p % q;
    return gcd(q,r);
}
public class Euclid {
     public static void main(String[] args) {
         int p=Integer.parseInt(args[0]);
         int q=Integer.parseInt(args[1]);
        StdOut.printf("gcd("+Integer.toString(p)+","+Integer.toString(q)+")=%d",gcd(p,q));
    }
     public static int gcd(int p,int q) {
         StdOut.printf("p=%d,q=%d\n",p,q);
         if (q==0) return p;
         int r=p % q;
         return gcd(q,r);
     }
}

1.1.25

1) 基础步骤:求证gcd(p,q)=gcd(q,r)

证:令p=a*q+r,其中p、a、q、r均为非负整数。

设整数d|p、d|q,则d|(p-a*q),得p与q的公约数和q与r的公约数相同。

设整数d|q、d|r,则d|(a*q+r),得q与r的公约数和p与r的公约数相同。基于上述两点得gcd(p,q)=gcd(q,r)。

2) 归纳步骤:设有gcd(p,q)=gcd(q,r),求证gcd(q,r)=gcd(r, q%r)

证:由gcd(p,q)=gcd(q,r)可得d|p、d|q、d|r、p=a*q+r。

由于有q=⌊q/r⌋*r+q%r、d|q、d|r,所以有d|q%r所以有gcd(q,r)=gcd(r,q%r)。

提高题

1.1.26

前两句保证 a 位置最小
第三句保证 c 位置最大

1.1.27

二项分布
命中概率为 p,求 N 次,命中 k 次的概率

1.1.28

/**
* 获取有序数组去重后的数组长度,截取后即为去重数组
* @param a 有序数组
* @return 去重后的数组长度
*/
public static int removeDuplicates(int[] a) {
    if (a.length == 0) return 0;
    int j = 0;

    for (int i = 0; i < a.length; i++) {
        if (a[j] != a[i]) {
            a[++j] = a[i];
        }
    }
    return j + 1;
}

1.1.29

public static int rank(int key, int[] a) {
    int lower = 0;
    for (int item : a) {
        if (key > item) {
            lower++;
        }
    }
    return lower;
}

public static int count(int key, int[] a) {
    int equal = 0;
    for (int item : a) {
        if (key == item) {
            equal++;
        }
    }
    return equal;
}