1. 程式人生 > 其它 >LC T668筆記 & 有關二分查詢、第K小數、BFPRT演算法

LC T668筆記 & 有關二分查詢、第K小數、BFPRT演算法

LC T668筆記 【涉及知識:二分查詢、第K小數、BFPRT演算法】

【以下內容僅為本人在做題學習中的所感所想,本人水平有限目前尚處學習階段,如有錯誤及不妥之處還請各位大佬指正,請諒解,謝謝!】

 

!!!觀前提醒!!!

【本文篇幅較大,如有興趣建議分段閱讀

有關二分查詢

作用:在有序集合中快速查詢目標值

適用性:

  1. 只能查詢有序的資料集

順序儲存的資料結果就是陣列了,也就是二分查詢只能從陣列中查詢,而不能查詢鏈式儲存的資料集,比如查詢連結串列中的數,就不能用二分查詢。

  2. 針對的是靜態有序資料集

二分查詢適合那種不經常變動的資料集合。如果經常插入、刪除的資料集,每次插入和刪除都要保證集合資料的有序,維護動態資料有序的成本很高

。所以二分查詢適合從有序的不經常變動的資料集合中查詢。適合資料集合已經排好序,但是需要經常查詢的場景。

  3. 不適合資料量太大或者太小的場景

因為二分查詢需要依賴陣列這種資料結構,而陣列要求連續的記憶體空間,其需要把所有資料全部讀入記憶體中,因此資料量太大的,對記憶體要求比較高。如果資料量只有幾十個,那麼不論是使用二分查詢還是順序遍歷,查詢效率都差不多。

有關二分查詢的邊界問題

“思路很簡單,細節是魔鬼”

二分的幾個常用情景:尋找一個數、尋找左側邊界、尋找右側邊界

以下是二分查詢的基本框架:

 1 public int BinarySearch(int[] nums, int target) {
2 int left = 0, right = ...; 3 4 while(...) { 5 int mid = left + ((right - left) >> 1); 6 if (nums[mid] == target) { 7 ... 8 } else if (nums[mid] < target) { 9 left = ... 10 } else if (nums[mid] > target) { 11 right = ...
12 } 13 } 14 return ...; 15 }

分析二分查詢的一個技巧是:不要出現 else,而是把所有情況用 else if 寫清楚,這樣可以清楚地展現所有細節。

(一)  尋找一個數

 1 public int BinarySearch(int[] nums, int target) {
 2     int left = 0; 
 3     int right = nums.length - 1; //【1】
 4 
 5     while(left <= right) { //【2】
 6         int mid = left + ((right - left) >> 1);
 7         if(nums[mid] == target)
 8             return mid; 
 9         else if (nums[mid] < target)
10             left = mid + 1;  //【3】
11         else if (nums[mid] > target)
12             right = mid - 1;  //【4】
13     }
14     return -1;
15 }

  1. while中的迴圈條件

迴圈條件由搜尋區間的結構確定,當找到目標值後,返回即可;

若沒找到則需考慮終止情況。此處的搜尋區間的結構是兩端閉區間。當left == right時,表示區間[left, right],此時區間內仍有一個數值未被搜尋,若此時結束迴圈,可能錯過對目標值的匹配,因此需要繼續查詢,則終止條件應當是left > right時,此時搜尋區間為空。所以此處while中應當為“<=”。

如果要使用小於號,則在結尾加一句判斷即可。

1 return nums[left] == target ? left : -1;

  2.  left與right的加加減減

邊界的加減也由搜尋區間的結構確定。在[left, right]中mid被檢測後,需要據mid將其劃分為兩個區間,若mid位置上的值不等於target,則不用再考慮mid。因為邊界均可取到,所以搜尋區間因改為[left, mid – 1]或[mid + 1, right]

  3.  缺點

當資料中重複出現目標元素,則返回的是在重複序列中中間位置的索引,並不能得到其左側或右側邊界。如{1, 2, 2, 2, 3, 5},target = 2,此時返回索引為2,但其邊界為[1, 3]

(二)  尋找左側邊界

 1 public int LeftBound(int[] nums, int target) {
 2     if (nums.length == 0) return -1;
 3     int left = 0;
 4     int right = nums.length; //【1】
 5     
 6     while (left < right) { //【2】
 7         int mid = left + ((left + right) >> 1);
 8         if (nums[mid] == target) {
 9             right = mid; //【3】
10         } else if (nums[mid] < target) {
11             left = mid + 1;
12         } else if (nums[mid] > target) {
13             right = mid; //【4】
14         }
15     }
16     return left;
17 }

  1.  while中的迴圈條件

