test001
1 题目
/**
* (2018吉林大学941)一个长度为 n 的数组由负数、0、正数组成。编写函数,将其重新排序为前段都是负数,后段均为非负数的结构。
* 要求时间复杂度为 O(n)。
*/
2 题解
2.1 法一
2.1.1 解题思路
设置双指针,通过将负值与头指针交换,正值与尾指针交换,最终可以形成一个左负右正中间零的顺序表。
其中,需要理解的是头尾指针的移动以及遍历顺序表的索引值i如何自增。
i从第0个位置开始扫描顺序表。
若正,与尾指针交换,此时i不自增。因为还不能知道交换来的这个数是正是负。
若为0,则i自增。
若负,与头指针交换,此时i可自增。因为前面扫到的正数都抛到后面去了,前面不会出现正数。
可以发现,当头指针向后移动或者尾指针向前移动时,其实就是确定了一个元素的最终位置。
2.1.2 过程
程序验证:
2.1.3 结果
2.1.4 结果分析
时间复杂度O(n),空间复杂度O(1)
2.1.5 代码
void switch_arr(int arr[],int len){
int head = 0;
int rear = len - 1;
int count = 0;
int i = 0;
while (count < len){
if(arr[i] < 0){
_swap(arr, i, head);
head++;
i++;
count++;
}else if(arr[i] == 0){
i++;
count++;
}else if(arr[i] > 0){
_swap(arr, i, rear);
rear--;
count++;
}
// cout<<"过程数组:";
// print_arr(arr,len);
}
}
2.2 法二
2.2.1 解题思路
牺牲空间换时间,直接开辟另外一个数组填入数值即可。这里也需要左右指针。
2.2.2 过程
比较简单,这里省略了。
2.2.3 结果
2.2.4 结果分析
时间复杂度O(n),空间复杂度O(n)
2.2.5 代码
int* switch_arr_2(int arr[],int len){
int* copy_arr = (int*)malloc(sizeof (int) * len);
int head = 0;
int rear = len-1;
for (int i = 0; i < len; ++i) {
if(arr[i]<0){
copy_arr[head++] = arr[i];
}else if(arr[i]>0){
copy_arr[rear--] = arr[i];
}
}
for (int i = head; i <= rear; ++i) {
copy_arr[i] = 0;
}
return copy_arr;
}