学习记录:js算法(七十六):一手顺子

文章目录

    • 一手顺子
      • 思路一:贪心算法
      • 思路二:动态规划
      • 思路三:排序 + 计数

一手顺子

Alice 手中有一把牌,她想要重新排列这些牌,分成若干组,使每一组的牌数都是 groupSize ,并且由 groupSize 张连续的牌组成。
给你一个整数数组 hand 其中 hand[i] 是写在第 i 张牌上的数值。如果她可能重新排列这些牌,返回 true ;否则,返回 false

示例 1:
输入:hand = [1,2,3,6,2,3,4,7,8], groupSize = 3
输出:true
解释:Alice 手中的牌可以被重新排列为 [1,2,3][2,3,4][6,7,8]。示例 2:
输入:hand = [1,2,3,4,5], groupSize = 4
输出:false
解释:Alice 手中的牌无法被重新排列成几个大小为 4 的组。

思路一:贪心算法

function isNStraightHand(hand, groupSize) {if (hand.length % groupSize !== 0) {return false;}const cardCounts = {};hand.forEach(card => {cardCounts[card] = (cardCounts[card] || 0) + 1;});const keys = Object.keys(cardCounts).map(Number).sort((a, b) => a - b);while (keys.length) {const currentKey = keys[0];for (let i = 0; i < groupSize; i++) {const key = currentKey + i;if (!cardCounts[key]) {return false;}cardCounts[key]--;if (cardCounts[key] === 0) {delete cardCounts[key];keys.splice(keys.indexOf(key), 1);}}}return true;
}

讲解
这道题目的关键在于理解“连续的牌”和“每组牌数都是 groupSize” 的要求。为了满足这些条件,我们首先需要统计每张牌出现的次数,然后从最小的牌开始,尝试组成大小为 groupSize 的连续序列。这是因为如果我们要组成连续的序列,那么数量最多的牌(频率最高)应该尽可能放在序列的中间,而频率较低的牌则放在序列的两端,这样更容易组成连续的序列。

  1. 统计牌的频率:使用一个 Map 或对象来统计每张牌出现的次数。
  2. 排序牌的种类:根据牌的数值从小到大排序这些牌的种类。
  3. 尝试组成连续序列:从最小的牌开始,尝试组成大小为 groupSize 的连续序列。如果某一张牌的数量不足以形成一个完整的序列,那么就无法满足题目要求,返回 false
  4. 重复尝试直至所有牌都被分组:如果所有牌都能被分组,返回 true

思路二:动态规划

var isNStraightHand = function (hand, groupSize) {if (hand.length % groupSize !== 0) return false;const count = {};for (const card of hand) {count[card] = (count[card] || 0) + 1;}const uniqueCards = Object.keys(count).map(Number).sort((a, b) => a - b);const dp = new Array(hand.length / groupSize + 1).fill(false);dp[0] = true;for (const card of uniqueCards) {const neededGroups = count[card];for (let g = 1; g <= neededGroups; g++) {for (let j = dp.length - 1; j >= g; j--) {dp[j] = dp[j] || dp[j - g];}}}return dp[dp.length - 1];
};

讲解

  1. 统计牌的数量
    • 目的:创建一个对象 count,用于统计每种牌的数量。
    • 细节:遍历 hand 数组,更新每种牌的计数。
  2. 获取唯一牌并排序
    • 目的:获取所有不同的牌并进行排序。
    • 细节:使用 Object.keys(count) 获取不同的牌,并将其转换为数字类型和排序。
  3. 初始化动态规划数组
    • 目的:创建一个动态规划数组 dp,用于记录是否可以形成特定数量的组。
    • 细节:dp 数组的长度为总组数加一,初始值为 falsedp[0] = true 表示可以形成 0 组。
  4. 动态规划填充
    • 目的:更新 dp 数组,检查是否可以形成目标组数。
    • 细节:遍历每种牌,利用其数量更新 dp 数组,检查是否可以通过使用当前牌形成新的组数。
  5. 返回结果
    • 目的:返回是否可以形成所需数量的组。
    • 细节:dp[dp.length - 1] 表示是否可以形成总组数。

思路三:排序 + 计数

var isNStraightHand = function (hand, groupSize) {if (hand.length % groupSize !== 0) return false;const count = {};for (const card of hand) {count[card] = (count[card] || 0) + 1;}const uniqueCards = Object.keys(count).map(Number).sort((a, b) => a - b);for (const card of uniqueCards) {while (count[card] > 0) {for (let i = 0; i < groupSize; i++) {if (count[card + i] === undefined || count[card + i] <= 0) {return false;}count[card + i]--;}}}return true;
};

