免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: 天魔封神霸
打印 上一主题 下一主题

【华为公司Python面试题】,要求10分钟写出代码。。。 [复制链接]

论坛徽章:
0
61 [报告]
发表于 2012-05-06 19:36 |只看该作者
按照我的思想,就是先合并两个序列a跟b,得到c,然后排序c,再分割c,左右端同时取值,一次放d,一次放e,最后得到de两个list,这个应该就是差值最小的了吧

论坛徽章:
0
62 [报告]
发表于 2012-05-07 11:57 |只看该作者
按照我的思想,就是先合并两个序列a跟b,得到c,然后排序c,再分割c,左右端同时取值,一次放d,一次放e,最后得到de两个list,这个应该就是差值最小的了吧

楼上的思路和我的一样,另一种等同的做法是:合并之后排序,按奇偶分割成两个序列即为所求。
理由:合并排序后,针对第一个元素,试想序列里元素,谁和他的差距最小?当然是第二个。这样,一二元素分离。再来考虑第三个元素,同样的道理,三四元素分开。这样,最后的结果是:元素最小差距1 + 元素最小差距2 + 。。。 = 两个序列的最小差距。

论坛徽章:
0
63 [报告]
发表于 2012-05-07 21:34 |只看该作者
本帖最后由 dknlnl 于 2012-05-07 22:11 编辑

每个序列之和越靠近总和的1/2,那么是两个序列这差越小.
考虑反贪心算法.
将两个序列合并,排序,记为sortList.
设x,y为结果序列.
x依次从sortList中取数,从最小的开始取.直到sum(x)>=sum(sortList)/2.

假设x从sortList取出一个数k反,sum(x)从小于sum(sortList)/2变为大于或等于sum(sortList)/2,根据以下条件判断k是否放入x:
如果将k加入x后,x的和与y(y就是sortList减于x啦)之差小于将k不放入x,那么k放入x.
以上是不要求结果序列等长的.

论坛徽章:
0
64 [报告]
发表于 2012-06-01 17:54 |只看该作者
本帖最后由 CMAX 于 2012-06-01 17:54 编辑

python的,纯实现,没考虑其他的
  1. #! /usr/bin/env python

  2. import input
  3. a = input.a
  4. b = input.b

  5. l = len(a)

  6. ar = list()
  7. br = list()

  8. sl = sorted(a + b, reverse = True)

  9. diff = 0

  10. sign = True

  11. for i in xrange(0, l):
  12.     for j in range(2*l-1, i+1, -1):
  13.         d1 = sl[i] - sl[j-1]
  14.         d2 = sl[i] - sl[j]
  15.         if diff - d1 >= 0 and diff - d2 < 0:
  16.             r1, r2 = i, j
  17.             break
  18.     else:
  19.         r1, r2 = i, i+1

  20.     if sign:
  21.         ar.append(sl[r1])
  22.         br.append(sl[r2])
  23.     else:
  24.         ar.append(sl[r2])
  25.         br.append(sl[r1])
  26.     sign = not sign

  27. print ar, sum(ar)
  28. print br, sum(br)
复制代码

论坛徽章:
11
2015年迎新春徽章
日期:2015-03-04 09:55:282017金鸡报晓
日期:2017-02-08 10:39:4215-16赛季CBA联赛之辽宁
日期:2016-12-15 10:24:1715-16赛季CBA联赛之佛山
日期:2016-11-30 09:04:2015-16赛季CBA联赛之江苏
日期:2016-04-29 15:56:1215-16赛季CBA联赛之同曦
日期:2016-04-12 13:21:182016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之山东
日期:2016-02-16 11:37:52每日论坛发贴之星
日期:2016-02-07 06:20:00程序设计版块每日发帖之星
日期:2016-02-07 06:20:0015-16赛季CBA联赛之新疆
日期:2018-01-09 16:25:37
65 [报告]
发表于 2012-08-29 11:35 |只看该作者
本帖最后由 bskay 于 2012-08-29 15:42 编辑

伪动态规划的,

