【前端面试】随机、结构赋值、博弈题
解构赋值(Destructuring Assignment)是 JavaScript ES6 引入的一项非常有用的特性,它允许我们快速地从数组或对象中提取值,并将它们赋给变量。这种方式使得代码更加简洁、易读,并且能够减少重复的访问和赋值操作。
1. 数组解构赋值
通过解构赋值,我们可以直接从数组中提取值并赋给变量。例如:
// 基本的数组解构赋值
const arr = [1, 2, 3];
const [a, b, c] = arr;console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
说明:
a、b和c分别从数组arr中提取了值。- 解构赋值顺序是按数组的索引顺序进行的。
跳过元素:
如果我们只需要数组中的部分元素,可以跳过不需要的元素:
const arr = [1, 2, 3];
const [a, , c] = arr; // 跳过第二个元素console.log(a); // 1
console.log(c); // 3
默认值:
解构时,如果数组的某个位置没有值,可以为该变量提供默认值:
const arr = [1];
const [a, b = 2] = arr;console.log(a); // 1
console.log(b); // 2
2. 对象解构赋值
对象解构赋值允许我们从对象中提取特定的属性并赋给变量。
const person = { name: 'Alice', age: 25 };
const { name, age } = person;console.log(name); // Alice
console.log(age); // 25
说明:
- 变量名需要与对象属性的名称相同。如果变量名与对象属性名不同,可以通过
:来重命名:
const person = { name: 'Alice', age: 25 };
const { name: personName, age: personAge } = person;console.log(personName); // Alice
console.log(personAge); // 25
默认值:
如果某个属性在对象中不存在,可以为该属性设置默认值:
const person = { name: 'Alice' };
const { name, age = 30 } = person;console.log(name); // Alice
console.log(age); // 30
嵌套解构:
你还可以对对象进行嵌套解构,从嵌套的对象中提取值:
const person = { name: 'Alice', address: { city: 'Wonderland', zip: '12345' } };
const { name, address: { city, zip } } = person;console.log(name); // Alice
console.log(city); // Wonderland
console.log(zip); // 12345
3. 解构赋值与剩余操作符
如果你需要从数组或对象中提取出剩余的元素或属性,可以使用剩余操作符 ...。
数组的剩余解构:
const arr = [1, 2, 3, 4, 5];
const [first, second, ...rest] = arr;console.log(first); // 1
console.log(second); // 2
console.log(rest); // [3, 4, 5]
对象的剩余解构:
const person = { name: 'Alice', age: 25, city: 'Wonderland' };
const { name, ...otherInfo } = person;console.log(name); // Alice
console.log(otherInfo); // { age: 25, city: 'Wonderland' }
4. 函数参数中的解构赋值
解构赋值可以与函数参数结合使用,直接从传入的对象或数组中提取值:
数组解构作为函数参数:
function sum([a, b]) {return a + b;
}console.log(sum([3, 5])); // 8
对象解构作为函数参数:
function greet({ name, age }) {console.log(`Hello, ${name}! You are ${age} years old.`);
}greet({ name: 'Alice', age: 25 }); // Hello, Alice! You are 25 years old.
带默认值的函数参数解构:
function greet({ name = 'Guest', age = 18 } = {}) {console.log(`Hello, ${name}! You are ${age} years old.`);
}greet({ name: 'Alice' }); // Hello, Alice! You are 18 years old.
greet(); // Hello, Guest! You are 18 years old.
这段代码 [arr[i], arr[j]] = [arr[j], arr[i]]; 是数组元素交换的语法,属于一种解构赋值的用法。它通常用于交换数组中两个元素的位置。
解释
-
解构赋值:这是 JavaScript ES6 中引入的一个特性,允许我们使用数组或对象的结构来进行赋值。
-
数组元素交换:在没有解构赋值的语法时,我们通常使用临时变量来交换两个元素,比如:
let temp = arr[i]; arr[i] = arr[j]; arr[j] = temp;而使用解构赋值的方式可以减少临时变量的使用,使代码更简洁。通过这种方式,
arr[i]和arr[j]两个元素的值会交换。
使用场景
这个代码片段在Fisher-Yates 洗牌算法中非常常见,它用于随机打乱数组中的元素顺序。通过不断交换数组中的元素,从最后一个元素开始,逐步将每个元素与之前的元素交换,确保每个元素都有相等的概率出现在数组的任何位置。
示例:Fisher-Yates 洗牌算法实现
function shuffleArray(arr) {for (let i = arr.length - 1; i > 0; i--) {// 随机选择一个索引 j,其中 0 <= j <= iconst j = Math.floor(Math.random() * (i + 1));// 交换 arr[i] 和 arr[j][arr[i], arr[j]] = [arr[j], arr[i]];}
}const arr = [1, 2, 3, 4, 5];
shuffleArray(arr);
console.log(arr); // 打乱顺序后的数组
这段代码的关键点:
- Fisher-Yates 洗牌算法:这个算法的核心思想是从数组的最后一个元素开始,随机选择一个元素并与当前元素交换位置,直到整个数组都经过处理。这确保了数组中每个元素出现的顺序是随机的。
- 解构赋值:通过
[arr[i], arr[j]] = [arr[j], arr[i]];来简洁地交换元素,无需使用额外的临时变量。
以下是将上述题目改成先输后赢情况的题目及对应答案,也就是目标变为让对方拿到最后一颗石子、最后一枚硬币等情况来取得胜利,供你参考:
💡题目 1:取石子游戏(先输后赢版)
- 有一堆石子,共 100 颗。甲、乙两人轮流从中取石子,每次最少取 1 颗,最多取 5 颗。取到最后一颗石子的人输。假设甲先取,问甲有没有必胜策略?如果有,甲第一步应该取几颗石子?
答案:
甲有必胜策略。因为要让乙取到最后一颗石子(即甲要避免取到最后一颗),那就需要保证每轮两人共取 6 颗石子(1 + 5 = 6,2 + 4 = 6,3 + 3 = 6 等情况),使得最后剩下 1 颗留给乙。100÷6 = 16……4,甲先取 4 颗石子,之后乙取 n 颗(1≤n≤5),甲就取 6 - n 颗,这样经过 16 轮后,就会剩下 1 颗石子留给乙去取,乙取到最后这颗石子,甲获胜。
💡题目 2:硬币游戏(先输后赢版)
- 桌上有 20 枚硬币,A、B 两人轮流拿硬币,每次可以拿 1 到 3 枚。谁拿到最后一枚硬币谁输。假设 A 先拿,A 有没有必胜策略?
答案:
A 有必胜策略。要保证 B 拿到最后一枚硬币,就要使得最后一轮留给 B 时只剩下 1 枚硬币。因为每次两人能取 1 到 3 枚,若想控制每轮取的数量,让两人一轮共取 4 枚硬币(1 + 3 = 4,2 + 2 = 4,3 + 1 = 4)是可行的。20÷4 = 5,没有余数,A 先拿 1 枚硬币,之后 B 拿 n 枚(1≤n≤3),A 就拿 4 - n 枚,这样经过 4 轮后,会剩下 1 枚硬币留给 B 去拿,A 获胜。
💡题目 3:划分数字(先输后赢版)
- 给定数字 10,A、B 两人轮流进行操作。操作可以是将当前数字减去 1 或者减去 2。谁先将数字减到 0 谁输。假设 A 先操作,A 有没有必胜策略?
答案:
A 有必胜策略。A 要避免自己把数字减到 0,那就需要让 B 去减到 0,所以 A 第一次要将 10 减去 2 变为 8。之后 B 操作,如果 B 减 1,A 就减 2;如果 B 减 2,A 就减 1,保证每轮两人共减去 3。因为 8÷3 = 2……2,经过 2 轮后,数字变为 2,此时不管 B 减 1 还是减 2,A 都能进行相应操作使得最后 B 把数字减到 0,A 获胜。
💡题目 4:报数游戏(先输后赢版)
- A、B 两人轮流报数,从 1 开始报,每次可以报 1 个或 2 个连续的数。谁报到 20 谁输。假设 A 先报,A 有没有必胜策略?
答案:
A 有必胜策略。A 要避免报到 20,要让 B 报到 20。A 先报 1 个数,报 1。然后 B 报数,如果 B 报 1 个数,A 就报 2 个数;如果 B 报 2 个数,A 就报 1 个数,保证每轮两人共报 3 个数。因为 (20 - 1)÷3 = 6……1,经过 6 轮后,正好轮到 B 报数,此时 B 只能报 20,B 输,A 获胜。
💡题目 5:火柴游戏(先输后赢版)
- 有 15 根火柴,A、B 两人轮流取火柴,每次可以取 1 根、2 根或 3 根。取到最后一根火柴的人输。假设 A 先取,A 有没有必胜策略?
答案:
A 有必胜策略。A 要让 B 取到最后一根火柴,也就是要保证最后剩下 1 根留给 B。因为每次两人取 1 到 3 根,控制每轮两人共取 4 根火柴(1 + 3 = 4,2 + 2 = 4,3 + 1 = 4)就行。15÷4 = 3……3,A 先取 3 根火柴,剩下 12 根,然后 B 取 n 根(1≤n≤3),A 就取 4 - n 根,这样经过 3 轮后,就会剩下 1 根火柴留给 B 去取,A 获胜。
相关文章:
【前端面试】随机、结构赋值、博弈题
解构赋值(Destructuring Assignment)是 JavaScript ES6 引入的一项非常有用的特性,它允许我们快速地从数组或对象中提取值,并将它们赋给变量。这种方式使得代码更加简洁、易读,并且能够减少重复的访问和赋值操作。 1.…...
Volta——开箱即用的Node.js 版本管理工具
Volta volta 是一个较新的 Node.js 版本管理器,旨在简化 Node.js 和其他工具的安装和管理,在 2019 年出世,仍在积极开发中。Volta 采用了与 nvm 不同的方法:它不是管理 Node.js 的多个版本,而是管理项目及其依赖项。当…...
ubuntu 磁盘空间满,找不到占用文件的目录
解决方法: 检查磁盘空间: 执行 df -h 查看各分区磁盘使用情况。 查找大文件或目录: 执行 du -sh /* 2>/dev/null 查找根目录下的大文件或目录,再逐一进入子目录使用相同命令查找。 清理缓存和临时文件: 清理 /t…...
1. 机器学习基本知识(5)——练习题(参考答案)
20.🔗本章代码笔记📓链接(需要🪜):(01_the_machine_learning_landscape.ipynb - Colab (google.com)) 如果你不想通过上面的官方网址下载本章的笔记,还可以在本篇博文的…...
spark-sql 备忘录
wordcount sc.textFile("../data/data.txt").flatMap(_.split(" ")).map((_,1)).reduceByKey(__).collect 读取json 文件 并通过sql 执行 join 查询 public static void main(String[] args) {SparkSession session SparkSession.builder().master(&qu…...
基于softmax回归的多分类
基于softmax回归的多分类任务是机器学习领域中的一种常见应用。softmax回归,又称多项逻辑回归或多类逻辑回归,是逻辑回归在多分类问题上的推广。以下是对基于softmax回归的多分类任务的详细解释: 一、softmax回归的原理 softmax回归的核心思想是通过softmax函数将输入数据…...
bs4基本运用
1. bs4基本使用 1.1. 简介 bs4的全称为 BeautifulSoup。和lxml一样,是一个html的解析器,主要功能也是解析数据和提取数据 。 本模块作为了解模块,实际开发中很少用这个模块去解析数据,大家可能会想为什么这个模块会逐渐被淘汰&…...
MySQL 时区参数 time_zone 详解
文章目录 前言1. 时区参数影响2. 如何设置3. 字段类型选择 前言 MySQL 时区参数 time_zone 有什么用?修改它有什么影响?如何设置该参数,本篇文章会详细介绍。 1. 时区参数影响 time_zone 参数影响着 MySQL 系统函数还有字段的 DEFAULT CUR…...
Redis - 消息队列 Stream
一、概述 消息队列 定义 消息队列模型:一种分布式系统中的消息传递方案,由消息队列、生产者和消费者组成消息队列:负责存储和管理消息的中间件,也称为消息代理(Message Broker)生产者:负责 产…...
Docker:国内加速源
阿里云docker加速云: sudo tee /etc/docker/daemon.json <<EOF { “registry-mirrors”: [“https://euf11uji.mirror.aliyuncs.com”] } EOFhttps://docker.mozhu.dev/ sudo tee /etc/docker/daemon.json <<EOF {"registry-mirrors": [&qu…...
Android Studio更改项目使用的JDK
一、吐槽 过去,在安卓项目中配置JDK和Gradle的过程非常直观,只需要进入Android Studio的File菜单中的Project Structure即可进行设置,十分方便。 原本可以在这修改JDK: 但大家都知道,Android Studio的狗屎性能,再加…...
ubuntu+ros新手笔记(四):gazebo无法加载
以下为ChatGPT 的解决方案,对我来说是可行的!! 我按照第2步操作就解决辣!! 我的提问: 在ubuntu 22.04 和ros2 humble环境下,gazebo加载不了 ChatGPT 回答: 在 Ubuntu 22.04 和 …...
vue季度选择器(antd2.0 版本无此控件,单独写一个)
vue季度选择器 效果显示 效果显示 <template><div><a-popoverplacement"bottom"overlayClassName"season-picker"trigger"click"v-model"showSeason"><template #content><div class"season-picker-b…...
C/C++代码性能优化技巧的书籍及资料
使用C/C开发的场景,大多对代码的执行的速度,实时性有较高的要求,像嵌入式系统的开发,资源还受限。在算力存储空间有限的MCU上写出简洁又高效的代码实际是一种艺术。软件工程师在代码设计上的这种差距,会反映在产品的性…...
通俗易懂的 Nginx 反向代理 配置
通俗易懂的 Nginx 反向代理 配置 首先 root 与 alias 的区别 root 是直接拼接 root location location /i/ {root /data/w3; }当请求 /i/top.gif ,/data/w3/i/top.gif 会被返回。 alias 是用 alias 替换 location location /i/ {alias /data/w3/images/; }当请…...
docker设置容器自动启动
说起开机自动启动应该很多人都遇到过,我们公司做的系统很多的中间件都没有设置开机自动启动然后中间修改问题又设置了一些临时生效的文件,开始的时候大家都不以为意,知道公司陆续有人离职入职管理交接一塌糊涂,项目成了历史遗留问…...
蓝桥杯刷题——day1
蓝桥杯刷题——day1 题目一题干题目解析代码 题目二题干题目解析代码 题目一 题干 给定一个字符串 s ,验证 s 是否是 回文串 ,只考虑字母和数字字符,可以忽略字母的大小写。本题中,将空字符串定义为有效的 回文串 。 题目链接&a…...
Leetcode 面试150题 399.除法求值
系列博客目录 文章目录 系列博客目录题目思路代码 题目 链接 思路 广度优先搜索 我们可以将整个问题建模成一张图:给定图中的一些点(点即变量),以及某些边的权值(权值即两个变量的比值),试…...
活动预告 |【Part2】Microsoft 安全在线技术公开课:安全性、合规性和身份基础知识
课程介绍 通过参加“Microsoft 安全在线技术公开课:安全性、合规性和身份基础知识”活动提升你的技能。在本次免费的介绍性活动中,你将获得所需的安全技能和培训,以创造影响力并利用机会推动职业发展。你将了解安全性、合规性和身份的基础知…...
Unity游戏实战
很小的时候在键盘机上玩过一个游戏叫寻秦,最近看有大佬把他的安卓版做出来了,打开封面就是Unity,想自己也尝试一下。...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...
