2014新浪校招笔试题:取水果(17年第一篇让人懵逼的面试题)

算法设计(动态规划):新水果取名(JAVA代码实现及题目分析) 新水果起名问题 题目内容: 两种水果杂交出一种新水果,现在给新水果取名,要求这个名字中包含以前两种水果的字母,且名字尽量短,即:以前的水果名字arr1、arr2是新水果名arr的子序列,使用动态规划的思想设计算法得到新水果名arr。 输入格式: 以空格分开两个水果的名字 输出格式: 新水果的名字 输入样例: apple peach 输出样例: appleach 这个沙雕问题浪费了我三个小时(NMD... 阅读详情

前言

2017 年,我还是会坚持每周一篇面试题,当然我每周看的面试题肯定是不止一篇的,我是在这周看过的面试题中,选择一题自己认为较好的来写。因为每一篇都写,不现实,写一篇博客,需要的时间也是挺长的,所以选择较好较大众化的题目。

一、题目

有任意种水果, 每种水果个数也是任意的, 两人轮流从中取出水果, 规则如下:
1) 每一次应取走至少一个水果; 每一次只能取走一种水果的一个或者全部.
2) 如果谁取到最后一个水果就胜.

给定水果种类 N 和每种水果的个数 M1, M2, …, Mn, 算出谁取胜.

二、解题

看到这个题目的时候,我整个人懵逼了,啥,到底是叫我做什么?一脸懵逼,然后再看题目,又重新看题目,才发现,题目有个隐含的条件,就是 这两个人足够聪明,充分利用了规则。 可是单单凭借这一点,还是不知道该从何下手,其实这题是 必胜策略题,可以通过用递推的方式找一下规律解决该题。

在递推之前,我们先来看看题目中一共给出了什么条件:
1.N 种不同的水果
2.每种水果的个数分别为:M1, M2, …, Mn,
3.有两个人,轮流取水果,每一次应取走至少一个水果; 每一次只能取走一种水果的一个或者全部
4.谁取到最后一个水果就胜

那好,根据上面的分析, 我们先假设两个人分别为 A 和 B ,A 先取水果,水果的总个数为 M ,即 M = M1 + M2 + M3 + … + Mn,

(1)N = 1(只有一种水果)

A 先拿,因为知道水果的种类,所以 A 不需要考虑水果有多少个,他只要第一次拿的时候,拿完这一种水果就可以获胜了。

结论:N = 1 ,A 必胜

(2)N = 2 (有两种水果)

此时两个人都不敢直接拿走一种水果, 因为那样会送对方进入(1)的必胜局中, 自己必败.所以 A 和 B 都只能一个一个的拿, 这样谁拿走最后一个就由 M(水果的总个数) 的奇偶性决定。也就是说 ,M 是奇数,A 必胜,M 是偶数,B 必胜

当然我在想这个例子的时候,不小心进入了一个误区,假如第一种水果 3 个,第二种水果 2 个,水果总数为奇数,满足条件,假如 A 先拿第一种水果,B 再拿一个第一种水果,A 再拿一个,然后 B 拿全部第二种,B 赢。可是 A 是足够聪明的,A 拿了第一种水果,B 跟着拿,此时 A 肯定不会接着拿第一种水果的,因为这样自己必败,所以他肯定会选择拿第二种水果,这样就能必胜了。所以还是 N = 2 的时候,水果的总数为奇数,先拿必胜,如果水果的总数为偶数,先拿必败

结论:N = 2 ,M 是奇数, A 必胜; 否则 A 必败

(3)N = 3 (有三种水果)

当水果种类大于 2 种时,不太好确定到底谁获胜,需要根据各种水果数量的奇偶数来判断,因此先按水按数量的奇偶分类,有 4 种可能:

  • 3 种水果的个数分别都是奇数个
  • 3 种水果的个数分别都是偶数个
  • 其中 2 种水果的个数是奇数个,其中 1 种水果的个数是偶数个
  • 其中 2 种水果的个数是偶数个,其中 1 种水果的个数是奇数个

