3、已知数组 A[n]中的元素为非零整数,设计一个时间复杂度为 O(n)的函数将其调整为左右两部分,左边所有元素小于 0,右边所有元素大于 0。①-④填空。 void adjust(int A[],
时间: 2024-12-19 09:15:13 浏览: 15
可以使用双指针法来解决这个问题,步骤如下:
1. 定义两个指针,一个 `left` 初始化为 0,用于追踪当前遍历到的左侧第一个负数的位置;另一个 `right` 初始化为 n - 1,表示右侧第一个正数的位置。
2. **循环条件**:只要 `left < right`,说明还有未处理的元素。这保证了时间复杂度为 O(n),因为我们最多只遍历整个数组一次。
3. **检查并交换**:
a. 检查 `A[left]` 是否为正数。如果是正数,则不需要移动 `left`,因为它已经在正确的位置上。
b. 同理,检查 `A[right]` 是否为负数。如果是负数,则不需要移动 `right`。
4. 如果 `A[left] <= 0` 且 `A[right] > 0`,则交换这两个位置的值,`A[left++] = A[right];` 和 `A[right--] = A[left];`。这样就实现了左侧元素小于等于0,右侧元素大于0的要求。
5. 当 `A[left]` 变为正数且 `A[right]` 变为负数时,跳出循环。
6. 最后,如果数组长度是奇数,中间的那个元素可能会保持原来的正或负,但这不影响结果。
以下是完整的函数实现(假设数组名为`arr`,为了简洁这里省略了类型声明):
```c++
void adjust(int arr[], int n) {
int left = 0;
int right = n - 1;
while (left < right) {
if (arr[left] > 0 && arr[right] >= 0) { // 如果左侧是正数,右侧是非负数
swap(arr[left], arr[right]);
right--;
} else if (arr[left] <= 0 && arr[right] < 0) { // 否则继续寻找
left++;
}
}
}
```
阅读全文