这是大冰块2021年第3篇原创文章,和大冰块一起在前端领域努力吧!!!


写在前面

不知为什么,感觉2020年面试过程中算法题突然流行了起来,不论你是前端后端还是架构师,面试前都得先来两道算法题热热身。

如果你很干脆的回答不会,hr小姐姐就会吃惊地问你:什么?身为一个前端程序员竟然不会算法??? 语气口吻就好比你的亲戚问你:不会吧不会吧!身为一个程序员不会修电脑??? 让你心跳加速脸红娇喘羞愧难当…

为了避免这种尴尬的情况出现,今天趁着领导不在阳光正好,我们一起来摸一条某大厂中等算法题的大鱼试试看,想看《海王的鱼塘》可以直接跳到尾部挑战一下,不过大冰块建议先从《聪明的销售》看起~


《聪明的销售》

销售主管的任务是出售一系列的物品,其中每个物品都有一个编号。
由于出售具有相同编号的商品会更容易,所以销售主管决定删除一些物品。
现在她知道她最多能删除多少物品,她想知道最终袋子里最少可以包含多少种不同编号的物品。
例如,最开始她有n = 6 个物品,编号为:ids = [1,1,1,2,2,3],她最多可以删除 n = 2 个物品。
如果删除两个物品 1,则剩下的物品 ids = [1,2,2,3],此时她拥有三种不同编号的物品。
如果删除两个物品 2,则剩下的物品 ids = [1,1,1,3],此时她拥有两种不同编号的物品。
如果删除物品 2 和物品 3 各 1个,则剩下的物品 ids = [1,1,1,2],此时她拥有两种不同编号的物品。
我们发现,物品最多可以剩下两种不同的编号,所以你的程序要返回 2

ids 的大小不超过 10^5
1 ≤ ids[i] ≤ 1000000
1 ≤ m ≤ 100000

样例:

输入:
[1,1,1,2,2,3]
2
输出:
2

在这里我要吐槽一句:出题人的语文学的极其差不好,在座的各位没意见吧?

实不相瞒,我看了三遍题目,终于看明白了出题人的意思,不就是数组中删掉n个元素,要求剩余的元素中,相同的元素越多越好嘛!

看明白了题目意思,就已经成功了一半。

算法题的难度50%在于题目读不懂,另50%在于题目读不懂不想做下去。 ——《大冰块语录》

既然已经成功了一半,那么趁热打铁,理一下思路吧!

如果想要删掉n个元素,剩余的元素中,相同的元素越多越好,那么:删掉的元素出现的次数肯定是越少越好。

所以这道题其实是求出每个元素出现的次数,只要求出每个元素出现的次数,答案就近在咫尺唾手可得呼之欲出了(大冰块的语文是不是比出题人要好?)。

就这???我微微一下,劈里啪啦敲出如下demo:

let arr = ['苹果','苹果','苹果','香蕉','香蕉','橘子','橘子','橘子','草莓','火龙果','火龙果']
let obj = {}
arr.forEach( item => obj.hasOwnProperty(item) ? obj[item]+=1 : obj[item] = 1 )
console.log(obj)  // 控制台输出:{苹果: 3, 香蕉: 2, 橘子: 3, 草莓: 1, 火龙果: 2}

如果要删掉5个,就从数量最少的水果删,删够5个即可,我一眼就看出来草莓1+火龙果2+香蕉2刚好等于5,删掉它们即可。

可是程序并不知道,所以我们应该先根据水果数量对obj进行排序,才能顺利的从少到多依次删除对应水果。

可是object对象真的能排序吗?我知道js里的object对象存在自动排序机制,但是我没有对object对象做过排序,所以本文暂时不做讨论object对象属性排序的问题。保险起见,我们采用人人都会的数组排序方式来解决。

把代码重构如下:

let arr = ['苹果','苹果','苹果','香蕉','香蕉','橘子','橘子','橘子','草莓','火龙果','火龙果']
let resultArr = []
arr.forEach( item => {let obj = {name: item, num: 1}let i = resultArr.findIndex(element => element.name == item)i !== -1 ? resultArr[i].num+=1 : resultArr.push(obj)
})
resultArr.sort((a,b)=>a.num-b.num);
console.log(resultArr)
// 控制台输出:[{name: "草莓", num: 1},{name: "香蕉", num: 2},{name: "火龙果", num: 2},{name: "苹果", num: 3},{name: "橘子", num: 3}]
Object.keys(obj).length

排序完成,那么从num最小的元素开始删除吧!

如果需要删除5个,则声明一个变量sum赋值为0,从第一个元素开始,把元素的num累加给sum,这样对比 sum是否大于5即可,如果大于5则不能删除,直接结束。如果小于5,则累加下一个元素的num,直到大于5。

代码重构如下