无论上面是哪种情况,A 都可以立即让 B 进入与 (2) 相反的局面(必败的局面),比如:

  • 3 种水果的个数分别都是奇数个: A 随便拿掉一种水果,剩余的水果总数为偶数(奇数 + 奇数 = 偶数),剩余两种水果,进入了(2)的局面,水果总数为偶数,先拿必败,所以 B 必败,A必胜
  • 3 种水果的个数分别都是偶数个: 跟上面是一样的,A 随便拿掉一种水果,剩余的水果总数为偶数(偶数 + 偶数 = 偶数),剩余两种水果,进入了(2)的局面,水果总数为偶数,先拿必败,所以 B 必败,A必胜
  • 其中 2 种水果的个数是奇数个,其中 1 种水果的个数是偶数个: A 拿走偶数个的水果的全部,也会进入(2)的局面且水果总数为偶数,A 必胜
  • 其中 2 种水果的个数是偶数个,其中 1 种水果的个数是奇数个: A 拿走奇数个的水果的全部,也会进入(2)的局面且水果总数为偶数,A 必胜

结论:N = 3 ,A 必胜

(4)N = 4 (有四种水果)

A 先取, 他肯定不会全部取走一种, 因为会送 B 进入(3)的必胜态, A 就必败.

因此 A 只能取一个

  • 若 A 取走一个,变成了三种水果,就是变成 (3) 了, 说明 4 种水果都只有一个(否则 A 足够聪明,可以避免这种情况) 即 M 为偶数 4 , A 必败
  • 若 A 取完这一个还剩 4 种水果, 那 B 同上分析也只敢取一个,依次类推, 谁最后面对变成 (3) 的情况就必败了.

也就是说 M - 4 必须是奇数,这样 A 才会让 B 进入最终的必败局面,所以胜负由 M - 4 的奇偶性决定, 也就是说胜负由 M 的奇偶性决定

结论:N = 4 ,M 是奇数, A 必胜; 否则 A 必败

通过上面的递推,我们基本可以看到规律了:

  • N 为奇数,A 必胜
  • N 为偶数,如果 M 为奇数,A 必胜;如果 M 为偶数,A 必败

三、编程

最后我们通过编程解决 GitHub 地址:https://github.com/TwoWater/Interview/blob/master/Interview/src/com/liangdianshui/TakeTheFruit.java


package com.liangdianshui;

import java.util.Scanner;


/**
 * <p>
 *   有任意种水果,每种水果个数也是任意的,两人轮流从中取出水果,规则如下:
 *   1)每一次应取走至少一个水果;每一次只能取走一种水果的一个或者全部
 *   2)如果谁取到最后一个水果就胜
 *    给定水果种类N和每种水果的个数M1,M2,…Mn,算出谁取胜。
 *   (题目的隐含条件是两个人足够聪明,聪明到为了取胜尽可能利用规则)
 * </p>
 * 
 * @author liangdianshui
 *
 */
public class TakeTheFruit {
    private static final String EXIT = "q";

    public static void main(String[] args) throws Exception {
        Scanner scanner = new Scanner(System.in);
        String input;
        int[] fruitNums;

        do {
            System.out.println("假设 A 和 B 两个人,A 先取水果");
            System.out.println("请输入每种水果的个数(空格或回车分隔):");
            System.out.println("输入 Q 或  q 退出");

            if (EXIT.equalsIgnoreCase(input = scanner.nextLine())) {
                System.out.println("Exit");
                break;
            }

            input = input.trim();
            if (input.length() != 0) {
                fruitNums = initFruitNums(input);
                boolean isWin = takeTheFruitGame(fruitNums, fruitNums.length);
                if(isWin){
                    System.out.println("A 赢");
                }else{
                    System.out.println("B 赢");
                }
                System.out.println("--------------------------------------------");
            }
        } while (true);
    }

    /**
     * 初始化每种水果的个数
     * 
     * @param input
     * @return
     */
    private static int[] initFruitNums(String input) {
        String[] nums = input.split("\\s+");
        int[] fruitNums = new int[nums.length];
        int num;
        for (int i = 0; i < nums.length; i++) {
            num = Integer.parseInt(nums[i]);
            if (num <= 0) {
                throw new IllegalArgumentException("水果数量不能为 0 或负数:" + num);
            }

            fruitNums[i] = num;
        }

        return fruitNums;
    }

