据说是今年腾讯面试题,就各种答案

肖远行 2012-04-21 11:25:33
Description
Given three integer sequences which have been sorted in ascending order,pick one integer from each sequence and we can get three integers.we want these three integers to be nearest to each other.Assuming these three integers as a,b,c, they are nearest to each other means d=(a-b)2+(b-c)2+(c-a)2 is the smallest.

Input
There are many test cases. For each test case,the first line are three integers la,lb,lc, they let you know the length of each sequence. The following three lines separately have la,lb,lc integers,give you the integers in each sequence. 1<=la,lb,lc<=10^6 and All integers in the sequences are in the range of [-10^9,10^9].

Output
For each test case, just print one integer : the smallest d as mentioned above.

Sample Input
10 10 10
1 2 3 4 5 6 7 8 9 10
2 3 6 8 10 12 14 16 18 20
3 5 7 9 11 12 14 16 18 20

Sample Output
0
...全文
873 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
yasz1 2012-04-27
  • 打赏
  • 举报
回复
用中学学的均值不等式可以降元- -。。
看不见的裂痕 2012-04-27
  • 打赏
  • 举报
回复
mark一下吧
肖远行 2012-04-26
  • 打赏
  • 举报
回复
if(a[i] < b[j])
{
++i;
}
else if(a[i] > b[j])
{
++j;
}
else
{
++i;++j;
}

这样变化的话,确实是线性,类似那个标程的思想,
但是正确性什么的还需要证明下。。。因为这样变化会去掉很多(a,b)组合。。。
j8daxue 2012-04-26
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 的回复:]
大致这个意思
enum_c(a[i],b[j]);
if(a[i] < b[j])
{
++i;
}
else if(a[i] > b[j])
{
++j;
}
else
{
++i;++j;
}
[/Quote]
enum_c的时候,可以先确定(a,b,a+b/2)是否小于min,可以的话再二分。
j8daxue 2012-04-26
  • 打赏
  • 举报
回复
大致这个意思
enum_c(a[i],b[j]);
if(a[i] < b[j])
{
++i;
}
else if(a[i] > b[j])
{
++j;
}
else
{
++i;++j;
}
肖远行 2012-04-26
  • 打赏
  • 举报
回复
你的归并具体指的是什么?
把数组a和数组b一起排序。。。

如果从这个归并后的数组之中,选取|a-b|的最小值的话,可以做到O(n),
但是如果要穷举所有的|a-b|的话,需要平方的算法吧。。。
j8daxue 2012-04-26
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 的回复:]
a=b时,用c靠近a是没错的吧?
a != b时,c落在ab之间没错吧?

这样的话,需要枚举所有的(a,b)对了,
复杂度就是M*N*logK了、、、
[/Quote]
不会呀,之前的归并就是来做这个事的。(m+n)*logk
肖远行 2012-04-26
  • 打赏
  • 举报
回复
a=b时,用c靠近a是没错的吧?
a != b时,c落在ab之间没错吧?

这样的话,需要枚举所有的(a,b)对了,
复杂度就是M*N*logK了、、、
j8daxue 2012-04-26
  • 打赏
  • 举报
回复
@17f。
a=b时,用c靠近a是没错的吧?
a != b时,c落在ab之间没错吧?
设|ac| = x,|bc|=y.
则x + y = |ab|;
x^2 + Y^2 >= 2xy当且仅当x = y;
所以x = y = |ab|/2;
肖远行 2012-04-26
  • 打赏
  • 举报
回复
我也不能确实那个标程是否正确。。。

我的意思是,先想办法确定|a-b|最小了,
然后再选c的话,当时会去二分最靠近(a+b)/2的c,
但是这样能不能得到正确结果的需要证明。。。
j8daxue 2012-04-26
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 的回复:]
发现个破绽,
取a-b的最小值,再取c
不代表最后能最小。。。

这个题最难的证明,确定a和b,再枚举c,
容易想到,麻烦的是确认可以这样做。。。
[/Quote]
破绽是为什么?A-B取最小了代表|a-b|已经确定,现在是当前枚举ab时的最小值,肯定要个min记录的。
j8daxue 2012-04-26
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 的回复:]
嗯,数据弱一点的话,应该可以过,
定2点,枚举1点,这个思路,以前也考虑过,
当时想的混乱一点,题也没过。。。

额,如果没有很多组数据的话,可以通过,
这个算法的复杂度上界我算了下,大概在6*10的7次作用。。。
那么大概跑10多组数据,应该可以。。。
[/Quote]
既然是你们学校oj上的,上面标程能过不?

我有一个疑问
当前状态0
0. A B C
1. AB C
2. A B C
3. A B C
这个例子显然是状态1的结果最小。我也说明了,处于状态0时调整B的话,B = (A + C)/2时结果最小。
但是此处怎么没判断 1和 B最靠近(a+c)/2时的情况?

肖远行 2012-04-26
  • 打赏
  • 举报
回复
发现个破绽,
取a-b的最小值,再取c
不代表最后能最小。。。

这个题最难的证明,确定a和b,再枚举c,
容易想到,麻烦的是确认可以这样做。。。
肖远行 2012-04-26
  • 打赏
  • 举报
回复
嗯,数据弱一点的话,应该可以过,
定2点,枚举1点,这个思路,以前也考虑过,
当时想的混乱一点,题也没过。。。

额,如果没有很多组数据的话,可以通过,
这个算法的复杂度上界我算了下,大概在6*10的7次作用。。。
那么大概跑10多组数据,应该可以。。。
j8daxue 2012-04-26
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 的回复:]
个人想法,abc为x轴上3个点。
求的是|ab| + |bc| + |ac|之和最小。