let arr = ['苹果','苹果','苹果','香蕉','香蕉','橘子','橘子','橘子','草莓','火龙果','火龙果']
let resultArr = []
arr.forEach( item => {let obj = {name: item, num: 1}let i = resultArr.findIndex(element => element.name == item)i !== -1 ? resultArr[i].num+=1 : resultArr.push(obj)
})
resultArr.sort((a,b)=>a.num-b.num);
let sum = 0
resultArr.map((item,index)=>{sum += item.numsum > 5 ? '' : delete resultArr[index]
})
console.log(resultArr)
// 控制台输出:[empty × 3,{name: "苹果", num: 3},{name: "橘子", num: 3}]

虽然map()方法看起来代码精简了不少,但是从如上代码运行角度来说,map()不能终止,在多个元素的情况下效率并没有for循环高,所以我们把代码优化如下:

let arr = ['苹果','苹果','苹果','香蕉','香蕉','橘子','橘子','橘子','草莓','火龙果','火龙果']
let resultArr = []
arr.forEach( item => {let obj = {name: item, num: 1}let i = resultArr.findIndex(element => element.name == item)i !== -1 ? resultArr[i].num+=1 : resultArr.push(obj)
})
resultArr.sort((a,b)=>a.num-b.num);
let sum = 0
for (let index = 0; index < resultArr.length; index++) {sum += resultArr[index].num// 三元运算符中不能使用return和break,因为三元运算符中要写表达式。所以暂时写if判断吧~if(sum > 5){ break}else{resultArr.splice(index,1)index-- // splice()删除元素后,会改变原数组length,所以要index--}
}
console.log(resultArr)
// 控制台输出:[{name: "苹果", num: 3},{name: "橘子", num: 3}]

看起来好像满足了题目的要求,这也没什么难度嘛~下面来封装一下试试看吧:

