算法例题第七章

如何求正整数n的所有可能的整数组合

例如: 4=1+1+1+1, 1+1+2, 1+3, 2+2, 4,  还要按递增展示,

嗯嗯, 懵逼

def printResult(result, count):
    if not result:
        return
    size = len(result)
    if count < 0 or count > size:
        return
    # 这里只有从0到count-1位才是结果
    temp = ""
    for i in range(0, count):
        if temp:
            temp += "+" + str(result[i])
        else:
            temp = str(result[i])
    print(temp)


'''
sums:求和为sums的所有组合
result:结果数组
count:组合中数字的个数
'''


def comb(sums, result, count):
    # 如果成功,就打印;这里成功是指sums为0
    if sums < 0:
        return
    if 0 == sums:
        # 这里只有从0到count-1位才是结果
        print("满足条件组合")
        printResult(result, count)
        # 找到结果需要返回
        return

    # 确定组合中下一个取值的起始范围,确保组合中下一个数字一定不会小于前一个数字
    i = 1 if 0 == count else result[count - 1]
    print("################ i={i} count={count}".format(i=i, count=count))
    # i最多可以取到sums
    while i <= sums:
        # 设置变量
        result[count] = i
        count += 1
        # 递归
        comb(sums - i, result, count)
        # 清除变量
        count -= 1
        # 找下一个数字做为组合中的数字
        i += 1


def process():
    sums = 4
    result = [None for i in range(sums)]
    count = 0
    result = comb(sums, result, count)
    print(result)


if __name__ == "__main__":
    process()

如何判断还有几盏灯亮着

题目描述:

感觉思考的很巧妙,服了

100个灯泡排成一排,第一轮将所有灯泡打开,第二轮每隔一个灯泡关掉一个,即排在偶数的灯泡被关掉,第三轮每隔两个灯泡,将开着的灯泡关闭,关闭的灯泡打开, 已从类推, 第100轮结束后, 还有几盏灯灯泡亮着。

分析:

第一轮把所有灯泡打开,第二轮是偶数的关闭,第三轮对三的倍数位置的灯泡操作,第四轮对四的倍数进行操作,最终被操作奇数次的灯泡还是开着的

  1. 对于每盏灯,当拉动的次数为奇数时, 灯时亮着的, 当拉动的次数时偶数时,灯就是关着的
  2. 每盏灯的拉动次数与它的编号所含约数的个数有关,它的编号有几个约数,这盏灯就被拉动几次
  3. 1~100这100个数中有哪几个数,约数的个数是奇数?一个数的约数是成对出现的,只有完全平方根的约数才是奇数个
  4. 所以题目就变成在1~100个数中,找完全平方根
def factorIsOdd(a):
    total = 0
    i = 1
    while i <= a:
        # a 是1到100的数, 下面的if 是看它有几个因数,比如a=1, a//1, a//2, a//3/....一直遍历
        if a % i == 0:
            # 能被1到100的数整除, +1
            total += 1
        i += 1
    if total % 2 == 1:
        # 有奇数个因数就返回1
        return 1
    else:
        return 0


def totalCount(num, n):
    count = 0
    i = 0
    while i < n:
        if factorIsOdd(num[i]) == 1:
            print("亮着的灯" + str(num[i]))
            count += 1
        i += 1
    return count


if __name__ == "__main__":
    # 创建1到100的列表
    num = []
    for i in range(1, 101):
        num.append(i)
    count = totalCount(num, 100)

 

如何组合1, 2, 5 这三个数使其和为100,求共有多少种组合方法

题目描述:

例如100个1, 0个2, 0个5; 50个1, 25个2,0个5。。

分析:

这也是个很巧妙的方法

可以写出方程x+2y+5z=100, 则x+5z=100-2y。  从这个表达式可以看出x+5z是偶数, 且x+5z <= 100。所以问题转化为求x+5z是偶数,且x+5z <= 100 的个数。遍历z可能的取值,来解决。0 <= z <= 20。

  • z = 0,x=0,2,4....100           共有100//2 +1 个
  • z=1,   x=1, 3, 5....95             共95//2 +1 个
  • 。。。。。。
def test(n):
    count = 0
    m = 0
    while m <= n:
        count += m // 2 + 1
        m += 5
    return count


print(test(100))

 

如何用一个随机函数得到另外一个随机函数

题目描述:
有一个func1能返回0和1,返回0,1的概率都为1/2, 怎么利用这个函数得到另一个函数func2,使func2的返回值为0, 1 且返回0的概率为1/4, 1的概率为3/4。

import random


def func1():
    return random.randint(0, 1)


