笔试刷题 | 贪心算法

定义

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。

贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即个状态以前的过程不会影响以后的状态,只与当前状态有关

个人疑惑

这句话能否在现实生活中使用?

因为生活中常常接触的道理是不能短视,要有大局观,牵一发而动全身,不能为了一点蝇头小利而失去自我。

而贪心算法都是基于当前做一个最优选择,以及它的前提是当前状态不影响以后状态,这个前提怎么能做到呢?因为,我们生活中的得失都是之前做出的决断共同造就的呀。

不过,贪心算法并不一定能得到全局最优解,这是肯定的。

#! /usr/bin/env python
# -*-coding:utf-8-*-
"""
Author: ChileWang
Created at 2020/03/20 15:59


Question:
贪心算法
常用于处理一维度问题,所得的解并不一定是最优解
贪心算法的每一次操作都对结果产生直接影响,而动态规划则不是。
贪心算法对每个子问题的解决方案都做出选择,不能回退;


动态规划则会根据以前的选择结果对当前进行选择,有回退功能。
动态规划主要运用于二维或三维问题,而贪心一般是一维问题 。
"""
import random




def horse_competition():
    n = int(input("输入马匹数目:"))
    tj = []  # 田忌马匹速度
    qw = []  # 齐王马匹速度
    reward = 0
    for i in range(0, n):
        tj.append(random.randint(0, 100))
        qw.append(random.randint(0, 100))
    # 从小到大排序
    tj = sorted(tj)
    qw = sorted(qw)
    print(tj)
    print(qw)
    while len(tj):
        if tj[0] > qw[0]:  # 田忌最慢的马比齐王最慢的马快
            reward += 1
            del tj[0], qw[0]
        elif tj[0] == qw[0]:  # 田忌最慢马和齐王最慢的马一样
            del tj[0], qw[0]
        else:  # 田忌最慢的马比齐王最慢的马垃圾
            reward -= 1
            del tj[0], qw[-1]  # 删除田忌最慢的马和齐王最快的马
    print(reward)




def candy_demand():
    """
    题目:已知一些孩子和一些糖果,每个孩子有需求因子g,
    每个糖果有大小s,当某个糖果的大小s>=某个孩子的需求因子g时,
    代表该糖果可以满足该孩子,求使用这些糖果,最多能满足多少孩子
    (注意,某个孩子最多只能用1个糖果满足)
    :return:
    """
    g = [5, 10, 2, 9, 15, 9]
    s = [6, 1, 20, 3, 8]
    g = sorted(g)
    s = sorted(s)
    print(g)
    print(s)
    child = 0
    candy = 0
    while child < len(g) and candy < len(s):
        if g[child] <= s[candy]:
            child += 1
        candy += 1
    print(child)




def get_max_len():
    """
    给定一个整数序列,返回作为摆动序列的最长子序列的长度。
    通过从原始序列中删除一些(也可以不删除)元素来获得子序列,
    剩下的元素保持其原始顺序。
    :return:
    """
    arr = [1, 17, 5, 10, 13, 15, 10, 5, 16, 8]
    arr = [1,2,3,4,5,6,7,8,9]
    arr = [1,7,4,9,2,5]
    if len(arr) < 2:
        print(len(arr))
    else:


        # Begin = 0, Up = 1, Down = 2
        state = 0
        max_len = 1
        for i in range(1, len(arr)):
            if state == 0:
                if arr[i - 1] < arr[i]:
                    state = 1
                    max_len += 1
                elif arr[i - 1] > arr[i]:
                    state = 2
                    max_len += 1
            elif state == 1:
                if arr[i - 1] > arr[i]:
                    state = 2
                    max_len += 1


            elif state == 2:
                if arr[i - 1] < arr[i]:
                    state = 1
                    max_len += 1
        print(max_len)




def remove_digits():
    """
    题目:已知一个使用字符串表示非负整数num,将num中的k个数字移除,
    求移除k个数字后,可以获得的最小的可能的新数字
    (num不会以0开头,num长度小于10002)


例如:输入:num = “1432219”,k=3 
在去掉3个数字后得到的很多可能里,
如1432,4322,2219,1219;
去掉数字4、3、2、得到的1219最小


    :return:
    """
    a = "1430219"
    k = 2
    stack = []
    for num in a:
        number = int(num)
        while stack and k and int(stack[-1]) > number:
            stack.pop()
            k -= 1
        stack.append(num)
    while k and stack:
        stack.pop()
        k -= 1
    print(stack)
    if not stack:
        print("0")
    else:
        print("".join(stack))




def marry_candy_value():
    """
    4.圣诞节发糖果
    圣诞节来临了,在城市A中,圣诞老人准备分发糖果。
    现在有多箱不同的糖果,
每一种糖果都有自己的价值和重量。每箱糖果都可以拆分成任意散装组合带走。
圣诞老人的驯鹿最多只能承受一定重量的糖果。
请问圣诞老人最多能带走多大价值的糖果。


输入数据:


    输入的第一行由两个部分组成,分别为糖果箱数正整数n(1<=n<=100),
驯鹿能承受的最大重量正整数w(0 max_load:  # 大于总载重,循环迭代减少单位重量
                        flag = 1  # 超出马车最大承重梁, flag=1


                        while True:
                            z = all_sum[1] + current_get_load  # 使用备份重量判断是否超过max_load
                            if z <= max_load:
                                break
                            current_get_load -= 1


                        all_sum[0] = all_sum[1]  # 回复原始的备份载重量
                        all_sum[0] += current_get_load  # 真实拿走的重量
                    sum_value += value_per_load[i] * current_get_load
                    list_load_state[j][2] = True  # 取走标志
            else:
                break
    print('Value:', sum_value)




def greedy():
    """
    一辆汽车加满油后可行驶n公里。旅途中有若干个加油站。
    设计一个有效算法,指出应在哪些加油站停靠加油,使沿途加油次数最少。
     对于给定的n(n <= 5000)和k(k <= 1000)个加油站位置,编程计算最少加油次数。
    :return:
    """
    n = 100
    k = 5
    d = [50, 80, 39, 60, 40, 32]
    # 表示加油站之间的距离
    num = 0
    # 表示加油次数
    for i in range(k):
        if d[i] > n:
            print('no solution')
            # 如果距离中得到任何一个数值大于n 则无法计算
            return


    i, s = 0, 0
    # 利用s进行迭代
    while i <= k:
        s += d[i]
        if s >= n:
            # 当局部和大于n时, 则局部和更新为当前距离,表示加完油之后已经行驶的距离
            s = d[i]
            # 贪心意在令每一次加满油之后跑尽可能多的距离
            num += 1
        i += 1
    print(num)




if __name__ == '__main__':
    candy_demand()
    get_max_len()
    remove_digits()
    marry_candy_value()
    greedy()












你可能感兴趣的:(笔试刷题 | 贪心算法)