#动态规划问题
#从M个数里面找出N个,让他们的和尽量接近 P
class NumList:
        def __init__(self):
                self.reset()
                pass
        def reset(self):
                self.vA = []
                self.vB = []
                self.nSumA = reduce(lambda x, y: x+y, self.vA, 0)
                self.nSumB = reduce(lambda x, y: x+y, self.vB, 0)
                pass
        #开始规划
        def addonce(self,nA,nB):
                #
                if self.nSumA > self.nSumB:
                        self.vA.append(nA)
                        self.nSumA += nA
                        self.vB.append(nB)
                        self.nSumB += nB
                        pass
                else:
                        self.vA.append(nB)
                        self.nSumA += nB
                        self.vB.append(nA)
                        self.nSumB += nA
                        pass
                #try
                while self.ajduest():pass
                return
        def ajduest(self):
                if self.nSumA>self.nSumB:
                        nA,nB = self.findd(self.vA,self.vB,(self.nSumA-self.nSumB)/2)
                        if nA is None or nB is None:
                                return False
                        pass
                elif self.nSumA<self.nSumB:
                        nB,nA = self.findd(self.vB,self.vA,(self.nSumB-self.nSumA)/2)
                        if nA is None or nB is None:
                                return False
                        pass
                else:
                        return False
                self.nSumA += self.vB[nB] - self.vA[nA]
                self.nSumB += self.vA[nA] - self.vB[nB]
                print 'r1(vA,vB) =',self.vA,self.vB
                self.vA[nA],self.vB[nB] = self.vB[nB],self.vA[nA]
                self.vA.sort()
                self.vB.sort()
                print 'r2(vA,vB) =',self.vA,self.vB
                return True
        #
        '''
        输入:
                I1. A中所有元素的和大于B中所有元素的和
                I2. A,B中的元素从小到大排列
                I3. 最大期望的调整值
        输出:
                O1. 在A,B中分别找出一个位置(a,b)
                O2. 交换调整A,B中对应的元素后,依然满足I1
                O3. 没有找到满足条件一个位置,返回None
        '''
        def findd(self,vA,vB,nDlt):
                print 'findd',vA,vB,nDlt
                nA,nB = None,None
                nXXX = nDlt
                for a in xrange(len(vA)-1,-1,-1):
                        for b in xrange(len(vB)):
                                if vB >= vA[a]:
                                        break
                                nDiff = vA[a]-vB #调整的差值
                                if nDiff > nDlt:
                                        continue
                                if nDlt-nDiff >= nXXX:
                                        continue
                                if nDiff == nDlt:
                                        print 'haha findd at ... ',a,b
                                        return a,b
                                #print '(vB,vA[a]) =',(vB,vA[a]),'(a,b)',(a,b), 'r =',nDiff
                                nXXX = nDlt-nDiff
                                nA,nB = a,b
                                continue
                        continue
                print 'findd at ... ',nA,nB
                return nA,nB
        def main(self,vA,vB):
                self.reset()
                vX = vA+vB
                vX.sort()
                while len(vX):
                        self.addonce(vX[0],vX[1])
                        del vX[:2]
                        continue
                print 'vA =>',self.vA
                print 'vB =>',self.vB
                return
        pass


self = NumList()
self.main([1,1,1,1],[2,2,2,2])
assert(self.vA == [1,1,2,2] and self.vA==self.vB)

self.main([1,1,1,1],[1,1,1,1])
assert(self.vA == [1,1,1,1] == self.vB)

self.main([1,1,2,3,5,10,], [20,30,30,50,50,100,])

论坛徽章:
0
66 [报告]
发表于 2012-08-29 16:38 |只看该作者
本帖最后由 Hadron74 于 2012-08-29 20:00 编辑

看了前人的解法,怎么把问题搞得那么复杂。这个题目是十分钟的题目,肯定没有那么多代码的。

我的思路是用穷举法,把所有的a+b的total的序列的排列穷举,得到所有可能的划分,对其差值计算最小值。

下面是程序,
  1. def minus(total):
  2.         n = len(total)/2
  3.         a = total[:n]
  4.         b = total[n:]
  5.         return abs(sum(a)-sum(b)),a,b

  6. def func(total,k):
  7.         mi,am,bm = minus(total)
  8.         global minusN,an,bn
  9.         if mi < minusN:
  10.                 minusN = mi
  11.                 an,bn = am,bm

  12.         for i in range(k,len(total)):
  13.                 total[k],total[i] = total[i],total[k]
  14.                 func(total,k+1)
  15.                 total[k],total[i] = total[i],total[k]

  16. a=[1,2,3,4]
  17. b=[6,7,8,9]
  18. an,bn = a[:],b[:]
  19. total = a+b
  20. minusN,am,bm=minus(total)
  21. func(total,0)
  22. print "a:",an
  23. print "b:",bn
  24. print "minus:",minusN

