假设我们要排列存储在任何数组中的n个数字,以使所有负值都出现在所有正值之前。那么如何找到最坏情况下所需的最小交换数?
答案 0 :(得分:0)
您可以使用两个指针方法。
首先移动所有负数并计算所需的交换次数
将所有负数移动到位并计算所需的交换次数
比较这些交换次数以获得最小交换次数。
这是C ++实现:
int minimumExchange(vector<int>& arr) {
int result = INT_MAX;
int countFirst = 0, countLast = 0;
int n = arr.size();
vector<int> tmp(arr);
int left = 0, right = 0;
while(right < n) {
if(arr[right] < 0) {
swap(arr[left], arr[right]);
if(left != right) countFirst++;
left++;
}
right++;
}
arr = tmp;
left = n - 1, right = n - 1;
while(right >= 0) {
if(arr[right] < 0) {
swap(arr[left], arr[right]);
if(left != right) countLast++;
left--;
}
right--;
}
result = min(countFirst, countLast);
return result;
}
您可以找到工作代码here。
时间复杂度为O(n)
,其中n
是数组的大小。
答案 1 :(得分:-1)
您只需要处理一半的项目。
想象一个包含6个元素的列表。在最坏的情况下,所有负数都在正数之后:
1,2,3,-1,-2,-3
要解决此问题,您需要2个指针:
+1,+2,+3,-1,-2,-3
^ ^
i j
,当它迭代3次时:
-1,+2,+3,+1,-2,-3
^ ^
-1,-2,+3,+1,+2,-3
^ ^
-1,-2,-3,+1,+2,+3
^ ^
所以您的解决方案是:
let X be your list
let i = 0
let j0 = len(X)/2 + 1, rounded down
let j = j0
while j < len(X)
if X[i] < 0
i ++
else if X[j] < 0
swap X[i] with X[j]
i ++
j ++
else
j ++
function printList(list, i, j) {
let str = list.map((x, xi) => {
if (xi == i) {
return "[" + x + "]";
} else if (xi == j) {
return "<" + x + ">";
} else {
return x;
}
}).join(" ");
console.log(str);
}
function foo(X) {
let i = 0
let j0 = Math.floor(X.length / 2)
let j = j0
while (j < X.length) {
printList(X, i, j);
if (X[i] < 0) {
i ++;
} else if (X[j] < 0) {
let tmp = X[i];
X[i] = X[j];
X[j] = tmp;
i ++;
j ++;
} else {
j ++;
}
}
printList(X);
}
foo([-1, 2, -3, 4, -5]);
console.log("----");
foo([1, -2, 3, 4, -1, 5]);
console.log("----");