【华为OD题库-032】数字游戏-java

题目

小明玩一个游戏。系统发1+n张牌,每张牌上有一个整数。第一张给小明,后n张按照发牌顺序排成连续的一行。需要小明判断,后n张牌中,是否存在连续的若干张牌,其和可以整除小明手中牌上的数字.
输入描述:
输入数据有多组,每组输入数据有两行,输入到文件结尾结束。
第一行有两个整数n和m,空格隔开。m代表发给小明牌上的数字
第二行有n个数,代表后续发的n张牌上的数字,以空格隔开。
输出描述:
对每组输入,如果存在满足条件的连续若干张牌,则输出1:否则,输出0
补充说明:
1<=n<= 1000
1<=牌上的整数<= 400000输入的组数,不多于1000
用例确保输入都正确,不需要考虑非法情况
示例1
输入:
6 7
2 12 6 3 5 5
10 11
1 1 1 1 1 1 1 1 1 1
输出
0
说明:
两组输入。
第一组小明牌的数字为7,再发了6张牌。第1、2两张牌数字和为14,可以整除7,输出1。
第二组小明牌的数字为11,再发了10张牌,这10张牌数字和为10,无法整除11,输出0。

思路

以单组数据来看,对于给定数组nums,是否存在连续和能够被指定k整除?可以想到一下几种方案:

  1. 暴力破解
  2. 组合思想
  3. 前缀和

思路一:暴力破解

双层循环:
外层i表示,依次以i开始的连续数组
内存循环变量j,初始值为i。求以i开始的连续数组的和,(即nums[i]+nums[i+1]+…+nums[j]),如果存在某个和能够被k整除,那么返回1
两层遍历完了都没有找到这样的连续数组,那么返回0

思路二:组合思想

找到nums所有的子连续数组:组合思想可参考:【JAVA-排列组合】一个套路速解排列组合题。
剪枝的关键在于判断数组是否连续,path中可以存放位置,如果是连续,那么path最后一个位置应该等于当前位置-1,即:i-1=path.peekLask();
如果某个子数组的和能够被k整除,那么返回1,否则返回0

思路三:前缀和
参考leetcode原题:974. 和可被 K 整除的子数组
leetcode的题目考虑了负数,虽然本题的牌的数字不会有正数,但这里还是对正负数都考虑进来。

设P[i]为nums数组的前i项的和
对于sum(i,j)=num[i]+num[i+1]+…+num[j]=P[j]-P[i-1]。
假设nums的i~j区间的和能够被k整除。
即:sum(i,j)%k==0,即(P[j]-P[i-1])%k=0,
即:(P[j]%k - P[i-1]%k)%k=0。
考虑同为正负的情况:P[j]%k == P[i-1]%k时上式成立
如果一正一负:|P[j]%k - P[i-1]%k| = k时上式成立,假设P[j]%k为正,P[i-1]%k为负,那么去掉绝对值后表达式为:P[j]%k = k+P[i-1]%k
综合正负数的情况,表达式可以写为:(P[j]%k+k)%k == (k+P[i-1]%k)%k,即,当前缀和为s时,考虑s可能为负数的情况,那么对k求余数可以写为: (s%k+k)%k

上面的推导可能比较抽象,现在以具体数据来说明过程:
假设我们的nums为:4 5 -4 -2 -7 -3 1,k为5。以下3行分别为nums,前缀和,对k求余((s%k+k)%k)的结果:
在这里插入图片描述
依次遍历nums,找到以当前nums[j]结尾的连续数组,判断其和能够整除k的数组有多少个?
j=0时,nums[j]=4,要满足(P[j]%k - P[i-1]%k)%k=0,才能找到满足条件的连续数组,现在P[j]%k=4,是否存在P[i-1]%k=4?i必须小于等于j, 明显不存在。
j=1时,P[j]%k=4,是否存在P[i-1]%k=4,即在j前面的求余结果是否有4,第一个为4,存在(i=1)。也就是说sum(1,1)能够被5整除。
j=2时,P[j]%k=0,第三行在位置2之前是否存在0?根据上面的逻辑不存在,但是实际上此时余数都为0了,肯定是能被k整除的,可以在0的左侧假设有P[-1]=0,这样当余数为0时,就能保证一定能够找到一个相同值,从而判断为满足条件。即sum(0,2)能够被5整除
j=3,P[j]%k=3,前面找不到
j=4,P[j]%k=1,前面找不到
j=5,P[j]%k=3,找得到,当i=4时,P[3]%k=3,即sum(4,5)能够被5整除
j=6,P[j]%k=4,在其前面能够找到4,i分别为1和2时,P[0]%k=4,P[1]%k=4,即sum(1,6),sum(2,6)均能被5整除