枚举其中2点(a,b),则|ab|已经固定,所以枚举的时候可以把ab先排序做个归并,最小值出现在两两之间的差。
如果a=b,则c为最靠近a的值。可以用lower_bound查找。
a!=b,则c点必然落在ab之间,且c = (a + b)/2时最小。则c为最靠近(a+b)/2的值。
[/Quote]
归并(nlogn + mlogm + klogk + n + m)
枚举应该是(n+m)*logk,枚举时遇到a=b=c立刻退出。
怕是过不了10^6数量级估计得线性。
肖远行 2012-04-26
  • 打赏
  • 举报
回复
while(i < n1 && j < n2 && k < n3 && ans > 0)
{
ans = min(ans, cal(a[i], b[j], c[k]));
tmpa = cal(a[i + 1], b[j], c[k]);
tmpb = cal(a[i], b[j + 1], c[k]);
tmpc = cal(a[i], b[j], c[k + 1]);
if(tmpa < tmpb && tmpa < tmpc) ++ i;
else if(tmpb < tmpc) ++ j;
else ++ k;
}

这个是主算法,只要操作就是如果改变i,j,k这三个下标。。。
肖远行 2012-04-26
  • 打赏
  • 举报
回复
我发一下程序,
是学校里面别人写的标程,
思路比较简单,一下子就能看懂了,
但是不知道对不对,我也没想出办法否认它,


#include<stdio.h>
#include<string.h>
#include<stdlib.h>

const int maxn = 1 << 20;
typedef long long LL;
LL a[maxn], b[maxn], c[maxn];

inline LL min(LL x, LL y)
{return x < y ? x : y;}

inline LL cal(LL x, LL y, LL z)
{return (x - y) * (x - y) + (x - z) * (x - z) + (z - y) * (z - y);}

int main()
{
LL ans, tmpa, tmpb, tmpc;
int n1, n2, n3, i, j, k;

freopen("in.txt", "r", stdin);
while(scanf("%d%d%d", &n1, &n2, &n3) != EOF)
{
for(i = 0; i < n1; ++ i) scanf("%lld", &a[i]);
for(i = 0; i < n2; ++ i) scanf("%lld", &b[i]);
for(i = 0; i < n3; ++ i) scanf("%lld", &c[i]);

ans = ((LL)1 << 63) - 1;
i = j = k = 0;

while(i < n1 && j < n2 && k < n3 && ans > 0)
{
ans = min(ans, cal(a[i], b[j], c[k]));
tmpa = cal(a[i + 1], b[j], c[k]);
tmpb = cal(a[i], b[j + 1], c[k]);
tmpc = cal(a[i], b[j], c[k + 1]);
if(tmpa < tmpb && tmpa < tmpc) ++ i;
else if(tmpb < tmpc) ++ j;
else ++ k;
}
printf("%lld\n", ans);
}
return 0;
}
肖远行 2012-04-26
  • 打赏
  • 举报
回复
这种方式确实可以,只是复杂度高了点。。。
归并2个数组,是nlogn,然后还有枚举这些ab,
每次枚举消耗logn,
大概需要nlogn + nlogn。。。
仔细想了下,在归并后的数组里面穷举最接近的|a-b|应该能O(n),
你这个算法应该能过这个题目。。。
xiaobeiweng 2012-04-26
  • 打赏
  • 举报
回复
学习,,,,
j8daxue 2012-04-26
  • 打赏
  • 举报
回复
个人想法,abc为x轴上3个点。
求的是|ab| + |bc| + |ac|之和最小。

枚举其中2点(a,b),则|ab|已经固定,所以枚举的时候可以把ab先排序做个归并,最小值出现在两两之间的差。
如果a=b,则c为最靠近a的值。可以用lower_bound查找。
a!=b,则c点必然落在ab之间,且c = (a + b)/2时最小。则c为最靠近(a+b)/2的值。
加载更多回复(6)
内容概要:本文针对无刷直流电机驱动的电子机械制动(EMB)执行器,建立了考虑Stribeck摩擦特性的非线性耦合动力学模型,并在Simulink环境中完成了系统级仿真分析。研究综合集成了电机动力学、齿轮传动机构与制动执行机构的动力学特性,构建了高保真的机电一体化系统模型。重点引入Stribeck摩擦模型以精确描述低速工况下执行器内部存在的静摩擦、粘滞摩擦与库仑摩擦之间的过渡行为,有效提升了系统在启停、反向运动等瞬态过程中的动态响应仿真精度。通过多工况仿真验证了模型的有效性,能够准确反映摩擦引起的爬行、滞后与定位误差等非线性现象,为EMB系统的高性能控制算法设计(如摩擦补偿、滑模控制)与结构优化提供了高可信度的仿真平台。; 适合人群:从事汽车电子制动系统、电机驱动控制、机电系统建模与仿真研究的研究生、科研人员及工程技术人员,需具备扎实的机械动力学、自动控制理论基础和MATLAB/Simulink仿真能力。; 使用场景及目标:①用于高精度电子机械制动系统的设计验证与性能预测;②为消除摩擦非线性影响的先进控制策略(如自适应控制、智能控制)提供精确的被控对象模型;③深入探究Stribeck摩擦等非线性因素对系统动态性能(如响应延迟、稳态误差)的作用机理; 阅读建议:读者应结合提供的Simulink模型文件,深入剖析Stribeck摩擦模块的数学实现与参数辨识方法,建议通过改变输入指令(如阶跃、正弦)和负载条件进行对比仿真,以直观理解非线性摩擦对系统动态特性的影响。

700

社区成员

发帖
与我相关
我的任务
社区描述
提出问题
其他 技术论坛(原bbs)
社区管理员
  • community_281
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