1.1一段神奇的字符
一段神奇的字符也称为巧填数据问题,是算法中的经典问题,也是谷歌公司推出的一道面试题。在实际应用中我们通常采用穷举法解决这个问题。
1.1.1问题描述
字母代表0-9的数字中的一个,且不重复。在下面公式中,首位不能是0。
he + she = you
计算出各个字母代表的数字,来表示上面公式。
1.1.2具体实现
from datetime import datetime
class data_struct(object):
def __init__(self,letter,status):
self.letter = letter
self.status = status
if self.status == True:
self.dight = [0,1,2,3,4,5,6,7,8,9]
else:
self.dight = [1,2,3,4,5,6,7,8,9]
@staticmethod
def norepet(list0):
length = len(list0)
list1 = [0 for i in range(10)]
for i in range(length):
list1[list0[i]]+=1
if list1[list0[i]]>1:
return False
return True
if __name__ == '__main__':
"""he + she = you"""
letterh = data_struct('h',True).dight
lettere = data_struct('e',False).dight
letters = data_struct('s',True).dight
lettery = data_struct('y',True).dight
lettero = data_struct('o',False).dight
letteru = data_struct('u',False).dight
start_time = datetime.now()
for h in letterh:
for e in lettere:
for s in letters:
for y in lettery:
for o in lettero:
for u in letteru:
list0 = [h,e,s,y,o,u]
if True == data_struct.norepet(list0):
str1 = str(h) + str(e)
str2 = str(s) + str(h) + str(e)
str3 = str(y) + str(o) + str(u)
if int(str1)+int(str2)==int(str3):
print(str1,str2,str3)
end_time = datetime.now()
diff_time = end_time-start_time
print(diff_time)
1.1.3输出结果
1.2 1000以内的完全数
完全数是一些特殊的自然数,满足所有的真因数(除自身以外)的和等于它本身这一条件
1.2.1问题描述
第一个完全数是6=1+2+3
第二个完全数是28=1+2+4+7+14
第三个是496=1+2+4+8+16+31+62+124+8128
1.2.2 算法分析
完全数有许多性质:
- 可以写成连续自然数的和
- 全部因数导数的和都是2
- 1/1+1/2+1/3+1/6=2
- 1/1+1/2+1/4+1/7+1/14+1/28=2
- 除6以外的完全数,可以写成连续奇立方数之和
- 28=13+33
- 496=13+33+53+73
1.2.3代码实现
def approximateNumber(num:int):
res = []
for divsors in range(1,num):
# 找出这个数中所有除自身外的约数
temp = []
for divsor in range(1,divsors,1):
if divsors%divsor==0:
temp.append(divsor)
tempSum = sum(temp)
if tempSum==divsors:
res.append(divsors)
return res
print(approximateNumber(1000))
1.2.4输出结果
1.3 多进程验证歌德巴赫猜想
1.3.1 问题描述
是不是所有的大于2的偶数,都可以表示为两个素数的呢? 这个问题是德国数学家哥德巴赫(C.Goldbach,1690-1764)于1742年6月7日在给大数学家欧拉的信中提出的,所以被称作哥德巴赫猜想。在现实应用中,通常采用枚举法解决该问题。
1.3.2 算法分析:枚举法
可以把问题归纳为在指定范围内(1~2000)验证其中每一个偶数是否满足哥德巴赫猜想,如果有一个数不满足的话,就跳出循环,否定该猜想。
上述问题的核心就演变成:如何验证一个偶数a是否满足哥德巴赫猜想,即偶数a能否表示为两个素数之和
:
一个正偶数a一定可以表示为a/2种正整数相加的形式:a=1+(a-1),a=2+(a-2),…a=(a/2-1)+(a/2+1),a=a/2+a/2,一共有a/2种。那么在这a/2种结构种只要存在一种a=i+j, i和j都是素数,就可以判断这个偶数a满足哥德巴赫猜想。
1.3.4 具体实现:判断素数并分解
这里插入一个证明,判断一个数是不是素数a,不需要遍历到a/2,到根号n就可以了。
首先我们通过函数IsPrime(n)判断数字n是否是质数,然后通过函数GDBH(T)验证大于2的偶数可以分解成2个质数的和,其中参数T是元组,表示需要计算的区间,为了提高程序的运行效率,本程序采用了多线程技术提高效率。具体代码如下:
单线程:
import math
from datetime import datetime
def isPrime(n):
if n <= 1:
return False
else:
for i in range(2, int(math.sqrt(n)) + 1):
if n % i == 0:
return False
return True
def GDBH(T):
S = T[0]
E = T[1]
if S < 4:
S = 4
if S % 2 == 1:
S += 1
for i in range(S, E + 1, 2):
isGDBH = False
for j in range(i // 2 + 1):
if isPrime(j):
k = i - j
if isPrime(k):
isGDBH = True
if i % 10000 == 0:
print("%d=%d+%d"%(i, j, k))
break
if not isGDBH:
print("哥德巴赫猜想错误!")
break
if __name__ == '__main__':
start_time = datetime.now()
GDBH((1, 1000000))
end_time = datetime.now()
print(end_time - start_time)
多线程:
import math
from datetime import datetime
from multiprocessing import Pool, cpu_count
def isPrime(n):
if n <= 1:
return False
else:
for i in range(2, int(math.sqrt(n)) + 1):
if n % i == 0:
return False
return True
def GDBH(T):
S = T[0]
E = T[1]
if S < 4:
S = 4
if S % 2 == 1:
S += 1
for i in range(S, E + 1, 2):
isGDBH = False
for j in range(i // 2 + 1):
if isPrime(j):
k = i - j
if isPrime(k):
isGDBH = True
if i % 10000 == 0:
print("%d=%d+%d" % (i, j, k))
break
if not isGDBH:
print("哥德巴赫猜想错误!")
break
# 对数字空间进行分段CPU_COUNT片
def seprateNum(N, CPU_COUNT):
list = [[i + 1, i + N // CPU_COUNT] for i in range(4, N, N // CPU_COUNT)]
list[0][0] = 4
if list[CPU_COUNT - 1][1] > N:
list[CPU_COUNT - 1][1] = N
return list
if __name__ == '__main__':
N = 10 ** 6
start_time = datetime.now()
CPU_COUNT = cpu_count()
pool = Pool(CPU_COUNT)
sepList = seprateNum(N, CPU_COUNT)
res = pool.map(GDBH, sepList)
pool.close()
pool.join()
end_time = datetime.now()
print(end_time - start_time)
1.3.5 实验结果
遍历到1000000用时37s,改进程序,使用多线程进行优化。
关于python多进程相关知识,可以查看这篇博客(留一个小坑,后面补齐!)
1.4 亲密数
1.4.1 问题描述
亲密数的概念:
如果整数a的全部因数之和等于b(此处因数包含1,不包含a),而b的全部因数之和等于a(此处因数包含1,不包含b),那么a和b就是亲密数。
1.4.2 算法分析:穷举法
首先计算出a的全部因数,累加求和得出b的值,再计算b的全部因数累加求和得到res,判断res是否等于a,如果等于,那么a和b就是亲密数。值得注意的是求因数的是对i(i=1~a/2)进行取模运算
1.4.3 具体实现:计算3000以内的亲密数
def check(n):
"""计算各因子之和"""
res = 0
for i in range(1, int(n // 2) + 1):
if n % i == 0:
res += i
return res
if __name__ == '__main__':
for i in range(1, 3000):
res = check(i)
if i != res and check(res) == i:
print(res, i)