综上:我们可以用一个变量来存放前缀和%k出现的次数,比如map。然后遍历nums,先求出当前的前缀和sum,再求余数mod=(sum%k+k)%k,然后在map中找是否存在map.get(mod)>0,如果存在,那么就找到了这样的连续数组,如果不存在,则将map.get(mod)++后继续查找。
前缀和%k的值域范围刚好为:0~k-1,所以也可以用一个数组dp来代替map,它标识的含义是,mod值等于key出现了val次。考虑到要设P[-1]=0,即mod值为0在初始状态就要出现一次,那么将dp[0]=1。

题解

给出了三种思路在本题的具体实现,前缀和确实很抽象,也不好表达,对此不理解的多看看974. 和可被 K 整除的子数组的题解

package hwod;

import java.util.*;
import java.util.stream.Collectors;

public class NumberGame {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        List<Integer> list1 = new ArrayList<>();//存放给定的牌
        List<List<Integer>> list2 = new ArrayList<>();//牌堆
        while (sc.hasNextLine()) {
            String firstLines = sc.nextLine();
            if ("".equals(firstLines)) break;
            list1.add(Arrays.stream(firstLines.split(" ")).mapToInt(Integer::parseInt).toArray()[1]);
            String secondLines = sc.nextLine();
            list2.add(Arrays.stream(secondLines.split(" ")).mapToInt(Integer::parseInt).boxed().collect(Collectors.toList()));
        }
        List<Integer> res = numberGame(list1, list2);
        for (Integer re : res) {
            System.out.println(re);
        }
    }

    private static List<Integer> numberGame(List<Integer> list1, List<List<Integer>> list2) {
        List<Integer> res = new ArrayList<>();
        for (int i = 0; i < list1.size(); i++) {
            res.add(checked3(list2.get(i), list1.get(i)));
        }
        return res;
    }

    /**
     * 暴力破解
     * @param list   牌堆
     * @param target 被除的值
     * @return 如果存在连续和能够整除target,返回1,否则返回0
     */
    private static int checked(List<Integer> list, Integer target) {
        for (int i = 0; i < list.size(); i++) {
            int sum = 0;
            for (int j = i; j < list.size(); j++) {
                sum += list.get(j);
                if (sum % target == 0) return 1;
            }
        }
        return 0;
    }

    private static int res = 0;

    /**
     * 组合思想
     * @param list
     * @param target
     * @return
     */
    private static int checked2(List<Integer> list, Integer target) {
        LinkedList<Integer> path = new LinkedList<>();
        dfs(list, 0, path, 0, target);
        return res;
    }

    private static void dfs(List<Integer> list, int start, LinkedList<Integer> path, int sum, int k) {
        if (!path.isEmpty() && sum % k == 0) {
            res = 1;
            return;
        }
        for (int i = start; i < list.size(); i++) {
            if (!path.isEmpty() && path.peekLast() != i - 1) continue;
            if (res != 0) break;
            path.addLast(i);
            dfs(list, i + 1, path, sum + list.get(i), k);
            path.removeLast();
        }
    }

    /**
     * 设P[i]为前i项的前缀和
     * sum(i,j)=num[i]+num[i+1]+...+num[j]=P[j]-p[i-1]
     * (P[j]-p[i])%k==0  ==>  (P[j]%k - p[i-1]%k)%k=0
     *
     * @param list
     * @param k
     * @return 如果存在连续和能够整除k,返回1,否则返回0
     */
    private static int checked3(List<Integer> list, Integer k) {
        int[] dp = new int[k];
        dp[0] = 1;
        int sum = 0;
        for (int i = 0; i < list.size(); i++) {
            sum += list.get(i);
            int mod = (sum % k + k) % k;
            if (dp[mod] != 0) return 1;
            dp[mod]++;
        }
        return 0;
    }
}


