---
# System prepended metadata

title: Lecture 02 - Analysis of Algorithms
tags: [課堂筆記, 演算法]

---

# Lecture 02 - Analysis of Algorithms
> 課程內容 : 中興大學資工系 范耀中教授 (112 學年度第 2 學期)
>
> 其他科目內容請參見 [[Here]](https://hackmd.io/@ChenZE/By4SOO6Jyl)

## 1. Example problem : 3-Sum problem 

### 1.1 Problem scription :question:
> **Question**
>
> Given N **distinct** integers, how many triples sum to exactly zero ?

For example, an 8 elements array, `arr = [30, -40, -20, -10, 40, 0, 10, 5]`
| Numbers | a[i] | a[j] | a[k] | sum |
| :-:     | :-:  | :-:  | :-:  | :-: |
| 1       | 30   | -40  | 10   | 0   |
| 2       | 30   | -20  | -10  | 0   |
| 3       | -40  | 40   | 0    | 0   |
| 4       | -10  | 0    | 10   | 0   |

---

### 1.2 Brute-force algorithm (暴力解)
```java=
// Java code for 3-Sum problem
public class TreeSum
{
    
    public static int count(int[] a)
    {
        int N = a.length;
        int count = 0;
        for (int i=0; i < N; i++)
            for (int j=i+1; j<N; j++)
                for (int k=j+1; k<N; k++)
                    if (a[i]+a[j]+a[k] == 0)
                        count++;
        return count;
    }
    
    public static void main(String[] args)
    {
        In in = new Ina(args[0]);
        int[] a = in.readAllInts();
        StdOut.printIn(coint(a));
    }
}
```

**<font color="FF0000">:warning: 任何專業的程式碼都不該出現三3個以上的巢狀迴圈 (垃圾程式碼)</font>**

## 2. Order-of growth classifications
### 2.1 How long does the following algorithm take ?
考慮以下程式碼，當輸入長度為 N 時的指令次數
```java=
int count = 0;

for (int i=0; i<N; i++)
    for (int j=i+1; j<N; j++)
        if (a[i]+a[j]==0)
            count++;
```
* **variavle decalration : $N+2$ times**
    * `count = 0` : 1 times
    * `int i = 0` : 1 times
    * `int j = i + 1` : N times, for 1 to N

* **assignment : $N+2$ times (why:question:)**

* less than compare : $\cfrac{1}{2} (N+1)(N+2)$ times
    * `i < N` : $N+1$ times, where 0 to N
    * `j < N` : $N+(N-1)+...+1=\cfrac{N(N+1)}{2}$
    * Total : $(N+1)+\cfrac{N(N+1)}{2}=\cfrac{1}{2}(N+1)(N+2)$

* equal to compare : $\cfrac{1}{2}N(N-1)$ times
    * `a[i][j] == 0` : $(N-1)+...+1=\cfrac{N(N-1)}{2}$

* array access : $N(N-1)$ times
    * `a[i]` : $(N-1)+...+1=\cfrac{N(N-1)}{2}$
    * `a[j]` : $(N-1)+...+1=\cfrac{N(N-1)}{2}$
    * Total : $N(N-1)$

大部分的效能分析太冗長，只要專注在前兩項(粗體字部分)即可
以`if`敘述來說，總共執行了$(N-1)+N+...+1=\cfrac{N(N-1)}{2}$次，可視為==從 N 個數字中挑出兩個==，即$(^n_2)$

---

### 2.2 Common order of growth classification
> **Definition**
>
> If $T(N)\sim c\cdot g(N)$ for some constant $c>0$, then the order of growth of $T(N)$ is $g(N)$
> 
以3-sum problem來說，問題複雜度是 $N^3$ ，意義在於==從 N 個元素中任選三個==

常用的演算法複雜度如下 : ==$1$、$\log N$、$N$、$N\log N$==、$N^2$、$N^3$、$2^N$

其中前 4 個是**可以接受**的範圍，==$N^2$、$N^3$ 不該出現在專業程式中==，$2^N$僅限在測試中
> **Example for $2^N$**
>
> $S=\{A, B, C, D, E\}$，挑選**任意長度**的子集的和

以編碼角度來看，子集$\{B\}=(0, 1, 0, 0, 0)$，子集$\{C\}=(0, 1, 1, 0, 0)$，所以共有 $2^5$ 個子集


## 3. Doubling hypothesis
### 3.1 About software performance understanding
* 黑箱測試(black box testing) : 看不到程式碼內部的邏輯(Ex: API)
* 白相測試(white box testing) : 看得到程式碼內部的邏輯

![image](https://hackmd.io/_uploads/SkAZxWTgC.png)

---

### 3.2 Data analysis
標準方式畫圖，將時間複雜度依照不同輸入長度畫圖，**觀察圖形**
![image](https://hackmd.io/_uploads/S1aDlZalC.png)

---

### 3.3 Double hypothesis
==將input size放大兩倍，觀察程式執行的效能變化==

Supposed that complexity : $T(N)=a \times N^b =T(N)$ , thus we have

$T_1(N)=a\times N^b$ and $T_2(N)=a \times (2N)^b$

Then, $\cfrac{T_2(N)}{T_1(N)}=\cfrac{a \times (2N)^b}{a \times (N)^b}=2^b$

由此可求出 $b$ 之值，代回後可再求得 $a$ 之值，但 ==$\log N$ 規模可能不適用==

## 4. Theory of algorithm
已知演算法的複雜度為 : 

$N^3 \rightarrow N^2\cdot \log N \rightarrow N^2 \rightarrow N \cdot \log N \rightarrow N \rightarrow \log N \rightarrow 1$

如何知道==針對某問題的演算法已經是最好的 ?==

### 4.1 Types of analysis

* Best case
    * **最簡單**的 input
    * 提供所有的input一個**目標解**
* Worst case
    * **最難的** input
    * 提供所有的input一個**保證解**
* Average case
    * 針對**隨機** input
:::info
此處主要聚焦在**Worst case**的討論
:::

---

### 4.2 Theory of algorithm
演算法理論的目標有二個 : 
1. 建立問題的**困難度**
2. 發展**最佳**的演算法

在此條件下衍生兩個邊界值 : ==Upper bound==，表示**最差 input** 之下所執行的狀況與結果；==Lower bound==，表示**最簡單 input** 之下所執行的狀況與結果。

<font color="F0000">**注意**</font>，其實 ==Lower bound 本身**不包含**演算法的概念==，他指的是**任何人來解問題時都必須付出的成本**。例如 : 

> **Find zero elements in array whose size = N**

此問題的 Lower bound = $N$，因為不論是誰來解決此問題，都必須將**整個 array 看過一次**才可以執行後續的步驟

演算法開發的方式有二個方向 : 
1. 將**Upper bound下壓**
2. 將**Lower bound上抬**

當 Upper bound = Lower bound ==(同一規模)== 時，就可以說此演算法是最好的。但實際上將 Lower bound 上抬的過程比較**困難**，需要**嚴謹的數學證明**，所以一般都是==開發新的演算法==將 Upper bound**下壓**，而 Upper bound 下壓的過程就是 optimize