const smartSale = (array=[],number=0)=>{let resultArr = []array.forEach( item => {let obj = {name: item, num: 1}let i = resultArr.findIndex(element => element.name == item)i !== -1 ? resultArr[i].num+=1 : resultArr.push(obj)})resultArr.sort((a,b)=>a.num-b.num);let sum = 0for (let index = 0; index < resultArr.length; index++) {sum += resultArr[index].numif(sum > number){ break  // 三元运算符中不能使用return和break,因为三元运算符中要写表达式。所以暂时写if判断吧~}else{resultArr.splice(index,1)index--  // splice()删除元素后,会改变原数组length,所以要index--}}return resultArr.length
}
let arr = ['苹果','苹果','苹果','香蕉','香蕉','橘子','橘子','橘子','草莓','火龙果','火龙果']
smartSale(arr,3)
// 控制台输出:3

测试完美运行!那么考虑一下题目下面的限定条件吧:

ids 的大小不超过 10^5
1 ≤ ids[i] ≤ 1000000
1 ≤ m ≤ 100000

即传入的数组length : 1 ≤ array.length ≤ 1000000,传入的number : 1 ≤ number ≤ 100000

const smartSale = (array=[],number=0)=>{if (array.length < 1 || array.length > 1000000) throw new Error("数组的长度范围限制为1-1000000")if (number < 1 || number > 100000) throw new Error("要删除的数量范围限制为1-100000")let resultArr = []array.forEach( item => {let obj = {name: item, num: 1}let i = resultArr.findIndex(element => element.name == item)i !== -1 ? resultArr[i].num+=1 : resultArr.push(obj)})resultArr.sort((a,b)=>a.num-b.num);let sum = 0for (let index = 0; index < resultArr.length; index++) {sum += resultArr[index].numif(sum > number){ break  // 三元运算符中不能使用return和break,因为三元运算符中要写表达式。所以暂时写if判断吧~}else{resultArr.splice(index,1)index--  // splice()删除元素后,会改变原数组length,所以要index--}}return resultArr.length
}

根据这道算法题的思路,我也编了一道算法题供诸君思考:

《海王的鱼塘》

海王的鱼塘里有n条不同的鱼,但是海王的精力和鱼塘面积有限,只能满足其中m条鱼的需求。海王决定根据每条鱼的送给自己的礼物数量,以及这条鱼的外貌情况,衡量优质鱼的价值,然后决定是否放生这条鱼。

海王衡量优质鱼的价值=礼物数量 * 5 + 外貌 * 50

相同情况下,海王会优先放生外貌分最低的鱼。

目前每个海王鱼塘里都有50 — 1500条鱼,同时每个海王的的精力和鱼塘面积可容纳鱼的数量不同,范围是10—1000。鱼送的礼物数量随机从10 — 50不等,外貌为随机80 — 100分不等。

海王该怎么放生才能保证自己的鱼塘是满的,同时都是优质鱼?

掏出你的大脑袋,开动你的脑筋吧~ 把你的答案码在评论区,供各位海王参考一下~

写在后面

原创不易,如有错误,欢迎指出。

如果有帮助到你,请给大冰块来个三连(点赞收藏评论)吧~

《JS玩算法系列》海王的鱼塘相关推荐

  1. 【Flocking算法】海王的鱼塘是怎样炼成的

    目录 一.引言 二.发展 三.鱼群 1.组件 2.生成鱼群 3.鱼群运动 四.聚合 五.速度匹配 六.捕食 七.分离 1.躲避

  2. 2021双非计算机保研推免经验分享——海王养成系列(一)

    作为一名不起眼的本科双非的计算机专业本科生,有幸在卷如梵高星空的保研大军中抓住机遇,成功上岸~~客观的讲,在计算机专业保研大军里,我的个人背景不算特别出众,跟那些清北中科院的巨佬真没法比,七分努力三分 ...

  3. (java)玩转算法系列-数据结构精讲[学习笔记](一)不要小瞧数组

    前言: 课程:玩转算法系列–数据结构精讲 更适合0算法基础入门到进阶(java版) 此处是个人学习笔记,用作回顾用途 不要小瞧数组 1.使用java中的数组 Main.java: public cla ...

  4. java爬虫系列第二讲-爬取最新动作电影《海王》迅雷下载地址

    为什么80%的码农都做不了架构师?>>>    1. 目标 使用webmagic爬取动作电影列表信息 爬取电影**<海王>**详细信息[电影名称.电影迅雷下载地址列表] ...

  5. 匈牙利算法——海王们的渣男渣女行为

    二分图定义 二分图又称作二部图,是图论中的一种特殊模型. 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不 ...

  6. 我看Next.js:一个更现代的海王

    Next.js是一个用于生产环境的React 应用框架(官方介绍:The React Framework for Production),使用它可以快速上手开发 React 应用( enables y ...

  7. kafka实战最佳经验,阿里又现海王!某程序员同时约两个女生十一出游

    "瓜王"阿里名不虚传,隔一段时间就会出来一个瓜,蒋凡事件还余音绕梁,又有人爆出阿里内网惊现海王! 网友们搬来小板凳,面前摆好瓜子花生大西瓜,一脸期待地等着吃瓜,到底什么情况? 有知 ...

  8. freemarker 数组转字符串_TypeScript 实战算法系列(一):实现数组栈与对象栈

    本文由图雀社区认证作者 神奇的程序员 写作而成,图雀社区将连载其TypeScript 实战算法系列,点击阅读原文查看作者的掘金链接,感谢作者的优质输出,让我们的技术世界变得更加美好? 前言 栈作为一种 ...

  9. 海王什么意思,海王是什么意思梗,网络流行词海王介绍

    最近发现一个新的网络词海王,这里的海王可不是电影说的海王,是最近网友新发明的网络新词,我们一起来看一下吧. 网络词海王渣男 海王其实就是和多人有暧昧关系,经常以广撒网多捕鱼的形式来撩妹的渣男,大面积撒 ...

最新文章

  1. 算法工程师当前选哪个方向好?
  2. MYSQL千万级数据量的优化方法积累
  3. 教你如何追缴中国移动恶意扣费:lol :lol
  4. jQuery 在 IE 上 clone checkbox 的問題。
  5. 斑马线分析_中设设计集团:聚焦智慧交通 助力城市发展|集团设计和实施的“智慧斑马线”惊艳亮相南京市江北新区...
  6. ITK:与矢量型图像应用GradientRecursiveGaussianImageFilter
  7. 《明日方舟》的塔防元素:是鸡肋还是精髓?
  8. 20佳带给你灵感的优秀个人博客设计案例
  9. Elasticsearch 安装配置 外网访问 及 后台启动
  10. batch spring 重复执行_重复的Spring Batch作业实例
  11. 如何将dmp文件里的某张表导入oracle数据库
  12. 安装nginx并搭建nginx图片服务器
  13. iOS 自定义UISlider
  14. 一些shell脚本,sed替换
  15. spring ORM管理
  16. 软件测试计划的主要内容
  17. 在Linux操作系统中使用手写板(转)
  18. .bat文件和脚本文件
  19. 蚂蚁迷宫—有限状态机设计(ANT MAZE)
  20. CSS 中z-index全解析(摘自阿里西西)

热门文章

  1. ElasticSearch简介及ElasticSearch部署、原理和使用介绍
  2. 聚焦 Android 11 : 隐私和安全
  3. 如何判断一个结构体的大小
  4. Hdu 5445 Food Problem 多重背包
  5. C语言指针难吗?纸老虎而已,纯干货讲解
  6. 宝贝,来,满足你,二哥告诉你学 Java 应该买什么书?
  7. 冷读术:瞬间抓住人心和操控人心的沟通技巧
  8. MyEclipse2015Stable2.0安装破解、遇到的问题和简单使用
  9. 使用Easyexcel动态生成excel
  10. Linux学习19-gitlab配置邮箱postfix(新用户激活邮件)