• 微软2014实习生及秋令营技术类职位在线测试-题目3 : Reduce inversion count


     这道题有几个关键的地方:
    1、计算一个数组的逆序对的个数。
      我采用遍历的方式,用两重循环,时间复杂度O(N^2),应该没有效率更高的方法【代码27-32】;
    2、找到一对(d[j],d[k],设j<k),通过交换他们,可以使得逆序对数减少最多。
      首先看下交换任意一对(d[j],d[k],设j<k),会对这个数组的逆序对的个数造成什么样的影响。认真思考下,可以知道交换(d[j],d[k])只影响在j到k之间的元素的逆序情况,而对这个范围之外的逆序对的个数是不造成影响的,因为[0到j-1]的任意元素相对[j到k]的任意元素的先后顺序,以及[k到len-1]的任意元素相对[j到k]的任意元素的先后顺序都没有变化。那么就只需要考虑交换后[i到j]之间逆序对变化的个数。交换(d[j],d[k])后,减少的逆序对是由下标在[j,k)之间且其元素大于d[k],以及下标在(j,k]之间且其元素小于d[j],而增加的逆序对是由下标在[j,k)之间且其元素小于d[k],以及下标在(j,k]之间且其元素大于d[j]【代码41-51】。另外一个值得注意的是只有当d[k]<d[j]时,交换才能减少逆序对数。
    1
    #include<stdio.h> 2 int main(void) 3 { 4 char data[120]; 5 int len = 0; 6 int d[50]; 7 int j =0,k=0,l =0,i=0; 8 int cnt =0,max =0,x=0,y=0,n=0; 9 while(gets(data)) 10 { 11 len = 0; 12 i =0; 13 j = 0; 14 cnt =0,max =0;; 15 n=0; 16 //operate input 17 while(data[i]!='') 18 { 19 if(data[i]!=',') 20 { 21 d[j++] = data[i]-'0'; 22 len++; 23 } 24 i++; 25 } 26 //count orignal reversion pairs 27 for(j=0;j<len;j++) 28 { 29 for(k=j+1;k<len;k++) 30 if(d[j]>d[k]) 31 cnt++; 32 } 33 //FIND the right pair which can largest reduce the count 34 for(j=0;j<len-1;j++) 35 { 36 for(k=j+1;k<len;k++) 37 { 38 n=0; 39 if(d[k]>d[j]) 40 continue; 41 for(l=j;l<k;l++) 42 { 43 if(d[l]>d[j]) 44 n--; 45 if(d[l]<d[j]) 46 n++; 47 if(d[l]>d[k]) 48 n++; 49 if(d[l]<d[k]) 50 n--; 51 } 52 if(n>max) 53 max = n; 54 } 55 } 56 57 printf("%d ",cnt-max); 58 59 } 60 return 0; 61 }
    最后声明下,作为菜鸟一个,没有在给定时间里,完整的把代码中的几个条件考虑进去,因此这里的程序不知道是否可以AC,但是我跑些case的结果是对的。
    有问题可以和我联系,bettyting2010#163 dot com
  • 相关阅读:
    chess「dp」
    e[树上主席树]
    d[贪心]
    神盐皇
    LA 8043. ACM-ICPC World Finals 2017 E. Need for Speed
    八数码问题
    UVa 679. Dropping Balls
    关于时间复杂度
    欧拉序列 (Euler Tour)
    莫队算法
  • 原文地址:https://www.cnblogs.com/echoht/p/3661425.html
Copyright © 2020-2023  润新知