好弱啊,这个题目折腾了好久。
构造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;
}