    /**
     * 递归法
     * 
     * @param fruitNums
     * @param numOfTypes
     * @return
     */
    private static boolean takeTheFruitGame(int[] fruitNums, int numOfTypes) {

        //当水果种类为1的时候,必胜
        if (numOfTypes == 1) {
            return true;
        }

        // 当水果种类为2的时候
        if (numOfTypes == 2) {
            return sumOfTwoFruitNums(fruitNums) % 2 == 1;
        }

        // 当水果种类大于等于3的时候
        int num;
        for (int i = 0; i < fruitNums.length; i++) {
            num = fruitNums[i];
            if (num == 0)
                continue;

            fruitNums[i] = 0;
            if (!takeTheFruitGame(fruitNums, numOfTypes - 1)) {
                fruitNums[i] = num;
                return true;
            }
            if (num > 1) {
                fruitNums[i] = num - 1;
                if (!takeTheFruitGame(fruitNums, numOfTypes)) {
                    fruitNums[i] = num;
                    return true;
                }
            }

            fruitNums[i] = num;
        }

        return false;
    }

    /**
     * <p>
     *  通过结论直接输出结果
     *  N 为奇数,A 必胜
     *  N 为偶数,如果 M 为奇数,A 必胜;如果 M 为偶数,A 必败
     * </p>
     * @param fruitNums
     * @return
     */
    private static boolean takeTheFruitGame2(int[] fruitNums) {
        if (fruitNums.length % 2 == 1) {
            return true;
        }

        return sumOfFruitNums(fruitNums) % 2 == 1;
    }

    private static int sumOfTwoFruitNums(int[] fruitNums) {
        int num1 = 0;
        int num2 = 0;

        for (int num : fruitNums) {
            if (num > 0) {
                if (num1 == 0) {
                    num1 = num;
                } else {
                    num2 = num;
                    break;
                }
            }
        }

        return num1 + num2;
    }

    private static int sumOfFruitNums(int[] fruitNums) {
        int sum = 0;

        for (int num : fruitNums) {
            sum += num;
        }

        return sum;
    }
}
新浪微博笔试题 这个还是去年校招时候做的笔试题了,一面之后发过来这样两道题,回复之后就被告知通过面试了。虽然自己写的不专业,但是现在翻出来看看,当时还是写得比较认真。竞品分析、数据分析这种,还是应该每周写一点锻炼锻炼。把这个题和我当初的答案贴在这里,就当给自己一个提醒吧。 1、请列举出微博的竞品,并说明你认为是竞品的理由。        微博是一个社交+资讯的平台,所以微博的竞品主要是指从社交和资 阅读详情

相关推荐

【华为2019年校园招聘】2019-4-17 软件题-水果摊小买卖

题目描述 小王手里有点闲钱,想着做点卖水果的小买卖,给出两个数组m,n,用m[i]表示第i个水果的成本价, n[i]表示第i个水果能卖出的价钱,假如现在有本钱k元,试问最后最多能赚多少钱? 说明: 1. 每种水果只能买一次,只能卖一次; 2. 数组m,n大小不超过50; 3. 数组元素为正整数,不超过1000 输入描述 1. 数组m, n; 2. 本钱k 输出描述 最多能赚多少钱 示例 输...

yj_isee的博客 9634

水果笔试题

水果笔试题 题目:本公司现在要给公司员工发波福利,在员工工作时间会提供大量的水果供员工补充营养。由于水果种类比较多,但是却又不知道哪种水果比较受欢迎,然后公司就让每个员工报告了自己最爱吃的k种水果,并且告知已经将所有员工喜欢吃的水果存储于一个数组中。然后让我们统计出所有水果出现的次数,并且求出大家最喜欢吃的前k种水果。  ps:要求打印出最喜欢的水果,并且效率尽可能的高。 提示:尽量STL

step_ma的博客 1828

题目1073: 搬水果

题目描述         在一个果园里,小明已经将所有的水果打了下来,并按水果的不同种类分成了若干堆,小明决定把所有的水果合成一堆。每一次合并,小明可以把两堆水果合并到一起,消耗的体力等于两堆水果的重量之和。当然经过 n‐1 次合并之后,就变成一堆了。小明在合并水果时总共消耗的体力等于每次合并所耗体力之和。        假定每个水果重量都为 1,并且已知水果的种类数和每种水果的数

落日小屋 3364

Codevs 题目1299 切水果 (线段树)

