1. 程式人生 > 實用技巧 >pytest(三十七)--fixture引數化params

pytest(三十七)--fixture引數化params

問題:

給定一個數組nums,若 i < j, nums[i] > 2*nums[j],則稱這一對 i,j為important reverse pair

求給定陣列中,有多少組important reverse pair。

Example1:
Input: [1,3,2,3,1]
Output: 2

Example2:
Input: [2,4,3,5,1]
Output: 3

Note:
The length of the given array will not exceed 50,000.
All the numbers in the input array are in the range of 32-bit integer.

  

解法:

解法一:FenwickTree

方針:遍歷陣列,對每一個新遍歷到的數nums[j],看已經遍歷過的數裡面,是否存在滿足要求的nums[i](nums[i] > 2*nums[j])

我們使用FenwickTree來記錄到目前為止,滿足要求的nums[i]總共有多少個。

每遍歷一個數,update到FenwickTree中。

presum來得到滿足要求的nums[i]的個數。

這裡,我們需要使用輔助陣列,sortnums來存放經過排序後的nums

使用FenwickTree來對應sortnums的計數。(相同index下)

具體做法:

每遍歷一個nums[j]

在sortnums中找到<=2*nums[j]的index

那麼在FenwickTree中,到目前為止所有個數-0~index的個數= >2*nums[j]的個數

在sortnums中找到nums[j]的index

更新到FenwickTree.update(index,1)

⚠️ 注意:這裡對於重複相同的元素,index可能會重複,但是沒關係,我們要求的是計數個數,(不需要index一一對應)直接使用update方法更新增加delta=1即可。

程式碼參考:

 1 class FenwickTree {
 2 public:
 3     FenwickTree(int n):preSum(n+1, 0){}
 4     void update(int
i, int delta){ 5 while(i<preSum.size()){ 6 preSum[i]+=delta; 7 i+=lowbit(i); 8 } 9 } 10 int getPreSum(int i){ 11 int sum=0; 12 while(i>0){ 13 sum+=preSum[i]; 14 i-=lowbit(i); 15 } 16 return sum; 17 } 18 private: 19 vector<int> preSum; 20 int lowbit(int x){ 21 return x&(-x); 22 } 23 }; 24 25 class Solution { 26 public: 27 int reversePairs(vector<int>& nums) { 28 FenwickTree tree(nums.size()); 29 vector<int> sortnums(nums); 30 sort(sortnums.begin(), sortnums.end()); 31 int res=0; 32 for(int i=0; i<nums.size(); i++){ 33 //對每一個j,前面遍歷過的每個i,是否有滿足條件nums[i] > 2*nums[j]的 34 //找大於2*nums[j]的位置 35 //sort從小到大,先找<=2*nums[j]的位置 36 int dislower=distance(sortnums.begin(), upper_bound(sortnums.begin(),sortnums.end(),(long long)2*nums[i])); 37 res+=(tree.getPreSum(nums.size())-tree.getPreSum(dislower)); 38 //將遍歷過的元素更新到tree 39 int pos_sorted_i=distance(sortnums.begin(), lower_bound(sortnums.begin(),sortnums.end(),nums[i]))+1; 40 tree.update(pos_sorted_i, 1); 41 } 42 return res; 43 } 44 };

解法二:

歸併排序 merge Sort

在歸併排序的合併兩個有序數列過程中,追加一個判斷,

  • if 左邊的數>=2倍的右邊的數:res+=左邊剩下的數。
  • 左邊下一個數

程式碼參考:

 1 class Solution {
 2 public:
 3     int reversePairs(vector<int>& nums) {
 4         int res=0;
 5         if(nums.size()==0) return 0;
 6         res = mergeSort(nums, 0, nums.size()-1);
 7         return res;
 8     }
 9     int mergeSort(vector<int>& nums, int start, int end) {
10         int res=0;
11         if (start==end) {
12             return 0;
13         }
14         int mid = start + (end - start) / 2;
15         res+=mergeSort(nums, start, mid);
16         res+=mergeSort(nums, mid+1, end);
17         res+=merge(nums, start, mid, end);
18         return res;
19     }
20     int merge(vector<int>& nums, int start, int mid, int end) {
21         int p = start, q = mid+1;
22         int res=0;
23         while(p<=mid && q<=end) {
24             if(nums[p] > (long long)2*nums[q]){
25                 res+=(mid-p+1);
26                 q++;
27             }else{
28                 p++;
29             }
30         }
31         
32         vector<int> a(end-start+1, 0);
33         p = start, q = mid+1;
34         int ai=0;
35         while(p<=mid && q<=end) {
36             if(nums[p] < nums[q]){
37                 a[ai]=nums[p];
38                 p++,ai++;
39             }else{
40                 a[ai]=nums[q];
41                 q++,ai++;                
42             }
43         }
44         while(p<=mid){
45             a[ai++]=nums[p++];
46         }
47         while(q<=end){
48             a[ai++]=nums[q++];
49         }
50         copy(a.begin(), a.end(), nums.begin()+start);
51         return res;
52     }
53 };