推荐

如果你对本系列的其他题目感兴趣,可以参考华为OD机试真题及题解(JAVA),查看当前专栏更新的所有题目。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/177923.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DB2—03(DB2中常见基础操作)

DB2—03&#xff08;DB2中常见基础操作&#xff09; 1. 前言1.1 oracle和mysql相关 2. db2中的"dual"2.1 SYSIBM.SYSDUMMY12.2 使用VALUES2.3 SYSIBM.SYSDUMMY1 "变" dual 3. db2中常用函数3.1 nvl()、value()、COALESCE()3.2 NULLIF() 函数3.3 LISTAGG() …

成为AI产品经理——AI产品经理工作全流程

一、业务背景 背景&#xff1a;日常排球训练&#xff0c;中考排球项目和排球体测项目耗费大量人力成本和时间成本。 目标&#xff1a;开发一套用于实时检测排球运动并进行排球垫球计数和姿势分析的软件。 二、产品工作流程 我们这里对于产品工作流程的关键部分进行讲解&…

SQL 中的 MIN 和 MAX 以及常见函数详解及示例演示

SQL MIN() 和 MAX() 函数 SQL中的MIN()函数和MAX()函数用于查找所选列的最小值和最大值&#xff0c;分别。以下是它们的用法和示例&#xff1a; MIN() 函数 MIN()函数返回所选列的最小值。 示例&#xff1a; 查找Products表中的最低价格&#xff1a; SELECT MIN(Price) F…

Vue 重写push和replace方法,解决:Avoided redundant navigation to current location

当我们使用编程式路由导航跳转路径时&#xff0c;如果我们两次携带同样的参数进行跳转&#xff0c;会进行页面报错&#xff1a; 那产生这个问题的原因是什么呢&#xff1f; 我们接收并输出调用push方法返回的结果&#xff1a; 会发现这是一个Promise对象 我们都知道&#xff…

2023年G2电站锅炉司炉证考试题库及G2电站锅炉司炉试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年G2电站锅炉司炉证考试题库及G2电站锅炉司炉试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&#xff09;特种设备作业人员上岗证考试大纲…

【Java 进阶篇】Redis 数据结构:轻松驾驭多样性

引言 Redis是一款强大的键值对存储系统&#xff0c;其数据结构的多样性是其引以为傲的特点之一。在这篇博客中&#xff0c;我们将深入探讨Redis的主要数据结构&#xff0c;包括字符串、哈希表、列表、集合和有序集合&#xff0c;并通过实例代码演示它们的用法。 1. 字符串&am…

小程序存在优惠卷遍历,但是歪了

进入小程序&#xff0c;因为是一个小商城&#xff0c;所以照例先查看收货地址是否存在越权&#xff0c;以及能否未授权访问&#xff0c;但是发现不存在这些问题&#xff0c;所以去查看优惠卷 进入领券中心&#xff0c;点击领取优惠券时抓包 发现数据包&#xff0c;存在敏感参数…

基于SpringBoot+Vue的体检预约管理系统

基于SpringBootVue的体检预约管理系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBootMyBatisVue工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 主页 管理员界面 用户界面 摘要 体检预约管理系统是一种基于Spring Boot…

Node.js入门指南(一)

