好弱啊,这个题目折腾了好久。
构造hash表用来维护各个元素所在的位置,利用map维护一颗红黑树来保存还未确定的元素的位置。
(1)用0不断的跟其他元素交换,每次交换都会保证一个元素在正确的位置。
(2)交换的过程中可能使得元素0到第0个位置,此时用0与某个还未在正确位置的元素交换。
循环(1)(2)直至所有元素都在正确的位置。
出现(2)这种情况的最大次数可能N,因为出现一次这种情况,一定会在接下来运行(1)的时候保证至少一个元素被交换到正确的位置。综上所述,最大交换次数应该不会高于2*N,每次交换会维护一次map,所以最终的算法复杂度应该为O(NlogN).
// 1067. Sort with Swap.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include <map> using namespace std; const int N = 100003; int a[N], hashTab[N]; map<int, int> cmap; void swap(int &m1, int &m2){ int temp = m1; m1 = m2; m2 = temp; } int main() { int n, cnt = 0, diff; cin >> n; for(int i = 0; i < n; i++){ cin >> a[i]; hashTab[a[i]] = i; if(i != 0 && a[i] != i) cmap[i] = i; } do{ while(hashTab[0] != 0){ swap(a[hashTab[0]], a[hashTab[hashTab[0]]]); int tmp = hashTab[0]; hashTab[0] = hashTab[hashTab[0]]; hashTab[tmp] = tmp; map<int, int>::iterator mIte = cmap.find(tmp); cmap.erase(mIte); cnt++; } if(cmap.size() != 0){ map<int, int>::iterator mIte = cmap.begin(); cnt++; hashTab[0] = hashTab[mIte -> first]; hashTab[mIte -> first] = 0; swap(a[hashTab[mIte -> first]], a[0]); } } while(cmap.size() != 0); cout << cnt << endl; return 0; }
改进版本:
弃用map,维护一个bool数组used[]保存某个元素是否已经确定好,每当一个元素被确定下来,就赋值为true(初始时数组清0)。
设置一个在第2步可以被用来交换的位置swapPos,初始时swapPos=1,由某个元素确定下来,就要询问该位置是否和swapPos相等,如果相等,则相应的swapPos后移直至一个还未确定好的位置pos(即used[pos]==false)。由此观之,swapPos后移顶多后移N个位置,每次在第二步寻找与0交换的元素,可以直接用a[swapPos]与之交换。所以最终的算法复杂度应为O(3*N)。
// 1067. Sort with Swap.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include <map> using namespace std; const int N = 100003; int a[N], hashTab[N]; bool used[N]; void swap(int &m1, int &m2){ int temp = m1; m1 = m2; m2 = temp; } int main() { int n, cnt = 0; cin >> n; memset(used, 0, sizeof(used)); for(int i = 0; i < n; i++){ cin >> a[i]; hashTab[a[i]] = i; if(a[i] == i) used[i] = true; } int swapPos = 1; while(used[swapPos]) swapPos++; do{ while(hashTab[0] != 0){ swap(a[hashTab[0]], a[hashTab[hashTab[0]]]); int tmp = hashTab[0]; hashTab[0] = hashTab[hashTab[0]]; hashTab[tmp] = tmp; used[tmp] = true; if(tmp == swapPos){ swapPos++; while(used[swapPos]) swapPos++; } cnt++; } if(swapPos != n){ cnt++; hashTab[0] = hashTab[swapPos]; hashTab[swapPos] = 0; swap(a[hashTab[swapPos]], a[0]); } } while(swapPos != n); cout << cnt << endl; return 0; }