跟风一把,刷几个算法题

276 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

最近看博文,发现好卷啊,都在刷面试题算法题,说好的摸鱼,原来我才是小丑[dog]

我也刷几题吧,顺便把解题思路记录下来。
解题语言就用C#吧(感觉什么语言都一样,也都差不多,算法核心是解题的思路和技巧)

瓶盖问题

题目:小明买了 n 瓶饮料,三个空瓶可以换一瓶新的饮料,请问小明一共可以喝多少瓶饮料,最后还能剩几个瓶子

分析:
首先最后剩余瓶盖肯定小于 3
假设每次喝完所有饮料,再一次去进行兑换瓶盖
如此循环往复,直到剩余瓶盖 < 3 则停止循环

简单推算一下,假设初始值 10瓶

兑换次数喝的瓶数喝完后盖子数
01010
134
212
总计兑换2次喝了14瓶剩余2个盖子

那这个循环的条件为 cap >= 3,一旦不满足这个条件时,停止循环(即不能兑换)
do..while表达式再合适不过了
直接上手写了

static void Main(string[] args)
{
    Console.Write("请输入小明初始买饮料的瓶数:");
    int fir = Convert.ToInt32(Console.ReadLine());//初始瓶数
    var tal = fir;//使用新变量保存初始瓶数
    int cap = 0;//喝的瓶数
    do
    {
        cap += tal + tal / 3;
        tal /= 3;
    } while (tal >= 3);
    Console.WriteLine("小明买了{0}瓶饮料,一共可以喝{1}瓶,剩余瓶盖{2}个。", fir, cap, tal);
    Console.ReadLine();
}

测试 image.png

手算了一下,这个结果不对啊,我的写法有问题...
想一下,do中的tal有问题,tal为每次的盖子数,只算了能兑换的瓶盖数,少于3的瓶盖被忽略了
而cap的累加也有问题,第一次可以加上tal,后面只能是喝到tal/3瓶饮料

看来我的第一次尝试完全没有按我分析的方法来,导致写错了
再次尝试,这次需要记录每次剩余的且不够兑换的盖子

static void Main(string[] args)
{
    Console.Write("请输入小明初始买饮料的瓶数:");
    int fir = Convert.ToInt32(Console.ReadLine());//初始瓶数
    var tal = fir;//每次兑换前瓶盖总数
    int cap = 0;//剩余不够兑换的空瓶
    var sum = 0;//喝的瓶数
    //循环体为开始兑换,兑换前,可以喝fir瓶,因此
    sum += fir;
    do
    {
        cap = tal % 3;//首先计算每次兑换后手里剩余的瓶盖
        sum += tal / 3;//喝的瓶数累加
        tal = tal / 3 + cap;//喝完剩余瓶盖总数,供下次兑换
    } while (tal >= 3);
    Console.WriteLine("小明买了{0}瓶饮料,一共可以喝{1}瓶,剩余瓶盖{2}个。", fir, sum, tal);
    Console.ReadLine();
}

image.png image.png

看似简单,其实实现起来还是有点小复杂的
可能算法题刷的少吧,挺有意思,分析到实现,过程很重要\

猴子吃桃问题

题目:假设有一堆桃子,猴子每天吃掉总数的一半 + 1个,吃到第 n 天,桃子还剩一个,求桃子总数

同上,先分析一波 这个感觉是反过来的,不知道总数,输入天数,求出总数
完全可以假设啊,比如总共20个桃子,看看能吃几天

第?天吃前桃子总数吃桃数量剩余桃子
020-20
120119
2954
3431

注:第0天为初始化数据,未开始吃桃

分析:
每天剩余桃子数有规律,一天是奇数一天是偶数!
吃前桃子数 和 吃完桃子数 奇偶对称(即必一奇一偶)
当剩余桃子为奇数x时,吃前桃子数为 (x+1) * 2
当剩余桃子为偶数x时,吃前桃子数为 x * 2 + 1

规律已找到,直接写代码

public static void Main(string[] args)
{
    Console.Write("请输入天数:");
    int n = Convert.ToInt32(Console.ReadLine());
    int tao = 1;
    for (int i = 0; i < n; i++)
    {
        if (tao % 2 == 0) 
        {
            tao = tao * 2 + 1;
        }
        else
        {
            tao = (tao + 1) * 2;
        }
    }
    Console.WriteLine("桃园桃子总数为:{0}",tao);
}

image.png

如果没有上面分析,直接贸然写,估计会耽误很长时间吧....
数学基础还是很有必要的,还好我喜欢写之前,先用假数据预测一波,然后再找规律,最后写代码

文末总结

不能眼高手低,看似简单的问题,实际着手写起来可能很棘手,理论分析很重要,但是写出来才显本事
其实很多数学问题,都可以用代码来实现,包括解方程!下次可以搞个鸡兔同笼问题玩玩....