题目描述 Description 简单的说,一共N个水果排成一排,切M次,每次切[L,R]区间的所有水果(可能有的水果被重复切),每切完一次输出剩下水果数量 数据已重新装配,不会出现OLE错误 时限和数据范围适当修改,避免数据包过大而浪费空间资源 输入描述 Input Description 第1行共包括2个正整数,分别为N,M。 接下来m行每行两个

Jogging_Clown 889

绝缘体上硅(SOI) vs 传统硅片:5个关键性能对比及适用场景分析

本文深入对比了绝缘体上硅(SOI)与传统硅片在功耗、速度、隔离性等5个关键性能维度的差异,并分析了各自适用场景。SOI技术凭借其独特的埋氧层结构,在低功耗、高频应用和极端环境下展现出显著优势,特别适合移动设备、汽车电子和航天应用。

weixin_30335575的博客 555

西门子S7通信协议TSAP配置全攻略:从默认值到自定义修改(附各型号对照表)

本文深入解析西门子S7通信协议中TSAP配置的核心原理与实战方法。针对S7-200/300/400/1200/1500等主流PLC型号,提供了默认TSAP对照表,并详细阐述了如何根据机架号和插槽号计算或自定义Remote TSAP。文章结合常见连接失败案例,给出了系统化的排错流程,旨在帮助工程师快速打通S7通信链路,提升工业自动化现场调试效率。

weixin_29163797的博客 278

外行人都能看得懂的机器学习,错过了血亏!

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33905756的博客 280

发那科机器人Modbus通讯配置全攻略:从IP设置到信号调试

本文详细介绍了发那科机器人Modbus通讯的配置方法,从基础认知到IP设置、端口配置、信号调试及故障排查。重点讲解了UOP和DI/DO信号的配置技巧,帮助工程师快速实现机器人与PLC的稳定通讯,提升自动化系统效率。

weixin_27872611的博客 623

AI智能体确定性工程:感知、判断与代码Harness

AI工程化领域,大模型的概率性输出与自动化流程的确定性需求之间存在天然矛盾。要让智能体从“会生成”进阶为“可靠执行”,关键在于为其构建可感知、可验证的运行环境。确定性代码框架(Code Harness)正是为此而生,它通过输入感知、环境探测与输出验真三层机制,将模型概率性输出转化为系统级确定性结果。这种工程范式在文档批处理、数据清洗、自动化报告生成等场景中价值显著,能有效提升批量任务的稳定性与可回溯性。本文聚焦Heides项目,解析其如何为AI智能体装上“感官”与“判断力”,实现从单次跑通到稳定批量运行的分

weixin_33871366的博客 443

配置cts performance最优范围