讲解

  1. 检查组大小
    • 目的:确保牌组的长度可以被 groupSize 整除。
    • 细节:如果 hand.length % groupSize !== 0,则返回 false,表示无法分组。
  2. 统计牌的数量
    • 目的:创建一个对象 count,用于统计每种牌的数量。
    • 细节:遍历 hand 数组,更新每种牌的计数。
  3. 获取唯一牌并排序
    • 目的:获取所有不同的牌并进行排序。
    • 细节:使用 Object.keys(count) 获取不同的牌,并将其转换为数字类型和排序。
  4. 构造顺子
    • 目的:检查是否可以构造出所需的顺子。
    • 细节:
      • 遍历每种牌 card
      • 使用 while 循环,直到当前牌的计数为 0
      • 尝试从 card 开始,连续取出 groupSize 张牌。
      • 如果在构造过程中发现某张牌不存在或计数不足,返回 false
  5. 返回结果
    • 目的:如果所有牌都成功构造出顺子,则返回 true
    • 细节:如果循环结束且未返回 false,则说明可以构造出所需的顺子,返回 true

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【开源鸿蒙】OpenHarmony 5.0轻量系统最小开发环境搭建

【开源鸿蒙】OpenHarmony 5.0轻量系统最小开发环境搭建 一、写在前面——为什么写本篇内容二、准备工作——下载源码前的准备2.1 准备基础环境2.2 准备命令行工具2.3 配置git用户凭据 三、下载OpenHarmony轻量系统最小源码3.1 使用ssh协议下载&#xff08;推荐&#xff09;3.2 …

SQL、MySQL、SQL Server的区别

SQL&#xff08;Structured Query Language&#xff09; SQL是一种标准化的编程语言&#xff0c;用于管理和操作关系数据库。 它用于插入、更新、查询和删除数据库中的数据。 SQL是独立于数据库的&#xff0c;这意味着同一个SQL命令可以在不同的数据库系统中使用&#xff0c…

c#获取目录下所有文件

c#获取目录下所有文件 一&#xff1a;Directory.GetFiles方法&#xff1a; var dirPath CommonMethod.GetDirectoryByType(FileTypeEnum.PowerTest); //获取目录下所有文件 var fileList Directory.GetFiles(dirPath, "*.*", SearchOption.AllDirectories).ToLis…

【Vue】Vue3.0(十五)Vue 3.0 中 hooks 的概念

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;Vue专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年10月22日21点50分 背景&#xff1a;在一些情况下&#xff0c;前台的组件是可以复用的&#xff0c;那这些复用的对象和数据&#xff0c;为…

学习记录:js算法(七十七):合并若干三元组以形成目标三元组

文章目录 合并若干三元组以形成目标三元组思路一 合并若干三元组以形成目标三元组 三元组 是一个由三个整数组成的数组。给你一个二维整数数组 triplets &#xff0c;其中 triplets[i] [ai, bi, ci] 表示第 i 个 三元组 。同时&#xff0c;给你一个整数数组 target [x, y, z]…

Prompt Engineering (Prompt工程)

2 prompt工程2大原则 2.1 给出清晰&#xff0c;详细的指令 策略1&#xff1a;使用分割符清晰的指示输出的不同部分&#xff0c;比如"",<>,<\tag>等分隔符 策略2&#xff1a;指定一个结构化的输出&#xff0c;比如json,html等格式 策略3&#xff1a;要…

使用openssl生成自签名证书(多域名)用于https的ssl验证

有时在项目的开发环境和测试环境,并不能获得正式的证书,但是项目的开发和测试又需要证书来模拟生产环境下的安全配置,此时就可以采用自签名证书。而且我们希望我们的证书能够在开发环境和测试环境中完全正常的使用,不会出现各种证书无效的提示和警告。此时就可以参考这里的…

Oracle视频基础1.1.2练习

1.1.2 需求&#xff1a; 查询oracle组件和粒度大小&#xff0c; select component,granule_size from v$sga_dynamic_components;Oracle SGA 中组件和粒度大小查询详解 在 Oracle 数据库的内存结构中&#xff0c;SGA&#xff08;System Global Area&#xff0c;系统全局区&am…

基于SSM房屋租赁管理系统的设计与实现

