lazybear d(`・∀・)b
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    [TOC] # 第一章 ## long long - `long long ll = 123456789LL;` ## IO - 用來加快IO ```c++ ios::sync_with_stdio(0); cin.tie(0); //解除cin、cout綁定 ``` # 第二章 ## 求Maximum subarray sum - p.33 - $O(n)$ ```c++= int arr[]= { -1, 2, 4, ..., -5, ...}; int sum = 0; int best = 0; for(int i=0; i < k; i++){ //取 -1 [2 4 ...] -5 //這樣就不會取到 [-1 2 4 ...],可以避免加到-1 sum = max(arr[i], sum + arr[i]); best = max(best, sum); } ``` # 第三章 Sorting ## Binary Search - p.32 - $O(log(n))$ - b為移動長度,每次移動$\frac{n}{2^i}$,i=1,直到b == 1 ```c++= int k = 0; for(int b = n / 2; b >= 1;b /= 2){ while(k + b < n && arr[k + b] <= x) k += b; //向右移動 } if(arr[k] == x) cout<<"Find\n"; ``` ## Maximum value - $f(x) < f(x+1)$ when $x<k$ - Increasing - $f(x) > f(x+1)$ when $x\ge k$ - Decreasing - 此時k為該區域最大值 - :arrow_right: $f(x+1)$為最大值 :arrow_right: $x$ 需加一 ```c++= int x = -1; for(int b = n; b >= 1; b /= 2){ while(x + b + 1 < n && a[x + b] < a[x + b + 1]) x += b; } cout<<a[x + 1]<<endl; ``` # 第五章 -- Complete Search ## 產生所有Subset - 兩種方法 - recursive - bit operation ### recursive - 左邊 :arrow_right: 不會將k納入 - 右邊 :arrow_right: 將k納入 - k從0開始,n為3 - 印出0~2的subset ![image](https://hackmd.io/_uploads/B1Wmk8jaT.png =95%x) :::spoiler Code ```c++= vector<int> nums; void recursive(int k, int n) { if (k == n) { //當達到目的 -> 印出來 for (auto x : nums) cout << x << " "; cout << endl; return; } recursive(k + 1, n); //左邊 -> 不會將k納入 nums.push_back(k); //納入 recursive(k + 1, n); //右邊 -> 會將k納入 nums.pop_back(); //回復狀態 } ``` ::: ### bit operation - 遍歷$0$~$2^n-1$ - 使用`1<<n` - Example ~這邊順序是由右到左~ - 5 -> `101` -> `{0,2}` - 3 -> `011` -> `{0,1}` :::spoiler Code ```c++= int n = 3; for (int i = 0; i < (1 << n); i++) { //產生0~2^n-1 for (int j = 0; j < n; j++) { //一個一個bit檢查 if (i&(1 << j)) cout << j << ' '; } //檢查是否第j位是否有值 cout << endl; } ``` ::: ## permutation - Recurisve - function ### Recurisve :::spoiler Code ```c++= int n = 3; vector<int> num; vector<bool> che(n); void recur() { if (num.size() == n) { //陣列滿了 -> 印 for (auto x : num) cout << x << " "; cout << endl; return; } for (int i = 0; i < n; i++) { if (che[i]) continue; //如果有在陣列 -> 跳過 //把他加入陣列 che[i] = true; num.push_back(i); //recursive recur(); //跑回來時,已經不需要 -> pop掉 che[i] = false; num.pop_back(); } } ``` ::: ### next_permutation - `<algorithm>` - return value - 好了 :arrow_right: false - `next_permutation(v.begin(), v.end())` - 補充 - `prev_permutation(v.begin(), v.end())` ```c++= do{ //do something } while(next_permutation(v.begin(), v.end())); ``` - `next_permutation`原理 - [參考](https://www.cnblogs.com/eudiwffe/p/6260699.html) :::spoiler C語言pointer版本(方便理解) ```c++= // STL next permutation base idea int next_permutation(int *begin, int *end) { int *i=begin, *j, *k; // 沒有東西 or 只有一個 不用做 if (i==end || ++i==end) return 0; // 0 or 1 element, no next permutation for (i=end-1; i!=begin;) { j = i--; // find last increasing pair (i,j) if (!(*i < *j)) continue; //找到離end最近 && 大於等於i 的元素 for (k=end; !(*i < *(--k));); iter_swap(i,k); //交換 // now the range [j,end) is in descending order reverse(j,end); return 1; } // current is in descending order reverse(begin,end); return 0; } ``` ::: ## Queen - 規則 - 不能同一個column、斜對角 - 需要三個vector紀錄 - column、左斜對角、右斜對角 ![image](https://hackmd.io/_uploads/rk4ESPhTp.png =80%x) :::spoiler Code ```c++= #define N 4 int cou = 0; vector<bool> col(N); vector<bool> l_r(N * 2 - 1); vector<bool> r_l(N * 2 - 1); void queen(int y, int n) { if (y == n) { //已達方法 cou++; return; } for (int i = 0; i < n; i++) { if (col[i] | l_r[(n - 1) - y + i] | r_l[y + i]) continue; //若該位置已有人 col[i] = l_r[(n - 1) - y + i] = r_l[y + i] = 1; //放置 queen(y + 1, n); col[i] = l_r[(n - 1) - y + i] = r_l[y + i] = 0; //拿起來 } } ``` ::: ## Meet in the middle - [Reference Video](https://youtu.be/naz_9njI0I0?si=1XWdPQKKjs_NCndI) - `[2,4,5,9]` 目標 = 15 - 先拆分成`[2,4]`、`[5,9]` - 擴展成`a = [0,2,4,6]`、`b = [0,5,9,14]` - 須將<font color=red>b做sort</font>,方便之後找可以用<font color=red>Binary Search</font> - 算 $目標 - a_i = x$,算$max(x_i \subset b \wedge x_i \le x)$,再將$ans = max(a_i + x_i)$ - 先選`0`,15 - 0 = 15,選擇$\{x_i|x_i\subset b \wedge x_i \le 15\} = 14$,$14 + 0 = 15$ - 選`2`,15 - 2 = 13,選擇$\{x_i|x_i\subset b \wedge x_i \le 13\} = 9$,$9 + 2 = 11$ - 選`4`,15 - 4 = 11,選擇$\{x_i|x_i\subset b \wedge x_i \le 11\} = 9$,$9 + 4 = 13$ - 選`6`,15 - 6 = 9,選擇$\{x_i|x_i\subset b \wedge x_i \le 9\} = 9$,$9 + 6 = 15$ - $\because \ 15 == 15$,所以有找到 - $O(Nlog(2^{N/2}))$ - Generate + Sort + Search - $2^{n/2}$ + $2^{n/2}$ + $\cfrac{N}{2}2^{n/2}$ + $\cfrac{N}{2}2^{n/2}$ - Search : $\frac{N}{2}$(a有$\frac{N}{2}個$) $\times$ $2^{N/2}$(BS) - [Leetcode](https://leetcode.com/problems/closest-subsequence-sum) :no_entry: # 第六章 -- Greedy ## Scheduling - [LeetCode](https://leetcode.com/problems/maximum-length-of-pair-chain/) - 先將<font color=red>end time</font>做sort,由小到大 - 選擇`arr[0]` - 選擇時間不會卡到 && end time最近~不用太考慮這點~,重複此動作 ## Job Sequencing Problem - [參考](https://www.geeksforgeeks.org/job-sequencing-problem/) - 敘述 - 有N組`{deadline,profit}`的工作,若超時了就<font color=red>獲得不到</font>profit - 求最大利益 - 方法 - 先<font color=red>sort</font>,依照<font color=red>profit遞減</font> - 陣列`slop`去記錄當天**是否有工作** - 陣列`result`紀錄當天是甚麼工作 - [題目](https://www.geeksforgeeks.org/problems/job-sequencing-problem-1587115620/1) :::spoiler Code ```c++= /* struct Job { int id; // Job Id int dead; // Deadline of job int profit; // Profit if job is over before or on deadline }; */ class Solution { public: static bool cmp(Job a, Job b){ return a.profit > b.profit; } vector<int> JobScheduling(Job arr[], int n) { vector<bool> slop(n); //記錄當天是否有工作 vector<int> result(n); //紀錄當天是甚麼工作 int ans_n = 0, ans_pro = 0; sort(arr,arr+n,cmp); for(int i=0;i<n;i++){ for(int j=min(n,arr[i].dead)-1; j>=0; j--){ if(slop[j] == false){ //那天沒工作 slop[j] = true; result[j] = i; break; //因為有工作了所以不用再看 } } } //紀錄結果 for(int i=0;i<n;i++){ if(slop[i]){ ans_n++; ans_pro += arr[result[i]].profit; } } vector<int> ans = {ans_n,ans_pro}; return ans; } }; ``` ::: # 第七章 -- DP - 要訣 - sort - Visualization - two sequence -> use matrix ## Coin Problem - 概念based recursive,寫法based **iterative** - $O(nk)$ - n : 目標值(amount) - k : coins量 - $solve(0) = 0$ - $solve(10)=solve(7)+1=solve(4)+2=solve(0)+3=3$ - 若10\$從$\{1,3,4\}$中找零錢 - 10 = 3 + 3 + 4 - [LeetCode](https://leetcode.com/problems/coin-change) :::spoiler Code ```c++= int amount = 17; vector<unsigned int> value(amount + 1,INT_MAX); vector<int> first(amount + 1); vector<int> coins = { 1,2,5 }; //記錄錢數量 value[0] = 0; //代表0$時,找0個硬幣 for(int i = 1; i <= amount; i++){ for(auto c:coins){ //代表i$扣掉硬幣c時,相較原本i$有更佳解 if(i - c >= 0 && value[i - c] + 1 < value[i]){ value[i] = value[i - c] + 1; //更新 first[i] = c; //紀錄第一個 -> 之後再靠first[i-c]回推 } } } if(value[amount] == INT_MAX) //當無法找錢時 cout<<"Can't\n"; else cout<<value[amount]<<endl; //若要印出組成 int tmp = amount; while(tmp >= 0 && first[tmp]){ cout<<first[tmp]<<" "; tmp -= first[tmp]; } ``` ::: :::spoiler 概念圖 - coins = {1,2,3} ![](https://www.simplilearn.com/ice9/free_resources_article_thumb/Coin%20Change%20Problem%20-%20soni/dynamic-programming-solution-using-coin-change-problem.png =70%x) ::: ### 延伸 -- Numbers of Coin Problem - 問題 - 有1$、3\$、4\$,請問幾種支付4$的方式? - 4 = 1+1+1+1 = 1+3 = 3+1 = 4 - <font color=red>找出<b>所有</b>的組合,包含<b>重複</b>的組和</font> - 與之前差別就是會將前c個的值加起來,而非取最小 :::spoiler Code ![430173144_920485866398202_646279089911462634_n](https://hackmd.io/_uploads/BkEn5MeT6.jpg =50%x) ```c++= int amount = 2; vector<int> count(amount + 1); vector<int> coins = { 1,3,4 }; count[0] = 1; for (int i = 1; i <= amount; i++) { //蒐集1~amount的problem組合 for (auto c : coins) { //每種problem的前c答案 if (i - c >= 0) count[i] += count[i - c]; } } if (count[amount] == 0) //找不到 cout << "Can't" << endl; else //找到 cout << count[amount] << endl; ``` ::: --- - 問題 - 有1$、3\$、4\$,請問幾種支付4$的方式? - 4 = 1+1+1+1 = 1+3 = 4 - <font color=red>只考慮了在<b>該金額之前</b>的硬幣組合,而<b>不會</b>重複考慮<b>已經計算過</b>的硬幣組合</font> :::spoiler Code ```c++= int amount = 5; vector<int> coins = { 1,2,5 }; vector<int> count(amount + 1); count[0] = 1; for (auto c : coins) { //先弄coins for (int j = 1; j <= amount; j++) { //再弄每種problem if (j - c >= 0) { count[j] += count[j - c]; } } } cout << count[amount] << endl; ``` ::: ## Longest increasing subsequence - $O(n^2)$ - 會往前找 1. 符合順序(Increasing) 2. ~若接上有~比較大的sequence - [LeetCode](https://leetcode.com/problems/longest-increasing-subsequence) :::spoiler Code ```c++= vector<int> nums = { 6,2,5,1,7,4,8,3 }; vector<int> length(nums.size(), 1); for (int k = 0; k < nums.size(); k++) { for (int i = 0; i < k; i++) { //往前找(0~k)找符合順序&length[i]+1 if (nums[i] < nums[k]) { length[k] = max(length[k], length[i] + 1); } //更新 } } for (int k = 0; k < nums.size(); k++) cout << "solve(" << nums[k] << ") = length(" << k << ") = " << length[k] << endl; ``` ::: ### $O(nlog(n))$ 方法 -- Patience sort - [LeetCode -- 題解](https://www.youtube.com/watch?v=l2rCz7skAlk&ab_channel=HuaHua) - $O(nlog(n))$ - $O(n) \times O(log(n))$ - 有n個 $\times$ BS - [Patience Sort Code](https://www.geeksforgeeks.org/patience-sorting/) - $O(n^2)$ - takes $O(N)$ time to locate such a pile - 然後有N個element - 不常用,但概念很不錯 - 先分堆,再merge :::spoiler Pseudocode ```c 分堆(vector<int> arr) vector<vector<int>> piple; for(i = 0; i < arr的長度; i++) if(piple 為空) 新建一個vector<int> tmp 加入arr[i] piple.push_back tmp else flag = 1; for(j = 0; j < piple的長度; j++) if arr[i] < piple[j].back() piple[j].push_back arr[i] flag = 0; if flag 為 true 建一個vector<int> tmp 加入arr[i] piple.push_back tmp merge(piple) merge(vector<vector<int>> piple) vector<int> ans while True Max = INT_MIN Max_index = -1 for(i = 0; i < piple的長度; i++) if Max < piple[i].back() Max = piple[i].back() index = i ans.push_back(piple[Max_index]) piple[Max_index].pop_back() if piple[Max_index] 為空 piple.erase(piple.begin() + Max_index) if piple 為空 break ``` ::: - [Patience Sort Code2](https://reurl.cc/2zpDyO) ## Paths in a grid - $O(n^2)$ - 會根據棋盤上的左邊和上面來決定要怎麼走 - (對於左邊)走右還是(對於上面)走下 - 缺點是棋盤要擴大 - $5\times 5$ :arrow_right: $6 \times 6$ - 多出來的 - **value設為0** - 會比較好做 - 比較 : recursive可以避免掉 - 條件到就直接return :::spoiler Code ```c++= int n = 5; //棋盤大小 vector<vector<int>> graph = { {0,0,0,0,0,0}, //這邊棋盤要擴大 5*5 -> 6*6 {0,3,7,9,2,7}, {0,9,8,3,5,5}, {0,1,7,9,8,5}, {0,3,8,6,4,10}, {0,6,3,9,7,8} }; vector<vector<int>> sum(6, vector<int>(6)); //answer for (int y = 1; y < 6; y++) { for (int x = 1; x < 6; x++) { sum[y][x] = max(sum[y - 1][x], sum[y][x - 1]) + graph[y][x]; } //左->右 上->下 目前位置 } cout << sum[n][n] << endl; ``` ::: ## 0/1 Knapsack Problem - 預先將$k$排好順序,會減少做的時間 - 有$k=\{1,3,3,5\}$,去組合權重為$Wi$ - <font color=red><b>不能使用重複的k</b></font> - $O(nW)$ - $n=|k|$ - $W$為要算的$Wi$有多少個 - 根據已有的True,用剩下還沒使用的$k$去往外擴(概念:左->右) - 計算順序要改成由<font color=red>後面</font>開始,才不會覆蓋左上方的格子 :::spoiler Code -- 課本範例,看是否能組成 ```c++= int w = 12; vector<bool> nums(w + 1); vector<int> k = { 1,3,3,5 }; nums[0] = 1; for (int j = 0; j < k.size(); j++) { for (int i = w; i >= 0; i--) { //根據已有的True,去往外擴(左->右) if (nums[i]) nums[i + k[j]] = 1; } } for (int i = 0; i <= w; i++) printf("%3d", i); cout << endl; for (auto x : nums) cout << " " << (x ? "O" : "X"); ``` ::: :::spoiler Code 範例,看組成最大值是多少 ```c++= int n = 4; int w = 8; vector<int> weight = { 0,1,2,5,6 }; vector<int> size = { 0,2,3,4,5 }; vector<int> c(w + 1); vector<int> best(w + 1); for (int i = 1; i <= n; i++) { for (int j = w; j >= 0; j--) { if (j - size[i] >= 0) { c[j] = max(c[j], c[j - size[i]] + weight[i]); best[j] = size[i]; //這個要記長度,不能記i //因為之後要回推時,要用長度回推,不是用i去扣 } } } cout << "weight " << w << " : " << c[w] << endl << "組成 : "; int tmp_i = w; while (tmp_i && best[tmp_i]) { cout << best[tmp_i] << " "; tmp_i -= best[tmp_i]; } ``` ::: ## Knapsack Problem - 拿出來,放新的進去試試看 - 比較大,放新的 - 比較小,放舊的回去 ## LCS - 用最少編輯次數,來改變字串 - "MOIVE" :arrow_right: "LOVE" 要花多少步呢? - [LeetCode](https://leetcode.com/problems/longest-common-subsequence/) :::spoiler Solution ![](https://assets.leetcode.com/users/votrubac/image_1564691262.png =50%x) ::: - $cost(a,b)=\begin{cases} 0,\ when\ \ x[a] = y[b] \\ 1,\ otherwise \end{cases}$ - $dis(a,b)\ =\ min(dis(a,b-1)+1,\ \ dis(a-1,b)+1,\ \ dis(a-1,b-1)+cost(a,b))$ - $dis(a,b-1)$ - insert a char 在a的後面 - "ABC" :arrow_left: "AB" - $dis(a-1,b)$ - remove a char 在a後面 - "AB" :arrow_left: "ABC" - $dis(a-1,b-1)$ - match or modifiy a的最後char - "ABC" :arrow_left: "ABD" :::spoiler Code ![image](https://hackmd.io/_uploads/Skj56kW6p.png =40%x) ```c++= bool cost(char a, char b) { return !(a == b); } ``` ```c++= string b = " MOVIE"; string a = " LOVE"; int m = a.size() - 1; int n = b.size() - 1; vector<vector<int>> dis(m + 1, vector<int>(n + 1)); //因為前面有空白字元,所以要填充0~m、0~n for (int i = 1; i <= m; i++) dis[i][0] = i; //" " vs. "LOVE" for (int i = 1; i <= n; i++) dis[0][i] = i; //"MOVIE" vs. " " for (int i = 1; i <= m; i++) { //row for (int j = 1; j <= n; j++) { //col //選擇方法,insert、remove、modify(或不動) dis[i][j] = min({ dis[i][j - 1] + 1, dis[i - 1][j] + 1,dis[i - 1][j - 1] + cost(a[i],b[j]) }); } } cout << " M O V I E\n"; //印 for (int i = 0; i < a.size(); i++) { cout << a[i] << " "; for (auto y : dis[i]) cout << y << " "; cout << endl; } ``` ::: ## Counting Tilings - [題目](https://cses.fi/problemset/task/2181/) - [Code](https://yuihuang.com/cses-2181/) ## Kadane's algorithm - [參考](https://www.geeksforgeeks.org/largest-sum-contiguous-subarray/) - Maximum Subarray - 版本一 - 若全為負數,也可以找最大 - 步驟 - 先加 - 找最大 - 負->歸零 - 版本二 - 若全為負數,<font color=red>不可以</font>找最大 - 只會變0 - 步驟 - max(先加,歸零) //因為加起來可能會為負 - 找最大 :::spoiler 版本一 ```c++= vector<int> nums = { -2,1,-3,4,-1,2,1,-5,4 }; int max_sum = INT_MIN; int sum = 0; for (int i = 0; i < nums.size(); i++) { sum += nums[i]; max_sum = max(sum, max_sum); //取答案 sum = max(0, sum); //若為負 -> 歸零 } cout << max_sum << endl; //answer ``` ::: :::spoiler 版本二 ```c++= int sum = 0; int best = INT_MIN; for (int i = 0; i < nums.size(); i++) { sum = max(0, sum + nums[i]); best = max(best, sum); } cout << best << endl; ``` ::: # 第八章 -- Amortized Analysis - ==分析最壞性能的每次運行的平均時間(runtime),但不能確認實際平均情況的性能== ????? ## Two Pointer - [參考](https://reurl.cc/E49RM0) - 可用於vector、linked list、string ### 左右指標 - 多用於Array 或 String - 在適當情況下,移動其中的一個或兩個指標 - 指標方向可<font color=red>同</font>方向或<font color=red>反</font>方向 ### 快慢指標 - 多用於Linked-list - 透過 slow 與 fast 兩指標,讓兩個指標保持一定的間隔規律 #### 找Linked List中心點 - slow走一步,fast走兩步 :::spoiler 範例 ![](https://miro.medium.com/v2/resize:fit:828/format:webp/1*D8OZpD4x-0Ow0kRpSNyofw.png =80%x) ::: #### 找Linked List倒數第k點 - fast先走k步 - slow、fast再用同速度走 :::spoiler 範例 ![](https://miro.medium.com/v2/resize:fit:828/format:webp/1*N9jnteF9nc-EPs7TssMSRQ.png =80%x) ::: #### 有無cycle - slow、fast用不同速度走 - 早晚會遇到 :::spoiler 範例 ![image](https://hackmd.io/_uploads/HJgPQvdCa.png =80%x) ![image](https://hackmd.io/_uploads/BywdQP_0a.png =80%x) ::: ## Subarray Sum #### 課本算法 - $O(n)$ - `left`每次只走一步 - `right`從left開始走 - 每次將走過的紀錄起來 - count = left $+\cdot \cdot \cdot+$ right - 直到 count<font color =red> 大於 </font>target_sum~且如果大於不能算進去count~ - 直到找到`target_sum` - [LeetCode](https://hackmd.io/@LazyBear0425/LeetCode7#560-Subarray-Sum-Equals-K) #### 補充算法 :::spoiler Code ```c++ vector<int> v = {1,3,2,5,1,1,2,100}; int x = 100; auto l = v.begin(); auto r = v.begin(); int sum = 0; while(l != v.end()){ if (r !=v.end() && sum < x + *r) sum += *r, r++; else sum -= *l, l++; if (sum == x) return true; } return false; ``` ::: ## Two Sum - $O(nlog(n))$ - Sort + 找 - $O(nlog(n))$ + $O(n)$ - 先<font color=red>sort</font> - `left`每次只走一步 - `right`從**最後**開始走 - 直到找到left + right <font color=red>$\le$</font> target_sum,才停下 - 直到找到`target_sum` ### Three Sum - $O(n^2)$ - [LeetCode](https://hackmd.io/@LazyBear0425/LeetCode1#15-3Sum) ## Nearest smaller elements - $O(n)$ - (push + pop) $\times$ n element - $O(1) \times O(n)$ - 用**Stack** - remove stack.top - until top < current element - Example - stack : `1,3,4`, current : `2` - remove `3,4` -> stack : `1` - push `2` -> stack : `1,2` - [LeetCode](https://hackmd.io/@LazyBear0425/LeetCode1#496-Next-Greater-Element-I) ## Sliding Window Minimum - 和[Nearest Smaller Elements](https://hackmd.io/v-lY_zPNSoGRap9s2sS2Ig?both#Nearest-smaller-elements)同理 - $O(n)$ - 用**priority_queue**實作 - 要找出window內的最小值,且window size固定 - remove queue.back - until back **<** current element <font color=gray>or</font> queue empty - <font color=gray>or</font> out of window size - [LeetCode](https://leetcode.com/problems/sliding-window-maximum) - [程式碼範例](https://www.geeksforgeeks.org/sliding-window-maximum-maximum-of-all-subarrays-of-size-k/) - 用<font color=red>priority_queue</font> - 從k開始,並把每項加入priority_queue - 要<font color=red>記錄index</font> - 若超出window && 非top -> 不會即時吐出去~條件到了自然退出~ ```c++ while (heap.top().second <= i - k) //過時了 heap.pop(); ``` - priority_queue的<font color=red>top</font>即為答案 :::spoiler function ```c++= vector<int> maxSlidingWindow(vector<int>& arr, int k) { vector<int> ans; priority_queue<pair<int, int> > heap; //處理 0~k-1 for (int i = 0; i < k; i++) heap.push({ arr[i], i }); ans.push_back(heap.top().first); //1st answer //start for (int i = k; i < arr.size(); i++) { heap.push({ arr[i], i }); while (heap.top().second <= i - k) //篩掉超出範圍 heap.pop(); ans.push_back(heap.top().first); //輸出answer } return ans; } ``` ::: - Deque - 處理<font color=red>front</font> - 若超出範圍 - 即時過濾 ```c++ while ((!Qi.empty()) && Qi.front().second <= i - K) Qi.pop_front(); ``` - 處理<font color=red>back</font> - pop掉尾巴 - 直到 back > current element ```c++ while ((!Qi.empty()) && arr[i] >= Qi.back().first ) Qi.pop_back(); ``` - Priority_queue vs. deque | STL | Priority_queue | deque | |:--------------:|:----------------:|:--------:| | 超出範圍的退出 | 時間到了自然退出 | 手動篩選 | # 第二十一章 ## 質數運算 ### number of factors ![image](https://hackmd.io/_uploads/SJm-egOTT.png =28%x) - Example - $\tau(84) = 3 \times 2 \times 2$ - 84 : 1,2,3,4,6,7,12,14,21,28,42,84,共12個 ### sum of factors ![image](https://hackmd.io/_uploads/SyxGeeuTa.png =55%x) - $\sigma(84) = \cfrac{2^3-1}{2-1} \cdot \cfrac{3^2-1}{3-1} \cdot \cfrac{7^2-1}{7-1} = 7 \cdot 4 \cdot 8 = 224$ - $1+2+3+4+6+7+12+14+21+28+42+84=224$ ### product of factors ![image](https://hackmd.io/_uploads/BkqGllOpa.png =25%x) - $\mu(84) = 84^6$ - $\because 1\cdot84、2\cdot42、3\cdot28\ ...\ 7\cdot12$ ## GCD ```c++= int gcd(int a, int b){ if(a == 0) return b; else return gcd(b, a%b); } ``` ### number of coprime - 用Euler's totient function - Example - $\varphi(n) = \prod^{k}_{i=1} p^{a_i-1}_i(p_i-1)$ - $\varphi(12) = 2^1\cdot(2-1)\cdot3^0\cdot(3-1) = 4$ - 備註 - 若$n$為質數 - $\varphi(n) = n-1$ ## LCM - 公式 $lcm(a, b) = \cfrac{ab}{gcd(a,b)}$ ## 求$x^n\%m$較快方法 - p.33 - $O(log(n))$ - 原方法 : $(x\%m)^n\%m$ - $O(n)$ ```c++= int modpow(int x,int n,int m){ if(n == 0) returm 1 % m; long long u = modpow(x, n / 2, m); u = (u * u) % m; //x^(n/2) * x^(n/2) if(n % 2 == 1) u = (u * x) % m; //x^(n-1) * x return u; } ``` ## 計算$x^{-1}\%m$ - 若m為質數 - == $x^{m-2}\%m$ # 補充 ## Eulerian path and circuit - [參考](https://www.geeksforgeeks.org/eulerian-path-and-circuit/) - 每個Edge會遍歷過一次 - Eulerian circuit - 所有Degree皆為偶數 - 為Eulerian path,但start和end為同一node - Eulerian path - 零個或兩個node的Degree為奇數,其他皆為偶數 - use DFS ## Sollin's Algorithm - 步驟 1. 將各頂點視為獨立的一棵樹 2. 就每棵樹挑出成本最小的邊,並加入此樹 3. 刪除重複挑出的邊,只保留一份 4. 重複②~③直到只剩一棵樹,或是無邊可挑 ![image](https://hackmd.io/_uploads/B1VZTkvQC.png)

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully