微软2014见习生及秋令营技术类职位在线测试第3题
昨天,有很多同学参加微软2014实习生及秋令营技术类职位在线测试,有些还拿了350分,实在是厉害。
第三题是这样的
- 样例输入
-
3,1,2 1,2,3,4,5
- 样例输出
-
1 0
Description
Find a pair in an integer array that swapping them would maximally decrease the inversion count of the array. If such a pair exists, return the new inversion count; otherwise returns the original inversion count.
Definition of Inversion: Let (A[0], A[1] ... A[n]) be a sequence of n numbers. If i < j and A[i] > A[j], then the pair (i, j) is called inversion of A.
Example:
Count(Inversion({3, 1, 2})) = Count({3, 1}, {3, 2}) = 2
InversionCountOfSwap({3, 1, 2})=>
{
InversionCount({1, 3, 2}) = 1 <-- swapping 1 with 3, decreases inversion count by 1
InversionCount({2, 1, 3}) = 1 <-- swapping 2 with 3, decreases inversion count by 1
InversionCount({3, 2, 1}) = 3 <-- swapping 1 with 2 , increases inversion count by 1
}
Input
Input consists of multiple cases, one case per line.Each case consists of a sequence of integers separated by comma.
Output
For each case, print exactly one line with the new inversion count or the original inversion count if it cannot be reduced.
就是给我们一个数组,让我们只交换其中的两个元素一次,使得逆序数降低的最多。
最普通的方法,无非是遍历O(n^2),然后每次计算逆序数,复杂度是O(n^4)
稍微改进一下,计算逆序数利用分治法,修改mergesort,复杂度也还是O(n^3*logn)
再稍微改进一下 , 当我们交换a[i]和a[j]时,对i前面和j后面的逆序数不产生影响,只对i,j中间的产生影响
今天,我又尝试了一下贪心算法,就是交换改变距离最大的,那么什么是距离最大呢?
比如我有数组5,3,1,2,4
排序完的话是1,2,3,4,5
5,3的距离是0,这是因为5换到3后,距离排序完的5近了一步,但是3换过去距离排序完的3又远了。
5,1的距离是4,交换后都近了2格
#include <iostream> #include <vector> #include <algorithm> #include <map> #include <time.h> using namespace std; int abs(int a,int b) { if(a > b) return b-a; return a-b; } int count1(vector<int>& array, int len) { int r = 0; for(int i = 0;i < len;i++){ for(int j = i+1;j< len;j++){ if(array[i] > array[j]) r++; } } return r; } int count2(vector<int>& array, int len) { vector<int>dup = array; sort(dup.begin(),dup.end()); map<int,int>index; for(int i = 0;i<len;i++) index[dup[i]] = i; int r1 = 0,r2 = 0,diff = -1; for(int i = 0;i < len;i++) { for(int j = i+1; j < len;j++) { if(array[i] > array[j]) { int index1 = index[array[i]]; int index2 = index[array[j]]; int differ1 = abs(index1 - i) - abs(index1 - j); int differ2 = abs(index2 - j) - abs(index2 - i); if((differ1+differ2) > diff) { diff = differ1+differ2; r1 = i; r2 = j; } } } } int tmp = array[r1]; array[r1] = array[r2]; array[r2] = tmp; int count = count1(array,len); return count; } // random generator function: int myrandom (int i) { return std::rand()%i;} int main(int argv, char** args) { srand(time(NULL)); vector<int>arr; int len = 100; for(int i = 1;i <= len; i++) arr.push_back(i); while(1){ random_shuffle(arr.begin(), arr.end(), myrandom); //计算min_count int min_count = count1(arr, len); for(int i = 0;i < len;i++){ for(int j = i+1;j < len;j++){ if(arr[i] > arr[j]){ int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; int count = count1(arr,len); if(min_count > count) min_count = count; tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } } } cout << min_count << endl; //第二种方法 int min_count_2 = count2(arr, len); cout << min_count_2 <<endl; if(min_count != min_count_2)break; } return 0; }
这是最原始的方法和贪心算法在一起,当我令数组大小为100,下面是我的输出
2592
2592
2210
2210
2517
2517
2717
2717
2296
2296
2370
2370
2283
2283
2423
2423
2254
2254
2402
2408
实在是想不出什么好解法了,如果你知道,一定要告诉我!!