每日一题:1、前负后正


题目

(2018吉林大学941)一个长度为 n 的数组由负数、0、正数组成。编写函数,将其重新排序为前段都是负数,后段均为非负数的结构。要求时间复杂度为 O(n)。


一、算法的整体思想

使用了双指针,分别指向了顺序表的头与尾。从前至后遍历顺序表。
如果该结点为负数,将其与头指针交换,头指针指向向下一个结点,从交换前的后一结点开始往后遍历;
如果该结点为0,则继续遍历不用交换结点(注意此时头指针未随i一起往后移动)
如果该结点为正数,将其与尾指针交换,尾指针指向前一结点,从交换前的结点指针处开始遍历(此时结点指针处就是i指向处,也就是继续刚刚的i处继续遍历,检察刚刚换回的尾指针所指的元素 )

二、程序编写

2.1代码

代码如下:

void Sort(int A[],int length)//输入:数组 A[],数组长度length
{
	int head,rear,count;//头尾指针 count为计算比较元素的个数
	head=0;count=0
	rear=length-1;//初始化
	for(int i=head;count<length;)//终止条件
	{
		if(a[i]>0) //如果该结点为正数,将其与尾指针交换
		{
		swap(&a[i],&a[rear]);
		rear--;count++;//计数+1
		}
		if(a[i]==0)//如果该结点为0,则不做变动,头指针保持不变,继续做遍历
		{
		i++;count++;//继续计数+1,接着往后遍历
		}
		if(a[i]<0)//如果该结点为负数,,将该结点与 头指针做交换,并将头指针往后指一个
		{
		swap(&a[i],&a[head]);
		i++;
		head++;
		count++;//计数+1
		}
	}
}
 

void swap(int *a, int *b) 
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
/*或者C++的引用方法
void swap(&a,&b)
{
	int temp;
	temp=a;
	a=b;
	b=temp;
}
此时上面的调用swap(a[i],a[j])*/

2.2相关基础补充

2.2.1 for循环语句

for循环语句要求,摘自C语言中文网

2.2.2 指针和指针指向的类型

  指针的类型和指针指向的类型,以下面的例子来说明:(*是间接访问符 /解引用 ,&取地址符)
int* p;
char* p;
int* *p;
int (*p)[3];
int* (*p)[3];
  从语法的角度看,你只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型。这是指针本身所具有的类型。上述例子中指针的类型为:
int* ptr; //指针的类型是int*
char* ptr; //指针的类型是char*
int* ptr; //指针的类型是int*
int (ptr)[3]; //指针的类型是int()[3]
int* (ptr)[4];//指针的类型是int()[4]
  从语法上看,你只须把指针声明语句中的指针名字和名字左边的指针声明符去掉,剩下的就是指针所指向的类型。上述例子中指针指向的类型为:
int* ptr; //指针所指向的类型是int
char* ptr; //指针所指向的的类型是char
int* ptr; //指针所指向的的类型是int
int (*ptr)[3]; //指针所指向的的类型是int ()[3]
int* (ptr)[4]; //指针所指向的的类型是int ()[4]

三、时间复杂度分析

本算法只有一层循环,最坏情况时遍历整个数组,故时间复杂度为O(n)。

四、总结

此题要注意双指针的运用,在运用时要有头指针,尾指针,以及计数器count,
另外还有遍历数组时的变量i,不要搞混。
另外此题还可以借助一个新数组,将原数组进行遍历,将负数放在新数组的前侧,非负数放在新数组的后侧。
此代码的时间复杂度是O(n),但是空间复杂度是O(n),而上文代码的空间复杂度是O(1)。

请添加图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值