关于两道排序面试题的讨论

7 篇文章 0 订阅

缘起

不久前,我去一家创业公司面试,因为他们没有专业的java开发,于是请了一个颇有经验的人出了两道笔试题:1.二分查找的代码实现,2.谈谈关于软件设计原则的看法。也是比较难较难得了,很少有人会问到这些方面,特别是设计原则这块,有很多开发者都不了解这方面的知识。而第一题是很容易,但要是撸一串代码也会为难一批有十年以经验的开发者了(当然我还是有这个自信的)。
在远程口试中,对方问到了两个简单的排序,我觉得这两个排序虽然简单,但很有意思。因为两道题目很相似,但解法确有些异差。

正文

题一

给定三个数组:
数组a,长度m;
数组b,长度n;
数组c长度m+n;
其中a与b存放了有序的数据,c为空数组,要求将a与了组合放入c中,且让c为有序数组。跟我以前见过的面试题很相似
以下是伪代码的实现示例:

int pa=0,pb=0,pc=0;//指向数组a,b,c的三个指针;
while(pa<a.lenght && pb < b.lenght){
	if(a[pa]<=b[pb]){
		c[pc] = p[pa++];
	}else{
		c[pc]=p[pb++]
	}
	pc++;
}
if(pa<a.a.lenght){
	arrayCopy(a,pa,(a.lenght-pa),c);// 将a中剩余的数组考贝到c中
}else if(pb <b.lenght){
	arrayCopy(b,pb,(b.lenght-pb),c);// 将b中剩余的数组考贝到c中
}

题二

给定两数组:
a:长度n,已存放n个有序数。
b:长度(m+n),其中从0至m-1中已存放两个有序序列
要求:将a中的数据拷贝到B中,且保持B为有序。

两题看起来很相似,但其实解法有些不同,题一我们设了三个指针,且按顺序移动,如果题二也按类似实现,那会让b中的数据整体移动(可以参考一下插入排序),于是采用逆序方式
伪代码如下:

int pa = n-1;  //指向a的指针
int pb = m -1 ; //指向b的指针
int putNext = a+b -1; 下一个在存放位置的指针
while(pa >=0 && pb >=0){
	if(a[pa]>= b[pb]){
		b[putNext] = a[pa];
		pa--;
	}else{
		b[putNext] = b[pb];
		pb--;
	}
	putNext--;
}

if(pa != 0){
	...
}else if(pb != 0){
	....
}
 

扩展

1 生成组织树

有人会问,这种算法题对自己的工作真的有帮助吗?或能没有帮助,但养成一好思维模式很重要。比如我在工作中见到这样的需求,有这样一张组织表:

id名称层级父id
1总部00
2上海总部11
3北京总部11
4上海技术部22
5上海销售部22
5北京销售部23

要求输出一颗树,或类似这样的json格式,再或者要和业务数据关联,进行统计分析。我们能有什么解决方案呢,要用递归一次次的查询,或作一次查询,然后递归操作,再或者用类似动态规划的方式用map保存有个节点的引用(这种方式还是蛮好的,以后我会给一个示例代码)?但我们的查询语句写成这样:
select * from 部门表 order by 层级 asc,父id asc, id asc.
我们在拼装树时真的需要用到递归吗?用上面的sql语句查询出的数据集已带有某种特性了,我们可以利用这些特性,来选择更优的算法。

2.查询时间段交集数据

id实例开始时间实例停止时间
1220-1-1 00:002010-1-3 00:44
2220-1-3 00:002010-1-4 00:44
3220-1-8 00:002010-1-20 00:44

我曾在一家名企与其成员共事过一段时间,有个需求:给一个起始时间以及一个结束时间,查询这段时间类所有运行的实例。也就是给定起始时间与结束时间,查询表中所有交集数据。项目组的SE特别交待:你要考虑很多情况:比如给定的时间段包含了起始时间,或者包含了结束时间,或者记录的时间段段包含了查询的时间……
如果要按照那样的分析去做,我或许会写一个有一堆or组成的超级语句。
但只要考虑到表中实例开始时间与实例停止时间 的顺序性,以及查询中所带的顺序性,这个语句只需要一个简单的and.

总结

一种特定的算法可能不重要,但思想很重要,要利用你现有数据集的特征,设计出合理的算法,有时能少写代码,有时能提高你程序的性能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值