同理,此處的搜尋區間為左閉右開型,當left == right時,表示區間[left, right),此時的區間已經為空,故可以終止。

注:這裡解釋一下為何上面用兩端閉區間,而這裡用左開後閉區間。因為這樣的寫法比較普遍,不這麼寫也可以,後文將會展示三種寫法(兩端閉,左開右閉,左閉右開)。

  2.  left與right的加減

因為此處是左閉右開區間,在[left, right)中mid被檢測後,需要據mid將其劃分為兩個區間,[left, mid)和[mid + 1, right)。為了保證區間結構不變,所以right應變為mid,left應變為mid + 1

  3.  有關結尾的返回值

返回值表示目標值在序列中的左側邊界,等價於小於目標值的元素個數。分析可知left的取值範圍是[0, nums.Length],所以當left == nums.Length時,說明沒有一個元素小於target,即target在該序列中不存在,返回-1即可。(當然,最終的返回值也可以是right,因為終止條件是left == right)

1 if (left == nums.length) return -1;
2 return nums[left] == target ? left : -1;

  4.  該演算法的核心,即為何可以查詢左側邊界

1 if (nums[mid] == target) 
2     right = mid;

當nums[mid] == target時,因為資料有序,說明mid左側可能存在target,所以應縮小上界,不斷向左收縮。

  5.  統一格式,將while迴圈加入等號

據原理,只需將right初值設為nums.Length – 1;right的變化改為mid – 1即可。

 1 public int LeftBound(int[] nums, int target) {
 2     int left = 0, right = nums.length - 1;
 3     while (left <= right) {
 4         int mid = left + (right - left) / 2;
 5         if (nums[mid] == target) {
 6             right = mid - 1;
 7             left = mid + 1;
 8         } else if (nums[mid] > target) {
 9             right = mid - 1;
10         } else if (nums[mid] < target) {
11             left = mid + 1;
12         }
13     }
14     if (left >= nums.length || nums[left] != target)
15         return -1;
16     return left;
17 }

(三)  尋找右邊界

 1 int right_bound(int[] nums, int target) {
 2     if (nums.length == 0) return -1;
 3     int left = 0, right = nums.length;
 4     while (left < right) {
 5         int mid = left + ((left + right) >> 1);
 6         if (nums[mid] == target) {
 7             left = mid + 1; //【1】
 8         } else if (nums[mid] < target) {
 9             left = mid + 1;
10         } else if (nums[mid] > target) {
11             right = mid;
12         }
13     }
14     return left - 1; //【2】
15 }

  1.  left與right的加減

因為此處是左閉右開區間,在[left, right)中mid被檢測後,需要據mid將其劃分為兩個區間,[left, mid)和[mid + 1, right) 。為了保證區間結構不變,所以right應變為mid,left應變為mid + 1

  2.  有關最後返回值

因為對left的更新為mid + 1,結束時會產生以下結果:

[注:上圖來源於搜尋引擎查詢結果】

所以需返回left – 1(也可返回right - 1)。

同理,當left == 0時,說明沒有一個元素大於target,即target在該序列中不存在,返回-1即可。

1 if (left == 0) return -1;
2 return nums[left-1] == target ? (left-1) : -1;

  3.  統一格式

 1 public int RightBound(int[] nums, int target) {
 2     int left = 0, right = nums.length - 1;
 3     while (left <= right) {
 4         int mid = left + ((right - left) >> 1);
 5         if (nums[mid] == target) {
 6             left = mid + 1;
 7         } else if (nums[mid] > target) {
 8             right = mid - 1;
 9         } else if (nums[mid] < target) {
10             left = mid + 1;
11         }
12     }
13     if (right < 0 || nums[right] != target)
14         return -1;
15     return right;
16 }

小結

1. 寫二分查詢時,儘量不要出現 else,將所有情況列出來便於分析。

2. 注意搜尋區間形式和 while 的終止條件,若存在漏掉的元素,最後特判。

3. 如需定義左閉右開的搜尋區間,搜尋左右邊界,只要在 nums[mid] == target 時做修改即可,搜尋右側時需要減一

4. 如果將搜尋區間全都統一成兩端閉,只要修改 nums[mid] == target 條件處的程式碼和返回的邏輯即可。

 

從一維二分談起

二分法,用於在集合中查詢某些符合要求的元素,可以將時間複雜度降低至對數級。使用二分法的前提查詢序列的有序性,主要思想是從序列中間位置開始,根據當前的中間值與目標值的大小關係,修改區間端點,確定目標值所在區間。

題意:在半有序的結合中查詢目標元素的索引值

思想:選定中點,比較中點值來更改區間,但需要先判斷當前所查詢的區間是否為有序區間,否則不能使用二分法

 1 //C# Version
 2 
 3 public class Solution {
 4     public int Search(int[] nums, int target) {
 5         int n = nums.Length;
 6         if(n == 0) return -1;
 7         if(n == 1) return nums[0] == target ? 0 : -1;
 8         
 9         int left = 0, right = n - 1;
10         while(left <= right) {
11             int mid = left + ((right - left) >> 1);
12             if(target == nums[mid]) return mid;
13             if(nums[0] <= nums[mid]) {
14                 if(nums[0] <= target && target < nums[mid]) right = mid - 1;
15                 else left = mid + 1;
16             }
17             else if(nums[0] > nums[mid]){
18                 if(nums[mid] < target && target <= nums[n - 1]) left = mid + 1;
19                 else right = mid - 1;
20             }
21         }
22         return -1;
23     }
24 }
 1 //C++ Version
 2 
 3 class Solution {
 4 public:
 5     int search(vector<int>& nums, int target) {
 6         int n = (int)nums.size();
 7         if(n == 0) return -1;
 8         if(n == 1) return nums[0] == target ? 0 : -1;
 9 
10         int left = 0, right = n - 1;
11         while(left <= right) {
12             int mid = left + ((right - left) >> 1);
13             if(target == nums[mid]) return mid;
14             if(nums[0] <= nums[mid]) {
15                 if(nums[0] <= target && target < nums[mid]) right = mid - 1;
16                 else left = mid + 1;
17             }
18             else if(nums[0] > nums[mid]){
19                 if(nums[mid] < target && target <= nums[n - 1]) left = mid + 1;
20                 else right = mid - 1;
21             }
22         }
23         return -1;
24     }
25 };

題意:找出陣列中滿足其和大於等於目標值的長度最小的連續子序列

思想:要判斷連續區間內的和,就先求出原陣列的字首和,因為題保證了陣列中每個元素都為正,所以字首和一定是遞增的,保證了二分的正確性。

得到字首和之後,對於每個開始下標 i,可通過二分查詢得到大於或等於i的最小下標 bound,使得 sum[bound] - sum [i−1] ≥ target,並更新子陣列的最小長度,此時子陣列的長度是bound - i + 1。

 【注:此解法非最優解】

 1 //C# Version
 2 
 3 public class Solution {
 4     public int MinSubArrayLen(int target, int[] nums) {
 5         int n = nums.Length;
 6         if (n == 0) return 0;
 7         int ans = int.MaxValue;
 8         int[] sums = new int[n + 1];
 9         for (int i = 1; i <= n; ++i) 
10             sums[i] = sums[i - 1] + nums[i - 1];
11         for (int i = 1; i <= n; ++i) {
12             int s = target + sums[i - 1];
13             int bound = LowerBound(sums, i, n - 1, s);
14             if (bound != -1)
15                 ans = Math.Min(ans, bound - i + 1);
16         }
17         return ans == int.MaxValue ? 0 : ans;
18     }
19     private int LowerBound(int[] nums, int left, int right, int s) {
20         while (left <= right) {
21             int mid = left + ((right - left) >> 1);
22             if (nums[mid] < s) left = mid + 1;
23             else right = mid - 1;
24         } 
25         return (nums[left] >= s) ? left : -1;
26     }
27 }
 1 //C++ Version
 2 
 3 class Solution {
 4 public:
 5     int minSubArrayLen(int s, vector<int>& nums) {
 6         int n = nums.size();
 7         if (n == 0) return 0;
 8         int ans = INT_MAX;
 9         vector<int> sums(n + 1, 0); 
10         for (int i = 1; i <= n; i++)
11             sums[i] = sums[i - 1] + nums[i - 1];
12         for (int i = 1; i <= n; i++) {
13             int target = s + sums[i - 1];
14             auto bound = lower_bound(sums.begin(), sums.end(), target);
15             if (bound != sums.end())
16                 ans = min(ans, static_cast<int>((bound - sums.begin()) - (i - 1)));
17         }
18         return ans == INT_MAX ? 0 : ans;
19     }
20 };

題意:找到陣列中某個峰值元素的索引(且nums[-1]與nums[len] = 負無窮)

思想:首先思考如何判斷峰值所在區間。

假設mid < mid + 1

  • 對於mid – 1,無論是mid – 1 > mid還是mid – 1 > mid均不能得到mid是峰值;
  • 對於mid + 2,有兩種情況:若mid + 2 < mid + 1則峰值為mid + 1;若mid + 2 > mid + 1,繼續後推,由於邊界後的值為-∞,那麼一定可以得到最後一個值為峰值。

綜上:峰值一定在較大的一部分。

 1 //C# Version
 2 
 3 public class Solution {
 4     public int FindPeakElement(int[] nums) {
 5         int left = 0, right = nums.Length - 1;
 6         while(left < right)
 7         {
 8             int mid = left + (right - left) / 2;
 9             if(nums[mid] > nums[mid + 1]) right = mid;
10             else left = mid + 1;
11         }
12         return left;
13     }
14 }
 1 //C++ Version
 2 
 3 int findPeakElement(vector<int>& nums) {
 4     int left = 0, right = nums.size() - 1;
 5     for (; left < right; ) {
 6         int mid = left + (right - left) / 2;
 7         if (nums[mid] > nums[mid + 1]) {
 8             right = mid;
 9         } else {
10             left = mid + 1;
11         }
12     }
13     return left;
14 }

小結

一維二分思想和操作較為簡單,具體步驟為:

  1. 確定並構建查詢物件。即是查詢元素,還是查詢和、差等,構建出用於查詢的序列,如:字首和。

  2.  判斷二分後目標值可能的所在區間。一般是通過中值和目標值的比較更改區間,特殊地(如峰值尋找)需要運用一定數學知識進行判斷。

 

有關二維二分

二維本質上可以看作是一維的疊加,某些簡單的情況下,可以一維一維的查詢。也可以從定義出發,從中點開始進行區間更改。當然,二維二分也有一些常見的變式,如從一個端點、對角線兩個端點出發等。

題意:在二維矩陣中查詢某個值是否存在。

思想:可以將二維陣列劃分為一維陣列,一行一行或一列一列進行判斷。可以對矩陣的第一列的元素二分查詢,找到最後一個不大於目標值的元素,然後在該元素所在行,進行二分查詢目標值是否存在。

 1 //C# Version
 2 
 3 class Solution {
 4     public bool SearchMatrix(int[][] matrix, int target) {
 5         int rowIndex = BinarySearchFirstColumn(matrix, target);
 6         if (rowIndex < 0) return false;
 7         return BinarySearchRow(matrix[rowIndex], target);
 8     }
 9 
10     private int BinarySearchFirstColumn(int[][] matrix, int target) {
11         int low = -1, high = matrix.Length - 1;
12         while (low < high) {
13             int mid = (high - low + 1) / 2 + low;
14             if (matrix[mid][0] <= target) low = mid;
15             else high = mid - 1;
16         }
17         return low;
18     }
19 
20     private bool BinarySearchRow(int[] row, int target) {
21         int low = 0, high = row.Length - 1;
22         while (low <= high) {
23             int mid = (high - low) / 2 + low;
24             if (row[mid] == target) return true;
25             else if (row[mid] > target) high = mid - 1;
26             else low = mid + 1;
27         }
28         return false;
29     }
30 }

也可以從定義出發,從中間點開始進行判斷。

 1 //C# Version
 2 
 3 public class Solution {
 4     public bool SearchMatrix(int[][] matrix, int target) {
 5         int m = matrix.Length, n = matrix[0].Length;
 6         int low = 0, high = m * n - 1;
 7         while (low <= high) {
 8             int mid = low + ((high - low) >> 1);
 9             int x = matrix[mid / n][mid % n];
10             if (x < target) low = mid + 1;
11             else if (x > target) high = mid - 1;
12             else return true;
13         }
14         return false;
15     }
16 }

注意到每行的第一個整數大於前一行的最後一個整數。因此,把每一行拼接到前一行可以得到一個遞增序列,所以可以從右上角開始進行判斷。

 1 //C# Version
 2 
 3 public class Solution {
 4     public bool SearchMatrix(int[][] matrix, int target) {
 5         int n = matrix.Length;
 6         if(n == 0) return false;
 7         int row = 0, col = matrix[0].Length - 1;
 8         while(row < n && col >= 0)
 9         {
10             if(matrix[row][col] < target) row++;
11             else if(matrix[row][col] >target) col--;
12             else return true;
13         }
14         return false;
15     }
16 }
 1 //C++ Version
 2 
 3 class Solution {
 4 public:
 5     bool searchMatrix(vector<vector<int>>& matrix, int target) {
 6         int row = matrix.size(), col = matrix[0].size();
 7         for(int i = 0, j = col-1; i < row && j >= 0;) {
 8             if(matrix[i][j] == target) 
 9                 return true;
10             else if(matrix[i][j] > target) 
11                 j--;
12             else if(matrix[i][j] < target)
13                 i++;
14         }
15         return false;
16     }
17 };

題意:在矩陣中找到第K小數

思想:可以從定義出發,從中間點開始進行判斷。關鍵是統計對於當前數mid,有多少個比它小的數。

若每行的第一個整數大於前一行的最後一個整數,則cnt = i * n + j。但本題不滿足該條件,則需要尋找一個參照值,通過迴圈,統計小於等於當前值的元素數。觀察四個邊角,左上角的元素最小,右下角的元素最大,而左下角和右上角的元素大小與mid相比是未定的,不妨取二者其一作為參照值。

在此,取左下角的值為參照值。

 1 //C# Version
 2 
 3 public class Solution {
 4     public int KthSmallest(int[][] matrix, int k) {
 5         int n = matrix.Length;
 6         int left = matrix[0][0], right = matrix[n - 1][n - 1];
 7         while(left < right) {
 8             int mid = left + ((right - left) >> 1);
 9             if(Check(matrix, mid, k, n)) right = mid;
10             else left = mid + 1;
11         }
12         return left;
13     }
14     private bool Check(int[][] matrix, int mid, int k, int n) {
15         int cnt = 0;
16         int i = n - 1, j = 0;
17         while(i >= 0 && j < n) {
18             if(matrix[i][j] > mid) i--;
19             else {
20                 cnt += i + 1;
21                 j++;
22             }
23         }
24         return cnt >= k;
25     }
26 }

本題與上題類似,只是在計數上有變化。

 1 /C# Version
 2 
 3 public class Solution {
 4     public int FindKthNumber(int m, int n, int k) {
 5         int left = 1, right = m * n;
 6         while(left < right) {
 7             int mid = left + ((right - left) >> 1);
 8             if(CheckCnt(mid, k, m, n)) right = mid;
 9             else left = mid + 1;
10         }
11         return left;
12     }
13     private bool CheckCnt(int mid, int k, int m, int n) {
14         int cnt = 0;
15         for(int i = 1; i <= m; i++) cnt += Math.Min(mid / i, n);
16         return cnt >= k;
17     }
18 }

小結

二維二分通常從邊角出發,通常以邊角值為參照值,進行區間的更新。其本質依舊是比大小,改區間。

 

有關第K小數

在此介紹一種演算法:中位數的中位數算(BFPRT),該演算法主要解決TOP-K問題。

有一個經典的問題,“從長度為N的無序陣列中找出前k大的數”。TOP-K問題的最簡單解法為快速排序後取第K大的數,但快速排序可能會達到最壞情況時間複雜度O(n2),且會對無用的資料進行排序操作(歸併除外)。而該演算法的主要優化是,修改快速排序選擇主元的方法,優化最壞時間複雜度。

對於快速排序,一般選擇中間位置的元素作為參照值,將小的數移到參照值左邊,大的數移到右邊,此時對於中間位置的該值,即為序列中第n/2小的數

那麼,是否可以用類似的方法,通過一次O(n)的操作找出第k小數呢?

該演算法通過“隨機選擇”實現了這個操作,其思想與快排類似,僅僅改變了對參照值的選取。

具體流程:

  1.將n個元素劃為 n/5 組,每組5個,至多隻有一組由 n%5 個元素組成。

  2.尋找每一個組的中位數(可以用插排)。

  3.對步驟2選出的 n/5 箇中位數,重複步驟1和步驟2,遞迴下去,直到剩下一個數字。

  4.最終剩下的數字近似為序列的中位數pivot,把小於等於它的數放左邊,大於的數放右邊。

  5.判斷pivot的位置與k的大小,如果pivot > k,則在[0, pivot – 1]內尋找第k小數;反之在[pivot + 1, n - 1]內尋找 k – pivot 小的數。

注意下面兩種分治的思想:

  1.分治法O(nlogn):大問題分解為小問題,小問題都要遞迴各個分支,例如:快速排序。

  2.減治法O(n):大問題分解為小問題,小問題只要遞迴一個分支,例如:二分查詢,隨機選擇。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int InsertSort(int array[], int left, int right);
 5 int GetPivotIndex(int array[], int left, int right);
 6 int Partition(int array[], int left, int right, int pivot_index);
 7 int BFPRT(int array[], int left, int right, int k);
 8 
 9 ///劃分
10 int Partition(int arr[], int left, int right, int pivot_index) {
11     swap(arr[pivot_index], arr[right]); // 把主元放置於末尾
12 
13     int partition_index = left; // 跟蹤劃分的分界線
14     for (int i = left; i < right; i++)
15         if (arr[i] < arr[right])
16             swap(arr[partition_index++], arr[i]); // 比pivot小的都放在左側
17 
18     swap(arr[partition_index], arr[right]); // 最後把pivot換回來
19     return partition_index;
20 }
21 
22 ///返回第 k 小數的下標
23 int BFPRT(int arr[], int left, int right, int k) {
24     int pivot_index = GetPivotIndex(arr, left, right); // 得到中位數的中位數下標
25     int partition_index = Partition(arr, left, right, pivot_index); // 進行劃分,返回劃分邊界
26     int num = partition_index - left + 1;
27 
28     if (num == k)
29         return partition_index;
30     else if (num > k)
31         return BFPRT(arr, left, partition_index - 1, k);
32     else
33         return BFPRT(arr, partition_index + 1, right, k - num);
34 }
35 
36 ///返回 [left, right]的中位數。
37 int Insertion(int arr[], int left, int right) {
38     int temp, j;
39     for (int i = left + 1; i <= right; i++) {
40         temp = arr[i];
41         j = i - 1;
42         while (j >= left && arr[j] > temp) {
43             arr[j + 1] = arr[j];
44             j--;
45         }
46         arr[j + 1] = temp;
47     }
48     return left + ((right - left) >> 1);
49 }
50 
51 ///陣列每五個元素作為一組,並計算每組的中位數,最後返回這些中位數的中位數下標
52 ///末尾返回語句最後一個引數多加 1 的作用是向上取整,可以始終保持 k 大於 0。
53 int GetPivotIndex(int arr[], int left, int right) {
54     if (right - left < 5)
55         return Insertion(arr, left, right);
56     int sub_right = left - 1;
57     
58     // 每五個作為一組,求出中位數,並把這些中位數全部依次移動到陣列左邊
59     for (int i = left; i + 4 <= right; i += 5) {
60         int index = Insertion(arr, i, i + 4);
61         swap(arr[++sub_right], arr[index]);
62     }
63 
64     // 利用 BFPRT 得到這些中位數的中位數下標
65     return BFPRT(arr, left, sub_right, ((sub_right - left + 1) >> 1) + 1);
66 }
67 
68 int main() {
69     ios::sync_with_stdio(false);
70     int k = 8; // 1 <= k <= array.size
71     int nums[20] = { 12, 9, 7, 1, 13, 9, 15, 0, 26, 2, 17, 5, 14, 31, 6, 18, 22, 7, 19, 41 };
72 
73     cout << "The Source Data:";
74     for (int i = 0; i < 20; i++)
75         cout << nums[i] << " ";
76     cout << endl;
77 
78     // 因為是以 k 為劃分,所以還可以求出第 k 小值
79     cout << "The Kth smallest number:" << nums[BFPRT(nums, 0, 19, k)] << endl;
80 
81     cout << "After Processing:";
82     for (int i = 0; i < 20; i++)
83         cout << nums[i] << " ";
84     cout << endl;
85     return 0;
86 }
TRANSLATE with x English
Arabic Hebrew Polish
Bulgarian Hindi Portuguese
Catalan Hmong Daw Romanian
Chinese Simplified Hungarian Russian
Chinese Traditional Indonesian Slovak
Czech Italian Slovenian
Danish Japanese Spanish
Dutch Klingon Swedish
English Korean Thai
Estonian Latvian Turkish
Finnish Lithuanian Ukrainian
French Malay Urdu
German Maltese Vietnamese
Greek Norwegian Welsh
Haitian Creole Persian  
  TRANSLATE with COPY THE URL BELOW Back EMBED THE SNIPPET BELOW IN YOUR SITE Enable collaborative features and customize widget: Bing Webmaster Portal Back