前言 房屋租赁管理系统&#xff0c;不仅可以改善用户线下到租赁公司进行查看房屋类型的局面以及预约信息等&#xff0c;还可以提供管理效率&#xff0c;同时也可以增强网站的竞争力。利用房屋租赁管理系统&#xff0c;可以有效地提高系统的人事的效率和信息化水平&#xff0c;…

Gateway 统一网关

一、初识 Gateway 1. 为什么需要网关 我们所有的服务可以让任何请求访问&#xff0c;但有些业务不是对外公开的&#xff0c;这就需要用网关来统一替我们筛选请求&#xff0c;它就像是房间的一道门&#xff0c;想进入房间就必须经过门。而请求想要访问微服务&#xff0c;就必须…

sa-token 所有的异常都是未登录异常的问题

在使用satoken的时候&#xff0c;有这么一个问题&#xff0c;就是不管我是什么错误&#xff0c;都会弹出未登录异常&#xff0c;起初的时候我以为satoken的拦截器会拦截所有的异常&#xff0c;但是今后测试才发现忽略了一点&#xff0c;也是最重要最容易忽视的一点。 如果我现在…

解决JeecgBoot微服务通过Gateway访问Swagger资源出现“Knife4j文档请求异常”

1.问题描述 基于jeecgboot单体版本,参照官方推荐的纯微服务项目拆分指南,对jeecgboot项目进行微服务拆分,将gateway和system模块启动成功后,通过gateway访问访问Swagger接口文档,出现“Knife4j文档请求异常”,如下图: 2.问题定位: 1.浏览器F12打开控制台,查看异常请…

【React】React 18:新特性与重大更新解析

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 React 18&#xff1a;新特性与重大更新解析并发渲染什么是并发渲染&#xff1f;…

Linux系统下串口AT指令控制EC20连接华为云物联网平台

一、前言 在当今万物互联的时代背景下&#xff0c;物联网技术的快速发展极大地推动了智能化社会的构建。作为其中的关键一环&#xff0c;设备与云端平台之间的通信变得尤为重要。本文介绍如何在Linux操作系统环境下&#xff0c;利用串口通信来实现EC20模块与华为云物联网平台的…

【JavaEE】【多线程】线程池

目录 一、线程池二、ThreadPoolExecutor类讲解2.1 构造方法2.1.1 corePoolSize和maximumPoolSize2.1.2 KeepAliveTime和unit2.1.3 workeQueue2.1.4 threadFactory2.1.5 handler 三、简易构造线程池四、自己实现一个简单线程池 一、线程池 线程池&#xff1a;线程池可以简单理解…

R语言笔记(二):向量

文章目录 一、Data structure: vectors二、Indexing vectors三、Re-assign values to vector elements四、Generic function for vectors五、Vector of random samples from a distribution六、Vector arithmetic七、Recycling八、Element-wise comparisons of vectors九、Comp…

Vue.js 学习总结(11)—— Vue3 Hook 函数实战总结

前言 在 Vue 3 中&#xff0c;Hook 函数是一种特殊的函数&#xff0c;用于封装可重用的逻辑和状态管理。Hook 函数允许你在 Vue 组件中提取和复用逻辑&#xff0c;而不是将所有逻辑都放在组件的选项对象中。它们可以帮助你更好地组织代码&#xff0c;提高代码的可维护性和可测…

Elasticsearch 解析:倒排索引机制/字段类型/语法/常见问题

Elasticsearch 是一个分布式的开源搜索引擎&#xff0c;广泛用于全文搜索、分析和数据存储。它基于 Apache Lucene 构建&#xff0c;支持 RESTful 风格的 API&#xff0c;使得开发者能够高效地存储和检索数据。本文将详细讲解 Elasticsearch 的基本原理&#xff0c;特别是其倒排…

网页上的视频怎么下载下来?三种方法

分享三个简单好用的网页视频下载工具&#xff0c;值得使用&#xff01; 1.IDM IDM 是一款可以提高下载速度达5倍的工具&#xff0c;同时具有恢复、调度和组织下载的功能。如果由于网络问题或意外的电源中断&#xff0c;程序将恢复未完成的下载。 IDM 还具有一个完全功能的站点…

第十四课 Vue中的HTML及文本渲染

Vue中的HTML及文本渲染 HTML渲染 v-html指令可以在DOM中渲染新的子HTML DOM&#xff0c;Vue官方认为HTML渲染是不安全的&#xff0c;并不建议直接做HTML插入操作。 <div id"app"><div v-html"vals"></div></div><script>n…