def func2():
    a1 = func1()
    # a1 可能为 0 1
    a2 = func1()
    # a2 可能为 0 1
    tmp = a1
    # tmp 可能为 0 1
    tmp |= (a2 << 1)
    # tmp = tmp | (a2 << 1)
    # a2左移一位, 可能00, 10。
    # 所以 00, 10 或 00, 01,00|00=00, 00|01=01. 10|00=10,10|01=11, 等于零的概率为四分之一
    if tmp == 0:
        # 概率为四分之一
        return 0
    else:
        return 1


if __name__ == "__main__":
    i = 0
    while i < 16:
        print(func2())
        i += 1
    print("\n")
    i = 0
    while i < 16:
        print(func2())
        i += 1

如何拿到最多的金币

题目描述:10个房间放着随机数目的金币,每个房间只能进一次,并且只能在一个房间拿金币。一个人采取了如下策略:前4个房间只看不拿,随后房间只要比前4个最多的还多就拿,否则就拿最后一个房间的金币。计算这种概率拿到最多金币的概率。没什么难的

import random


def getMaxNum(n):
    if n < 1:
        print("参数不合法")
        return
    # 创建一个有十个随机数的列表
    a = []
    for i in range(n):
        a.append(random.uniform(1, n))
    # 找到前四个最大的数
    max4 = max(a[:4])
    i = 4
    while i < n - 1:
        # 减1 使不拿最后一个房间的
        if a[i] > max4:
            return True
        i += 1
    return False


if __name__ == "__main__":
    monitorCount = 1000
    success = 0
    i = 0
    while i < monitorCount:
        if getMaxNum(10):
            success += 1
        i += 1
    print(success/monitorCount)

如何求数字的组合

用1, 2, 2, 3, 4, 5这六个数字i,写一个函数, 打印所有不同的排列,例如:512234,412345等, 要求4不能再第三位, 3与5不能相连。  mmp,看了许久,为解其中深意,留给日后机缘巧合再做商榷。

class Test(object):

    def __init__(self, arr):
        self.numbers = arr
        self.visited = [False] * len(self.numbers)
        # [False, False, False, False, False, False]
        self.graph = [([None] * len(self.numbers)) for i in range(len(self.numbers))]
        # [[六个None], [六个None], ...六个]
        self.n = 6
        self.combination = ''
        self.s = set()

    def depthFirstSearch(self, start):
        # start=0, 1, 2, 3, 4, 5
        self.visited[start] = True
        # [True, False, False, False, False, False] start=0
        # [True, True, False, False, False, False] start=1
        self.combination += str(self.numbers[start])
        # number =  [1, 2, 2, 3, 4, 5]
        if len(self.combination) == self.n:
            if self.combination.index("4") != 2:
                self.s.add(self.combination)
        j = 0
        while j < self.n:
            # graph
            # [[0, 1, 1, 1, 1, 1], [1, 0, 1, 1, 1, 1], [1, 1, 0, 1, 1, 1],
            # [1, 1, 1, 0, 1, 0], [1, 1, 1, 1, 0, 1], [1, 1, 1, 0, 1, 0]]
            # visited [True, False, False, False, False, False] i=0, start=0
            if self.graph[start][j] == 1 and self.visited[j] is False:
                # j=1 开始符合条件
                self.depthFirstSearch(j)
            j += 1
        self.combination = self.combination[:-1]
        self.visited[start] = False

    def getAllCombinations(self):
        i = 0
        while i < self.n:
            j = 0
            while j < self.n:
                if i == j:
                    self.graph[i][j] = 0
                else:
                    self.graph[i][j] = 1
                j += 1
            i += 1
        # print(self.graph)
        # [[0, 1, 1, 1, 1, 1], [1, 0, 1, 1, 1, 1], [1, 1, 0, 1, 1, 1],
        # [1, 1, 1, 0, 1, 1], [1, 1, 1, 1, 0, 1], [1, 1, 1, 1, 1, 0]]
        self.graph[3][5] = 0
        self.graph[5][3] = 0
        # print(self.graph)
        # [[0, 1, 1, 1, 1, 1], [1, 0, 1, 1, 1, 1], [1, 1, 0, 1, 1, 1],
        # [1, 1, 1, 0, 1, 0], [1, 1, 1, 1, 0, 1], [1, 1, 1, 0, 1, 0]]
        i = 0
        while i < self.n:
            self.depthFirstSearch(i)
            i += 1

    def printAllCombimations(self):
        for i in self.s:
            print(i)


if __name__ == "__main__":
    arr = [1, 2, 2, 3, 4, 5]
    t = Test(arr)
    t.getAllCombinations()
    t.printAllCombimations()

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值