問(wèn)題:
http://acm.pku.edu.cn/JudgeOnline/problem?id=1007http://acm.pku.edu.cn/JudgeOnline/problem?id=2299思路:
求逆序?qū)Φ膫€(gè)數(shù)
這兩題的基本問(wèn)題是一致的,給定一個(gè)數(shù)組(包括字符串),求出逆序?qū)Φ膫€(gè)數(shù)
1. 最簡(jiǎn)單的方法
兩層循環(huán),復(fù)雜度O(n^2)
1 int
2 inversion_cal(char *str)
3 {
4 int i, j, count = 0;
5 int len = strlen(str);
6 for(i=0; i<len; i++)
7 for(j=i+1; j<len; j++)
8 if(str[i] > str[j])
9 ++count;
10 return count;
11 }
2.
歸并排序&分治思想其實(shí),只要將歸并排序稍加修改,就是一個(gè)求解逆序?qū)€(gè)數(shù)問(wèn)題的O(nlgn)方法
要理解的是這其中涉及的分治思想(三步驟):
a. 分解為子問(wèn)題
b. 求解子問(wèn)題
c. 合并子問(wèn)題的解來(lái)得到原問(wèn)題的解
具體對(duì)應(yīng)到求逆序?qū)€(gè)數(shù)的問(wèn)題:
a. 將原數(shù)組分解為前后兩個(gè)子數(shù)組
b. 求解子數(shù)組的逆序?qū)€(gè)數(shù)
c. 合并前后子數(shù)組,同時(shí)計(jì)算逆序?qū)€(gè)數(shù)(這個(gè)是指逆序?qū)Φ牡谝粋€(gè)數(shù)在前子數(shù)組中,而第二個(gè)數(shù)在后子數(shù)組中)
1 long long
2 merge_count(long *arr, long *temp, long begin, long end)
3 {
4 if(begin >= end)
5 return 0;
6 long i, j, k, mid = (begin+end)/2;
7 long long rt = 0;
8 rt += merge_count(arr, temp, begin, mid);
9 rt += merge_count(arr, temp, mid+1, end);
10 i = k = begin;
11 j = mid+1;
12 while(i<=mid && j<=end) {
13 if(arr[i] <= arr[j])
14 temp[k++] = arr[i++];
15 else {
16 temp[k++] = arr[j++];
17 rt += (mid-i+1);
18 }
19 }
20 for( ; i<=mid; i++)
21 temp[k++] = arr[i];
22 for( ; j<=end; j++) {
23 temp[k++] = arr[j];
24 rt += (mid-i+1);
25 }
26 /* copy */
27 for(k=begin; k<=end; k++)
28 arr[k] = temp[k];
29 return rt;
30 }
3. 特例方法
針對(duì)PKU 1007該題的特殊性: 字符串中只包含A, G, T, C四個(gè)字母,還有一種更加簡(jiǎn)單的O(n)方法
1 int
2 inversion_cal2(char *str)
3 {
4 int i, temp[4], count = 0;
5 int len = strlen(str);
6 memset(temp, 0, sizeof(temp));
7 for(i=len-1; i>=0; i--) {
8 switch(str[i]) {
9 case 'A':
10 ++temp[0];
11 break;
12 case 'C':
13 ++temp[1];
14 count += temp[0];
15 break;
16 case 'G':
17 ++temp[2];
18 count += (temp[0]+temp[1]);
19 break;
20 case 'T':
21 ++temp[3];
22 count += (temp[0]+temp[1]+temp[2]);
23 break;
24 }
25 }
26 return count;
27 }