1.1 看这本书的目的
个人目前观点,这本书的意义在于,实现一个功能是必要的,实现一个高性能的功能也是非常重要的,在大量输入下,如果解决不了性能问题,那么“正确”的程序也会变成错误的
1.2 数学知识复习
1.2.1 指数
几个指数公式:
- X A X^A XA X B X^B XB = X A + B X^{A + B} XA+B
- X A X B \frac{X^A}{X^B} XBXA = X A − B X^{A - B} XA−B
- ( X A ) B (X^A)^B (XA)B = X A B X^{AB} XAB
- ( 2 N ) (2^N) (2N) + ( 2 N ) (2^N) (2N) = 2 N + 1 2^{N + 1} 2N+1
- X N X^N XN + X N X^N XN = 2 X N X^N XN
1.2.2 对数
注意:在计算机科学中,除非有特别的说明,否则所有的对数都是以2为底的。
对数的定义:
X
A
X^A
XA = B 当且仅当
log
X
B
\log_XB
logXB = A
对数的几个定理:
- log A B \log_AB logAB = log C B log C A \frac{\log_CB}{\log_CA} logCAlogCB; (A、B、C > 0, A ≠ 1 A\not=1 A=1)
- log A B \log{AB} logAB = log A \log{A} logA + log B \log{B} logB; (A、B > 0)
- log A B \log{A}^B logAB = B log B \log{B} logB; (A > 0)
1.2.3 级数
概念:就是将数列的项依次用加号连接起来的函数,其实就是数列的和。
附:
- 等差数列的求和公式: S n S_n Sn = n a 1 na_1 na1 + n ( n − 1 ) 2 d \frac{n(n-1)}{2}d 2n(n−1)d
- 等比数列的求和公式: S n S_n Sn = a 1 ( 1 − q n ) 1 − q \frac{a_1(1-q^n)}{1-q} 1−qa1(1−qn)
最简单的一个级数:
- ∑ i = 0 N 2 i \sum_{i=0}^N {2^i} ∑i=0N2i = 2 i + 1 2^{i+1} 2i+1 - 1
1.2.4 模运算
定义: 如果N整除A - B,那么说A与B模N同余,记为 A ≡ B ( m o d N ) A\equiv B(modN) A≡B(modN), 换句话说就是无论是A还是B被N整除,所得的余数都是相同的。。例如 92 ≡ 62 ≡ 2 ( m o d 10 ) 92 \equiv 62\equiv 2(mod10) 92≡62≡2(mod10)
1.2.5 证明的方法
(1)归纳证明法
步骤:第一步是证明基准情形,第二步是归纳假设
例子:菲波那切数
F
k
+
2
=
F
k
+
1
+
F
k
F_{k+2} = F_{k+1} + F_k
Fk+2=Fk+1+Fk,
F
0
=
1
F_0 = 1
F0=1,
F
1
=
1
F_1 = 1
F1=1,
F
2
=
2
F_2 = 2
F2=2,
F
3
=
3
F_3 = 3
F3=3,
F
4
=
5
F_4 = 5
F4=5,‘…,
证明:
F
k
+
1
<
(
5
3
)
k
+
1
F_{k+1}<({\frac{5}{3}})^{k+1}
Fk+1<(35)k+1
(2)反证法证明
反证法证明就是通过假设定理不成立,然后证明该假设导致的某个已知的性质不成立,从而原假设是错误的。一个经典的例子就是证明存在无穷多个素数。为了证明这个结论,假设定理不成立。于是,就会有一个结论,存在某个最大的素数
P
k
P_k
Pk. 另所有的素数
P
1
P_1
P1,
P
2
P_2
P2,
P
3
P_3
P3,
P
4
P_4
P4,…,
P
k
P_k
Pk 依次排列,另 N =
P
1
P_1
P1
P
2
P_2
P2
P
3
P_3
P3
P
4
P_4
P4…
P
k
P_k
Pk+ 1,很明显N是一个比
P
k
P_k
Pk大的素数,因为存在定理,一个整数要么是素数,要么是素数的乘积,由此可见N显然是素数。
1.3 递归简论
递归的四条基本法则:
(1)基准情形: 必须要有某些基准情形,它不通过递归调用就能运行通过。
(2)不断推进:对于需要递归求解的情形,每一次递归调用都必须要使状况朝向一种基准情形推进。
(3)设计法则:假设所有的递归调用都能运行。
(4)合成效益法则:在求解一个问题的同一个实例时,切勿在不通的递归调用中重复同样的工作。例如,求解菲波那切数时,直接使用递归调用
F
k
+
1
+
F
k
F_{k+1} + F_{k}
Fk+1+Fk 求解值,便做了很多重复的工作。
1.4 java 泛型
什么时候使用泛型?当求解一个问题,除去对象的基本类型之外,实现方法是相同的,那么就可以使用泛型。
问题
- 选择问题,求出一组数中第k个最大的值。
思路:直接对数组进行逆序排序,然后取出数组中第 k - 1个值。
实现代码:
public class SelectProblem{
public static void main(String[] args) {
Integer[] arr = {12,14,16,4,7,8,10};
sortArray(arr);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
public static void sortArray (Integer [] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
Integer temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
}
- 问题二,定义一个Rectangle类,该类提供getLength()和getWidth() 方法,定义一个main方法,该方法创建一个Rectangle数组并且首先找到数组中依面积最大的对象,然后再找出依周长最大的对象。
第一步,先创建一个Rectangle类
public class Rectangle {
private double length;
private double width;
public Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
}
第二步,重写一个comparable类
public class CompareRectangle implements Comparable<Rectangle>{
@Override
public int compareTo(Rectangle o) {
return 0;
}
public int compareArea(Rectangle o1, Rectangle o2) {
if (o1.getLength() * o1.getWidth() > o2.getLength() * o2.getWidth()) {
return 1;
} else {
return 0;
}
}
public int comparePerimeter(Rectangle o1, Rectangle o2) {
if ((o1.getLength() + o1.getWidth()) * 2 > (o2.getLength() + o2.getWidth()) * 2) {
return 1;
} else {
return 0;
}
}
}
第三步,实现方法
public class FindMaxProgram {
public static Rectangle findMaxArea(Rectangle [] arr, CompareRectangle cmp)
{
int max = 0;
for (int i = 1; i < arr.length; i ++ ) {
if (cmp.compareArea(arr[i - 1], arr[i]) < 1)
{
max = i;
}
}
return arr[max];
}
public static Rectangle findMaxPerimeter(Rectangle [] arr, CompareRectangle cmp)
{
int max = 0;
for (int i = 1; i < arr.length; i ++ ) {
if (cmp.comparePerimeter(arr[i - 1], arr[i]) < 1)
{
max = i;
}
}
return arr[max];
}
public static void main(String[] args) {
Rectangle[] arr = {
new Rectangle(1,1),
new Rectangle(1,2),
new Rectangle(1,3),
new Rectangle(2,2),
new Rectangle(2,3),
new Rectangle(3,3),
new Rectangle(2,7),
new Rectangle(4,4)
};
Rectangle maxArea = findMaxArea(arr, new CompareRectangle());
Rectangle maxPerimeter = findMaxPerimeter(arr, new CompareRectangle());
}
}