目录 Node.js入门 什么是Node.js Node.js的作用 Node.js安装 Node.js编码注意事项 Buffer(缓冲器&#xff09; 定义 使用 fs模块 概念 文件写入 文件读取 文件移动与重命名 文件删除 文件夹操作 查看资源状态 路径问题 path模块 Node.js入门 什么是Node.js …

SSH连接远程服务器报错:WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED 解决方法

一.错误描述 报错信息里提示了路径信息/root/.ssh/known_hosts:20 二.解决方案 方法一 输入以下指令&#xff1a; ssh-keygen -R XXX&#xff08;需要连接远程服务器的ip&#xff09; 按照我的例子ip:10.165.7.136&#xff0c;会返回以下信息: 重新尝试连接&#xff1a; 输…

数据结构学习笔记——多维数组、矩阵与广义表

目录 一、多维数组&#xff08;一&#xff09;数组的定义&#xff08;二&#xff09;二维数组&#xff08;三&#xff09;多维数组的存储&#xff08;四&#xff09;多维数组的下标的相关计算 二、矩阵&#xff08;一&#xff09;特殊矩阵和稀疏矩阵&#xff08;二&#xff09;…

7种SQL的进阶用法

1.自定义排序&#xff08;ORDER BY FIELD&#xff09; 在MySQL中ORDER BY排序除了可以用ASC和DESC之外&#xff0c;还可以使用自定义排序方式来实现。 CREATE TABLE movies ( id INT PRIMARY KEY AUTO_INCREMENT, movie_name VARCHAR(255), actors VARCHAR(255), price DEC…

MySQL面试,MySQL事务,MySQL锁,MySQL集群,主从,MySQL分区,分表,InnoDB

文章目录 数据库-MySQLMySQL主从、集群模式简单介绍1、主从模式 Replication2、集群模式3、主从模式部署注意事项 UNION 和 UNION ALL 区别分库分表1.垂直拆分2、水平拆分 MySQL有哪些数据类型1、整数类型**&#xff0c;2、实数类型**&#xff0c;3、字符串类型**&#xff0c;4…

MySQL 事务的底层原理和 MVCC(一)

在事务的实现机制上&#xff0c;MySQL 采用的是 WAL&#xff08;Write-ahead logging&#xff0c;预写式日志&#xff09;机制来实现的。 在使用 WAL 的系统中&#xff0c;所有的修改都先被写入到日志中&#xff0c;然后再被应用到系统中。通常包含 redo 和 undo 两部分信息。 …

初识Java 18-2 泛型

目录 构建复杂模型 类型擦除 C中的泛型 迁移的兼容性 类型擦除存在的问题 边界的行为 对类型擦除的补偿 创建类型实例 泛型数组 本笔记参考自&#xff1a; 《On Java 中文版》 构建复杂模型 泛型的一个优点就是&#xff0c;能够简单且安全地创建复杂模型。 【例子&am…

广告机/商业显示屏_基于MT878安卓主板方案

安卓主板在广告机领域扮演着重要的角色。无论是在商场、车站、酒店、电梯、机场还是高铁站&#xff0c;LED广告机广泛应用&#xff0c;并通过不同方式进行播放和管理。 广告机/商业显示屏_基于MT878安卓主板方案 基于MT8788安卓主板方案的广告机采用了联发科MT8788八核芯片方案…

力扣.面试题 04.06. 后继者(java 树的中序遍历)

Problem: 面试题 04.06. 后继者 文章目录 题目描述思路解题方法复杂度Code 题目描述 设计一个算法&#xff0c;找出二叉搜索树中指定节点的“下一个”节点&#xff08;也即中序后继&#xff09;。 如果指定节点没有对应的“下一个”节点&#xff0c;则返回null。 思路 由于题…

msvcp140.dll是什么?msvcp140.dll丢失的有哪些解决方法

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“msvcp140.dll丢失”。这个错误通常会导致某些应用程序无法正常运行。为了解决这个问题&#xff0c;我们需要采取一些措施来修复丢失的msvcp140.dll文件。本文将详细介绍5个解决msvcp140.dl…

visual studio 如何建立 C 语言项目

安装这个 模块。 新建 空项目 创建完成 写demo 点击运行&#xff1a;

计算机毕业设计 基于微信小程序的“共享书角”图书借还管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…