这里写自定义目录标题cts例如此案例中,我们多测几次,发现Measured frame rate 的平均值为average=(380+389+380+371)/4=380 cts by VinterYoung Expected achievable frame rates for OMX.MTK.VIDEO.DECODER.HEVC video/hevc 1280x720: [75.0, 262.0]. Measured frame rate: [380.5645006622224, 389.3983545

o343196469的博客 1319

OpenClaw 与十几款国产 “龙虾” 智能体深度对比

详解介绍OpenClaw和各种类似国产“龙虾”智能体工具深度对比

program哲学 2349

输入一个文件和一个字符,统计该字符在文件中出现的次数

def countstr(filename,str1): filenames = filename + ".txt" f = open(filenames,'r') count = 0 for line in f: for i in line: if i == str1: count += 1...

Wut_LS的博客 8512

手把手教你完成基于YOLOv8的水果/商品/食堂/蔬菜/饮料/书籍识别与计价系统,前台+后台管理系统

手把手教你完成基于YOLOv8的商店的水果/商品/食堂/蔬菜/饮料/书籍识别与计价系统,前台+后台管理员系统,可进行目标检测的操作和展示,实现对图片、视频和摄像头的实时目标检测

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 2456

今年我错过了哪些优秀的技术书?在线等,急!

作为程序员工作累成狗但现实还在逼你不断学习这一年,你都学到了哪些新技术这一年,你又错过了哪些新知识跟上我们的速度别担心落后于时代2018 · GitChat 年度最受欢迎...

mobilehub 318

【零基础学习CAPL】——CAN报文的发送(CRC——ChecSum值)

本章主要介绍带有CRC值的报文发送一般报文可使用CANoe的IG模块直接发送,但带有CRC值的报文就只能编写脚本进行发送,以下详细讲解在配合Panel面板情况下,如何进行带有循环冗余码的报文进行报文的发送。

LOVE135149的博客 1913

智能解译城市进程:遥感影像建筑物提取研究全景与前沿进展(数据集及代码)

随着全球城市化进程的加速,高效、精准地监测城市建筑物分布对城市规划、灾害评估、人口估算及智慧城市建设具有重要意义。传统的人工测绘方法耗时费力,难以满足大范围、动态更新的需求。而遥感影像建筑物提取技术,借助深度学习与计算机视觉,能够自动化识别并提取建筑物轮廓,极大地提升了城市信息获取的效率和精度。首先,建筑物提取是遥感影像解译的核心任务之一。

hanfeng5268的博客 591

新浪2020校园招聘笔试题及答案

public class Test { public static void main(String[] args) { Test t = new Test(); Scanner sc = new Scanner(System.in); String str = sc.next(); System.out.println(str); Sy...

find_happiness的博客 1212

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

C/C++校招笔试面试经典题目总结三

题目21:求下面函数的返回值,输入x=9999;(微软) int func(x) { int countx = 0; while(x) { countx ++; x = x&(x-1); } return countx; } 解答: 其实这个程序的意思就是求9999的二进制中有多少个1(别问我为什么知道的,可以查看剑指of

疯狂的猫 1978

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

新浪微博 2019校园招聘笔试编程题-2018.09.15

#include &lt;iostream&gt; #include &lt;cstring&gt; using namespace std; char arr[255]; int main() { string str1, str2; getline(cin, str1); getline(cin, str2); for(int i=0; i&lt;str...

whl_program的博客 1366

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

九度笔记之 1420:Jobdu MM分水果

动态规划分水果,使两个人尽可能分的差值最小

KingEasternSun的专栏 2052

一个关于“取数问题”的游戏

最近在算法课上老师讲了一个“qus”

PCPwLer's 1569

新浪2014校招的两道笔试题. [搬萝卜 & 取水果]

2. (10分) 一只小兔子有100根胡萝卜, 它要走50米才能到家, 每次它最多搬50根胡萝卜, 而每走1米就要吃掉1根胡萝卜, 请问它最多能把多少根胡萝卜搬到家里? 3. (10分) 有任意种水果, 每种水果个数也是任意的, 两人轮流从中取出水果, 规则如下: 1) 每一次应取走至少一个水果; 每一次只能去走一种水果的一个或者全部. 2) 如果谁取到最后一个水果就胜. 给定水果种类N和

lzl124631x的专栏 4226

查询水果价格(15 分)

给定四种水果,分别是苹果(apple)、梨(pear)、桔子(orange)、葡萄(grape),单价分别对应为3.00元/公斤、2.50元/公斤、4.10元/公斤、10.20元/公斤。 首先在屏幕上显示以下菜单: [1] apple [2] pear [3] orange [4] grape [0] exit 用户可以输入编号1~4查询对应水果的单价。当连续查询次数超过5次时,程

qq_40787658的博客 3万+

转帖)错过了一次,也许就错过了一辈子

为了订婚的细节,曼菁和立平先是争执不下,继而演变成各持己见,相互相指责,最近吵到脸红脖子粗....盛怒中,曼菁跳脚叫嚣着:「算了!干脆不要订了.......」立 平也不甘示弱~~~「不订就不订!」扔下狠话之后两人各自鼓着一肚子气回家了...。     这一肚子气,气的全是对方,都认定那个人简直莫名其妙,不可理喻,根本是没把我当一回事!继而发酵为───他(她)一定不爱我,再转化成,如果他(她)在...

weixin_34357928的博客 160

思特奇2019校招笔试题

这里仅记录自己不会的哦,有需要的可以参考下哦 1Java接口的修饰符可以为(d) A.private B.proected C.final D.abstarct 有这道题,我又重新理解了一下接口 接口用于描述系统对外提供的所有服务,因此接口中的成员常量和方法都必须是公开(public)类型的,确保外部使用者能访问它们; 接口仅仅描述系...

Mar.三月 1万+
上一篇: Git忽略文件.gitignore的使用
下一篇: Google刁钻古怪面试题
Two_Water
博客等级 码龄12年 573粉丝 134原创
评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值