今天开始进入算法环节,从头开始手撸各种算法,这里使用C语言,后续我会补充Java版的。
大家都知道顺序表是一个线性表,那么他就具有线性表的特性,那就是随机存取,它的逻辑地址跟物理地址都是相同的,都可以用下标解决,Java的话有很多封装工具可以使用,更方便一些,对于C可能要麻烦一些,但是要想打好坚实的基础我们不挑语言,而且C的执行速度是优于Java的。
正品开始啦!!!
第一道题(开胃菜):有一个数组[1,2,3,4,5,6,7] 变成 [7,6,5,4,3,2,1]很简单吧,我相信不会有人不会的,Java的话只需要调用一个方法就搞定了,自行百度一下,数组逆置的函数是什么
C语言:
#include <stdio.h>
/**
* 顺序表算法1:数组倒置(部分)
* 思路:对位交换
* 复杂度分析:时间O(n/2) --> O(n)、空间O(1)
* 1,2,3,4,5,6,7 from,to,i = 0,temp:暂存变量
*/
void Reverse(int R[],int from,int to){
int temp;
for (int i = 0; i < (to - from + 1)/2; i++) {
temp = R[from+i];
R[from+i] = R[to-i];
R[to-i] = temp;
}
}
/**
* 数组遍历打印
* @param R
*/
void printf_arr(int R[], int length){
for (int i = 0; i < length; ++i){
printf("%d ", R[i]);
}
}
/**
* 顺序表
* @return
*/
int main(void) {
// 1、数组倒置
int R[] = {1,2,3,4,5,6,7};
Reverse(R,1,5);
printf_arr(R,sizeof(R) / sizeof(R[0]));
return 0;
}
我这里采用的方法是对位交换,不理解?那我给大家画个图就理解了,图示如下:
图画的不是很形象将就看一下,相同颜色对调位置是不是就是我们想要的结果了,那么我们的循环次数就是
[(目标元素下标)-(开始元素下标)+1]/2
上面给出的代码其实是可以实现数组部分元素逆置的。
性能分析:时间复杂度方面我们只遍历了一次数组,循环次数是(to - from + 1)/2就是上面给出的公式。空间复杂度我们借助了一个temp变量做承接所以空间复杂度为O(1)
时间复杂度:O(n)
空间复杂度:O(1)
今天的主菜开始:
听题:
设将n(n>1)个整数存放到一维数组R中。设计一个在时间和空间两方面都尽可能高效的算法.将R中保存的序列循环左移p(0<p<n)个位置,即将R中的数据由(X0,X1..n-1)变为(Xp,Xo+1,...,Xn-1,X0,X1,...,Xp-1)
题解:这道题看起来就高大上很多了,乍一看挺懵的,我来分析一下,emmm,无非就是将一个数组[1,2,3,4,5,6,7]变成[3,4,5,6,7,1,2]其实就是把后半部分往前提了,暴力解其实不难三个遍历也能搞定,不过用暴力解他的空间复杂度会是O(n),那可不行,忍不了,其实仔细看就能发现,这道题一定是跟上面那道题有关系的,就是方法不是很好想,我用的方法其实就是调用了三遍前面的代码就实现了。
上代码:
/**
* 顺序表
* @return
*/
int main(void) {
int R[] = {1,2,3,4,5,6,7};
// 2、原地逆置:原题:设将n(n>1)个整数存放到一维数组R中。设计一个在时间和空间两方面都尽可能高效的算法.将R中保存的序列循环左移p(0<p<n)个位置,即将R中的数据由(X0,X1..n-1)变为(Xp,Xo+1,...,Xn-1,X0,X1,...,Xp-1)
Reverse(R,0,1);
Reverse(R,2,6);
Reverse(R,0,6);
printf_arr(R,sizeof(R) / sizeof(R[0]));
return 0;
}
把数组逆置的main方法替换就OK了。
性能分析:由于我们没有做代码变动,所以时间跟空间复杂度跟数组逆置是完全一样的。
时间复杂度:O(n)
空间复杂度:O(1)
ok!!!今天分享就到这,后续还会继续更新,留个小关注吧!!!!