复制代码
这里的算法用到了穷举一个序列的全排列的算法,见
http://www.cnblogs.com/height/archive/2012/08/14/2638802.html

这个算法的复杂性太过要O((2n)!),我的写法中也有冗余的部分,有时间来改正。
这里抛砖引玉,也许有更短小的写法。肯定有更快的算法,我正在寻找中。

论坛徽章:
0
67 [报告]
发表于 2012-09-12 19:03 |只看该作者
本帖最后由 Hadron74 于 2012-09-12 19:13 编辑

回复 66# Hadron74


    现在我有了一个更好的方法,用0-1背包问题来解决这个问题。思路是,给一个总和长的select数组,记录a/b的状态,True表示在a中,False表示在b中。
用递归遍历所有选取n个元素在a中的可能,就遍历了所有可能的交换。这个算法的复杂度小于O(2^(2n)).

其算法可以参考http://www.cnblogs.com/Myhsg/archive/2009/08/29/1556460.html

下面是代码
  1. def  minus():
  2.     global total,select,number
  3.     a = [ total[i] for i in range(number) if select[i] ]
  4.     b = [ total[i] for i in range(number) if not select[i] ]
  5.     return abs(sum(a) - sum(b)),a,b

  6. def func(sumN,k):
  7.     global select,number,halfnumber,minSN,an,bn
  8.     if k==number:
  9.         return
  10.     if sumN == halfnumber:
  11.         mi,am,bm = minus()
  12.         if mi< minSN:
  13.             minSN = mi
  14.             an,bn = am,bm
  15.         return
  16.     select[k] = True
  17.     func(sumN+1,k+1)
  18.     select[k] = False
  19.     func(sumN,k+1)
  20.    
  21. if __name__ == '__main__':
  22.     a = [1,2,3,4]
  23.     b = [6,7,8,9]
  24.     total = a + b
  25.     an, bn = a[:], b[:]
  26.     minSN = abs(sum(a)-sum(b))
  27.     number = len(total)
  28.     halfnumber = number/2

  29.     select = map(lambda x: False,total)

  30.     func(0,0)

  31.     print minSN
  32.     print an
  33.     print bn
复制代码
结果:
  1. 0
  2. [1, 4, 7, 8]
  3. [2, 3, 6, 9]
复制代码

论坛徽章:
0
68 [报告]
发表于 2012-09-16 20:59 |只看该作者
我觉得就是一个排序问题吧。
比如:序列a1,a2,a3,...an
         序列b1,b2,b3,...bn
         假设存在一个序列c,c的元素为a1,a2,a3...an,b1,b2,b3...bn.对序列c排序后得到新的顺序,c1,c2,c3..c2n.则得到序列a结果为c1,c3,c5...c2n-1,序列b为c2,c4,c6...c2n.
而排序可以只比较就可以了。

论坛徽章:
0
69 [报告]
发表于 2012-09-17 00:21 |只看该作者
回复 68# new_ray

这个问题没有那么简单,详细请看我们最新的帖子。《编程之美》给出了正整数的动态规划算法。我写了代码。

http://bbs.chinaunix.net/forum.p ... age%3D1#pid22286448

   

论坛徽章:
0
70 [报告]
发表于 2012-09-22 07:09 |只看该作者
呵呵,写完后就发现自己写错了,后来又有了一种想法。仍然是先排序,得到c1,c2,c3..c2n。然后将cn+1,cn+2...c2n数据与前面的进行交换。每次选取的值都是要是差值最小(>0)的数对。
1.若使得cn+1,cn+2...c2n与c1,c2...cn的差值变大时就结束。
2.若cn+1,cn+2...c2n与c1,c2...cn的差值为负数时,如果负数的绝对值变小时仍然交换。
3.再将c1,c2...cn与与后面的进行交换。每次选取的值都是要是也差值最小(>0)的数对。
4.处理与1,2步骤类似。

呵呵,这样应该是可以了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP