diff --git a/C04-Recurrences/problem.md b/C04-Recurrences/problem.md index 107ff475..ce6541be 100644 --- a/C04-Recurrences/problem.md +++ b/C04-Recurrences/problem.md @@ -183,12 +183,46 @@ more than n/2 of the chips are good. Give and solve the recurrence that describe ### `Answer` + +中文版 + a. 如果超过一半是坏的,那么我们可以从这些坏的中取出一组数量和好的一样多的,他们的表现能和好的一样. b. 将所有的芯片两两配对,如果报告是both are good or bad,那么就从中随机选一个留下来,否则全部扔掉. 一直这样递归下去,最后剩下的是好的. c. T(n) = T(n/2)+n/2,是Θ(n)的. +English Version + +a. consider the situation that at least half chips are bad. Denote good chip number is N. +**We can choice more than N bad chips, and make them act as same as GOOD one.** +In this situation, we cannot distinguish whether is GOOD or BAD.(The BAD chips are always major and perfectly confuse information GOOD chips make) + +b. Let make floor(N / 2) pairs arbitrarily. We **focus the pairs that both of it report opponent is GOOD.** +Because at least half chips are GOOD, **the pairs both report opponent is GOOD contains at least half GOOD-GOOD pairs.** Next, **we discard one chip of the GOOD-GOOD pair, per every GOOD-GOOD pairs.** After all, **we operate the remained chips as same as this action.**(make pairs -> focus GOOD-GOOD reported pairs -> discard one chip per pairs) +We can decrease the target chips by half by discarding, and **after discarding we can still assure that target chips contains at least half GOOD chips.** As a conclusion, if we make this actions till the last chip remained, the last must be GOOD. + +c. The recurrence is + +T(n) = T(n / 2) + n / 2 + +This is Θ(n) admittedly. + +日本語版 + +a. 過半数のチップがbadの時、**goodのチップより多くのbadチップに、goodチップと同じ挙動をしてもらえばよい。** +そのとき、判別者はどれがgoodでどれがbadチップなのかを判別できない。 + +b. 任意にfloor(N / 2)ペア組んで、その中で「どちらもGOOD」のペアに着目する。この時、**必ず過半数のペアはGOOD-GOODである(つまり、BAD-BADよりもGOOD-GOODの方が必ず多い)** +次に、その「どちらもGOOD」の各ペアのうち片方のチップを除外する。この操作後でも、着目するチップのうち、GOODチップはBADチップより必ず多くなる。 +よって、その半分にする作業を最後の1つになるまで繰り返せば、残ったチップはGOODだと確定する。(常にGOODチップは +BADチップより多いため) + +c. T(n)は、n / 2回のペア判別と捨てるを行った後、T(n / 2)の計算に移るので、漸化式は + +T(n) = T(n / 2) + n / 2 + +この漸化式は明らかに、Θ(n)の式となる。 ### Problems 7 : Monge arrays *** diff --git a/C07-Quicksort/7.2.md b/C07-Quicksort/7.2.md index df6e8a94..772c5e90 100644 --- a/C07-Quicksort/7.2.md +++ b/C07-Quicksort/7.2.md @@ -40,7 +40,7 @@ Banks often record transactions on an account in order of the times of the trans ### `Answer` 原数组越有序,逆序对越少,插入排序越快. -The more ordered the original array, the less the inversions and quicksort will run much more quickly. +The more ordered the original array, the less the inversions and Insertion Sort will run much more quickly. INSERTION-SORT's while loop which checks for whether or not a new insertion needs to be done would stop after only one iteration, and in addition quicksort would not be able to achieve a balanced split at every recursive step due to the pivot being the largest number in the new array to sort. diff --git a/C09-Medians-and-Order-Statistics/randomized-select.cpp b/C09-Medians-and-Order-Statistics/randomized-select.cpp index 38835fed..d3de3a73 100644 --- a/C09-Medians-and-Order-Statistics/randomized-select.cpp +++ b/C09-Medians-and-Order-Statistics/randomized-select.cpp @@ -1,66 +1,47 @@ -/************************************************************************* - > File Name: randomized-select.cpp - > Author: Louis1992 - > Mail: zhenchaogan@gmail.com - > Blog: http://gzc.github.io - > Created Time: Sun May 24 11:46:39 2015 - ************************************************************************/ #include #include using namespace std; -class Solution { - - int kthSmallest(vector& arr, int l, int r, int k) - { - - if (k > 0 && k <= r - l + 1) - { - int pos = randomPartition(arr, l, r); - - if (pos-l == k-1) - return arr[pos]; - else if(pos-l > k-1) - return kthSmallest(arr, l, pos-1, k); - else - return kthSmallest(arr, pos+1, r, k-pos+l-1); - } - return INT_MAX; - } - - int partition(vector& arr, int l, int r) - { - int x = arr[r], i = l; - for(int j = l; j <= r - 1; j++) - { - if (arr[j] <= x) - { - swap(arr[i], arr[j]); - i++; - } +int partition(vector& arr, int l, int r) { + int x = arr[r], i = l; + for (int j = l; j <= r - 1; j++) { + if (arr[j] <= x) { + swap(arr[i], arr[j]); + i++; } - swap(arr[i], arr[r]); - return i; - } - - int randomPartition(vector& arr, int l, int r) - { - int n = r-l+1; - int pivot = rand() % n; - swap(arr[l + pivot], arr[r]); - return partition(arr, l, r); } + swap(arr[i], arr[r]); + return i; +} + +int randomPartition(vector& arr, int l, int r) { + int n = r - l + 1; + int pivot = rand() % n; + swap(arr[l + pivot], arr[r]); + return partition(arr, l, r); +} -public: - int findKthLargest(vector& nums, int k) { - return kthSmallest(nums, 0, nums.size()-1, nums.size()-k+1); +int kthSmallest(vector& arr, int l, int r, int k) { + int pos = randomPartition(arr, l, r); + if (pos - l == k - 1) { + return arr[pos]; + } else if (pos - l > k - 1) { + return kthSmallest(arr, l, pos - 1, k); + } else { + return kthSmallest(arr, pos+1, r, k-pos+l-1); } -}; +} + +int kthSmallest(vector& arr, int k) { + // TODO: Validate k is in valid range. + return kthSmallest(arr, 0, arr.size() - 1, k); +} -int main() -{ - int arr[5] = {2,4,0,-2,8}; - vectorv(arr, arr+5); - Solution s; - cout << s.findKthLargest(v, 2) << endl; -} \ No newline at end of file +int main() { + vectorv{3,4,2,5,1}; + cout << kthSmallest(v, 1) << endl; + cout << kthSmallest(v, 2) << endl; + cout << kthSmallest(v, 3) << endl; + cout << kthSmallest(v, 4) << endl; + cout << kthSmallest(v, 5) << endl; +} diff --git a/C10-Elementary-Data-Structures/10.1.md b/C10-Elementary-Data-Structures/10.1.md index 6ed1a8aa..77bf81c6 100644 --- a/C10-Elementary-Data-Structures/10.1.md +++ b/C10-Elementary-Data-Structures/10.1.md @@ -34,7 +34,7 @@ Using Figure 10.1 as a model, illustrate the result of each operation in the seq Explain how to implement two stacks in one array A[1...n] in such a way that neither stack overflows unless the total number of elements in both stacks together is n. The PUSH and POP operations should run in O(1) time. ### `Answer` -At the beginning, top of the first stack is A[1], top of the second stack - A[n]. When pushing element to first stack, icrease the iterator, when pushing to the second stack - decrease it. +At the beginning, top of the first stack is A[1], top of the second stack - A[n]. When pushing element to first stack, increase the iterator, when pushing to the second stack - decrease it. ### Exercises 10.1-3 *** diff --git a/C18-B-Trees/18.1.md b/C18-B-Trees/18.1.md index 0eb4b95b..50e7d4d4 100644 --- a/C18-B-Trees/18.1.md +++ b/C18-B-Trees/18.1.md @@ -26,7 +26,10 @@ which yields 2 ≤ t ≤ 3. So t can be 2 or 3. Show all legal B-trees of minimum degree 2 that represent {1, 2, 3, 4, 5} ### `Answer` -The question asks for the legal trees with min degree t=2. So, each node can contain x num of keys while 1 ≤ x ≤ 3 +The question asks for the legal trees with min degree t=2. So, each node can contain x num of keys while 1 ≤ x ≤ 3. Since each internal node that has x num of keys also has x+1 num of children (property 2), the root can only have 1 or 2 keys, the root can not have 3 keys since it must have 4 children and we only have 5 keys to draw. + +If the root has 1 key there are following variations. + ``` 2 1 3 4 5 @@ -41,17 +44,14 @@ The question asks for the legal trees with min degree t=2. So, each node can con 3 1 2 4 5 ``` - + +If the root has 2 keys there is only one possibility. + ``` 2 4 1 3 5 ``` -``` - 2 3 4 - 1 5 -``` - ### Exercises 18.1-4 *** As a function of the minimum degree t, what is the maximum number of keys that can be stored in a B-tree of height h? diff --git a/C18-B-Trees/18.2.md b/C18-B-Trees/18.2.md index 491e9e98..e16481a7 100644 --- a/C18-B-Trees/18.2.md +++ b/C18-B-Trees/18.2.md @@ -78,7 +78,24 @@ Since leaf nodes require no pointers to children, they could conceivably use a d Suppose that disk hardware allows us to choose the size of a disk page arbitrarily, but that the time it takes to read the disk page is a + bt, where a and b are specified constants and t is the minimum degree for a B-tree using pages of the selected size. Describe how to choose t so as to minimize (approximately) the B-tree search time. Suggest an optimal value of t for the case in which a = 5 milliseconds and b = 10 microseconds. ### `Answer` -Objective : minimize (5+10t)*tlog{t}{n} + +For a B-tree with n number of keys, B-TREE-SEARCH performs at most ![\log_{t}{n}](https://render.githubusercontent.com/render/math?math=%5Clog_%7Bt%7D%7Bn%7D) disk accesses, each access takes (a + bt) IO time. Since for each internal node x, x.n < 2t, it takes at most 2t - 1 compares within each node. The final objective function is + +Objective: minimize ![\log_{t}{n}](https://render.githubusercontent.com/render/math?math=%5Clog_%7Bt%7D%7Bn%7D) * (IO Time of each access + ((2t - 1) * CPU time of each compare)) + +The problem doesn't give the corresponding CPU time for each compares but since modern computer IO operation is much more expensive than the CPU operations we can ignore the second part, hence resulting + +Objective: minimize ![\log_{t}{n}](https://render.githubusercontent.com/render/math?math=%5Clog_%7Bt%7D%7Bn%7D) * IO Time = ![\log_{t}{n}*(a+bt)](https://render.githubusercontent.com/render/math?math=%5Clog_%7Bt%7D%7Bn%7D*(a%2Bbt)) = ![\frac{\ln{n}}{\ln{t}}(a+bt)](https://render.githubusercontent.com/render/math?math=%5Cfrac%7B%5Cln%7Bn%7D%7D%7B%5Cln%7Bt%7D%7D(a%2Bbt)) => minimize ![\frac{a+bt}{\ln{t}}](https://render.githubusercontent.com/render/math?math=%5Cfrac%7Ba%2Bbt%7D%7B%5Cln%7Bt%7D%7D) + +[Taking derivative of ![\frac{a+bt}{\ln{t}}](https://render.githubusercontent.com/render/math?math=%5Cfrac%7Ba%2Bbt%7D%7B%5Cln%7Bt%7D%7D)](https://www.wolframalpha.com/input/?i=derivative+of+%28a%2Bbt%29%2Fln+t+respect+to+t&assumption=%22UnitClash%22+-%3E+%7B%22t%22%2C+%7B%22MetricTons%22%7D%7D&assumption=%7B%22C%22%2C+%22t%22%7D+-%3E+%7B%22Variable%22%7D) we get ![\frac{a+bt-bt*\ln{t}}{t*ln^{2}{t}}](https://render.githubusercontent.com/render/math?math=%5Cfrac%7Ba%2Bbt-bt*%5Cln%7Bt%7D%7D%7Bt*ln%5E%7B2%7D%7Bt%7D%7D). + +Since t > 1 we only need to find root of ![a+bt-bt*\ln{t}](https://render.githubusercontent.com/render/math?math=a%2Bbt-bt*%5Cln%7Bt%7D). + +![a+bt=bt*\ln{t}](https://render.githubusercontent.com/render/math?math=a%2Bbt%3Dbt*%5Cln%7Bt%7D) => ![t=e^{W(\frac{a}{be})+1}](https://render.githubusercontent.com/render/math?math=t%3De%5E%7BW(%5Cfrac%7Ba%7D%7Bbe%7D)%2B1%7D) + +where W is the LambertW function + +when a = 5, b = 10, t is around [3.18](https://www.wolframalpha.com/input/?i=e%5E%281+%2B+ProductLog%281%2F%282+e%29%29%29&assumption=%22ClashPrefs%22+-%3E+%7B%22Math%22%7D), the optimal value of t is 3 in this case. *** Follow [@louis1992](https://github.com/gzc) on github to help finish this task. diff --git a/README.md b/README.md index 1dc4f91c..2c430e4a 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ Solutions to *Introduction to Algorithms* by Charles E. Leiserson, Clifford Stei 29. [tushar-rishav](https://github.com/tushar-rishav) 30. [ravgill](https://github.com/ravgill) 31. [Mad_Kingu](https://github.com/Mad-Kingu) +32. [kotoz](https://github.com/Kottoz) If I miss your name here, please pull a request to me to fix. @@ -324,5 +325,6 @@ If a problem is too easy to solve, we'll mark it as **straightforward** in order *** Follow [@louis1992](https://github.com/gzc) on github to help finish this task. +You can also subscribe my [youtube channel](https://www.youtube.com/channel/UCAvvkYnRNyObcHzOCaVgSrQ). **Disclaimer**: the solutions in this repository are crowdsourced work, and in any form it neither represents any opinion of nor affiliates to the authors of Introduction to Algorithms or the MIT press.