针对前一次笔试的总结与反思

这次回顾自己笔试中遇到的问题及反思,这些问题很多博客已经讲得非常清楚,学习了很多,大概归纳下自己学习的内容。

1、数组和链表

数组是静态分配内存,在一开始创建数组时,内存大小就已固定,数组创建默认初值为0,存储的地址是连续的。链表动态分配内存,根据后面的增删内存大小会有改变,链表的地址既可以是连续的,也可以是不连续的。

数组的根据下标查询数据所以,查询数据的时间复杂度为O(1),数组插入、删除都会对涉及到数组的后面(前面)元素的移位,时间复杂度为O(n);链表的查询会从第一个结点(不一定是头结点)开始查询,所以查询数据的时间复杂度为O(n),链表的插入、删除都只涉及一个元素,所以时间复杂度为O(1)。

数组优点:查询,修改快。缺点:插入、删除慢,内存固定,不能扩展,要求连续的内存地址。

链表优点:插入、删除快,内存动态分配,地址可不连续   缺点:查询、修改都需要从第一个节点遍历。

头结点与第一节点的区别:第一结点有可能为头结点,有可能不为头结点,因为头结点不是必须的。头结点是为了操作的通用和方便而设立的,放在第一个元素的结点之前,其数据域一般无意义(或者存放链表的长度),有了头结点对于第一个元素结点操作就和其他元素接点一致。

头指针为指向第一个结点的指针,若链表有头结点,则指向头结点,没有则指向第一个元素结点。头指针不为空,为必要元素。

2、单链表和双链表

单链表只有一个指向下一个结点的指针,而双向链表具有指向下一个结点和上一个结点的指针。单链表在删除某个结点,需要获取到要删除的结点的前驱,进行删除的方法有两种,一边定位要删除的结点,一边定位其前驱;先找到要删除的结点,再找到其前驱。双链表因为具有前后两个方向的指针,所以只需定位到删除的结点就可以。通常采用单链表是因为双链表多一个指针存储,在大规模存储下,人们通常采用时间换空间的方法。

3、冒泡算法

从小到大:第一轮,冒泡算法是通过第一个数据和第二个数据比较大小,将比较大的数据换到第二个数据位置,然后第二个数据和第三个数据比较大小,将更大的数据放到第三个位置,不断执行,总共执行n-1次(n为数组中的大小),之后最大的数据就会被存放到最后的位置。第二轮从第一个位置开始,总共执行n-2次,第三轮执行n-3次...总共执行的轮数为n-1轮。

4、选择排序算法

从小到大:第一轮,从所有元素中找到最小的元素,将最小的元素和第一个元素进行数值交换,第二轮对第二个元素到最后的元素查找最小的元素,然后将最小元素和第二个元素进行数值交换,第三轮...每一轮会选出最小的元素按顺序排放在在数组中。总共执行的轮数为n-1轮。

5、哈夫曼树

构建哈夫曼树首先对这串数字从小到大排序,然后然后取其中的两个最小的数字最为子叶,两个数字之和,再次添加到去掉了这两个数字的那串数字中,再次排序,再取其中两个最小的数字作为子叶:情况一,这两个最小的数字包含上一次两个数字之和,则在上层构建只有一个叶子节点的分支;情况二,不包含上一次最小数字之和,则是同一层次的两个叶子节点的分支。持续构造下去...带权路径长度为叶子结点所在第几层乘以叶子结点的权。

例如:1,2,3,5

第一次最小的两数:1,2                  第二次最小的数为 3,3 (其中一个位前两最小数之和)

那么第二次的分叉就应该位于 1,2结点的上层。

6、笔试中遇到一个编程问题

(1)a[6]={1,-1,3,-2,0,2}

输出其中任意三个数字的和为0的组合,要求不重复。

做笔试的时候,脑袋被严重阻塞,完全没有分析好题目。昨晚睡觉前回想起这个问题发现就是一个组合问题。从数学的思维来讲就是,第一次,我从这六个数字中选出一个数字,然后第二次我再从剩余5个数字选出一个数字,第三次从剩余的4个数字选出一个数字,但是数学可以直接除去重复的数字,程序不行。不过程序也有好处,程序可以不需要随机性,直接遍历就ok,只要保证不遍历相同的数字就行。所以具体思路如下:

for(int i=0;i<=3;i++)//从第一个数字开始到第四个数字

for(int j=i+1;j<=4;j++)//从第一个数字的后一个数字到第五个数字

for(int k=j+1;k<=5;k++)//第一个数字的后两个数字开始到第六个数字

{

if(a[i]+a[j]+a[k]==0)

cout<<a[i]<<a[j]<<a[k]<<endl;

}

这样就能保证所有组合全部遍历过了,并且不会有相同的组合

(2)笔试只有这一道编程题,睡觉前想到了组合自然也就想到了排列,所以后来就思考了下排列如何实现,其实排列更简单,只要保证不要有两个及两个以上取到相同数字就可以了。具体方法如下:

 

for(int i=0;i<=5;i++)

for(int j=0;j<=5;j++)

{

if(j==i)

continue;

for(int k=0;k<=5;k++)

{

if(k==i||k==j)

continue;

if(a[i]+a[j]+a[k]==0)

cout<<a[i]<<a[j]<<a[k]<<endl;

}

}

 

链表相关内容主要学习了这个博客:https://blog.csdn.net/qq_26626709/article/details/52203924

讲得很仔细,如果有看到了这篇博客的同学不太了解链表的内容,可以参考学习。

以上,祝好。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值