当前位置: 首页 > news >正文

前端面试经典手写题

1、手写Promise

class Promise2 {state = "pending";callbacks = [];constructor(fn) {fn(this.resolve.bind(this), this.reject.bind(this));}resolve(result) {if (this.state !== "pending") return;this.state = "fullFilled";nextTick(() => {this.callbacks.forEach((handle) => {if (typeof handle[0] === "function") {handle[0].call(undefined, result);}});});}reject(reason) {if (this.state !== "pending") return;this.state = "rejected";nextTick(() => {this.callbacks.forEach((handle) => {if (typeof handle[1] === "function") {handle[1].call(undefined, reason);}});});}then(success, fail) {const handle = [];if (typeof success === "function") {handle[0] = success;}if (typeof fail === "function") {handle[1] = fail;}this.callbacks.push(handle);return this;}
}function nextTick(fn) {if (process !== undefined && typeof process.nextTick === "function") {return process.nextTick(fn);} else {var counter = 1;const observer = new MutationObserver(fn);var textNode = document.createTextNode(String(counter));observer.observe(textNode, {// 踪字符更改characterData: true,});counter += 1;textNode.data = String(counter);}
}// 方法返回一个Promise实例,此实例在 iterable 参数内所有的promise 都完成(resolved)时回调完成(resolve);
// 如果参数中 promise有一个失败(rejected),此实例回调失败(reject),失败的原因是第一个失败promise的结果。Promise2.all = function(arrP) {let list = [];len = 0;return new Promise2((resolve, reject) => {for (let i = 0; i < arrP.length; i++) {arrP[i].then((val) => {list[i] = val;len++;len === arrP.length && resolve(list);},(err) => {reject(error);});}});
};Promise.prototype.myAll = (iterator) => {return new Promise((resolve, reject) => {const ret = []let count = 0Array.from(iterator).forEach((item, index) => {Promise.resolve(item).then(data => {ret[index] = datacount++if(count === iterator.length) {resolve(ret)}}, reject)})})
}// 方法返回一个Promise实例,一旦迭代器中的某个 promise 完成(resolved)或失败(rejected),返回的 promise 就会 resolve 或 rejectPromise2.race = function(arrP) {let flag1 = false;let flag2 = false;return new Promise2((resolve, reject) => {for (let i = 0; i < arrP.length; i++) {arrP[i].then((data) => {!flag2 && !flag1 && resolve(data);flag1 = true;return;},(error) => {!flag2 && !flag1 && reject(error);flag2 = true;return;});}});
};new Promise2((resolve, reject) => {let [val, time] = [Math.random(), Math.random() * 1000];setTimeout(() => {val > 0.2 ? resolve(val) : reject(val);}, time);
}).then((val) => console.log("promise 测试:", val),(err) => console.error("promise 测试:" + err)
);const getPList = () => {let arrP = [];for (let i = 0; i < 10; i++) {arrP[i] = new Promise2((resolve, reject) => {let [v, t] = [Math.random(), Math.random() * 1000];setTimeout(() => {v > 0.1 ? resolve(v) : reject(v);}, t);});}return arrP;
};Promise2.all(getPList()).then((data) => console.log("promise.all 测试:", data),(err) => console.error("promise.all 测试:" + err)
);Promise2.race(getPList()).then((data) => console.log("promise.race 测试:", data),(err) => console.error("promise.race 测试:" + err)
);

2、手写new

// 新生成一个对象
// 将构造函数的作用域赋值给新对象(即绑定新对象的 this)
// 执行构造函数中的代码(即为这个新对象添加属性)
// 返回新对象function myNew() {// 创建对象let obj = new Object();// 取第一个参数let fn = Array.prototype.shift.call(arguments);//obj.__proto__指向fn.prototypeobj.__proto__ = fn.prototype;// 执行结果let result = fn.apply(obj, arguments);return typeof result === "object" ? result : obj;
}function Person(name) {this.name = name;
}// var p1 = myNew(Person, "xx");
// console.log(p1.name);function P(name) {this.name = name;return 1;
}var p2 = myNew(P, "xm");
console.log(p2);

3、手写instanceof

实现思路:

1、leftVaule代表实例对象

2.rightVaule代表构造函数

3.利用typeof方法,判断输入的leftVaule是否为对象,如果不是,则返回false

4.遍历leftVaule的原型链,直到找到rightVaule的prototype,如果查找失败的话,返回false,反之,返回true

function myInstanceof(leftValue, rightValue) {if (typeof leftValue !== "object" || leftValue === null) return false;let leftProto = leftValue.__proto__;let rightProto = rightValue.prototype;while (true) {if (leftProto === null) {return false;}if (leftProto === rightProto) {return true;}leftProto = leftProto.__proto__;}
}myInstanceof([], Array);

4、并发请求限制

限制请求数,一个请求完成替换下一个请求

第一次分段

第二次添加下一个

控制startIndex与endIndex

终止态:返回值已等于请求数,执行cb

// class LimitFetch {}// 
// 第一次分段
// 第二次添加下一个
// 控制startIndex与endIndex
// 终止态:返回值已等于请求数,执行cbclass LimitFetch {constructor(opts) {this.requestList = opts.requestList;this.limit = opts.limit;this.cb = opts.cb;this.startIndex = 0;this.result = {};this.resultCount = 0;this.batchRequest();}batchRequest(num) {const endIndex = this.startIndex + (num || this.limit);const len = this.requestList.length;for (let i = this.startIndex; i < endIndex; i++) {this.startIndex++;if (!this.requestList[i]) return;this.requestList[i]().then((res) => {this.result[i] = res;this.resultCount++;if (this.resultCount === len) {this.cb(this.result);}if (i < len - 1) {this.batchRequest(1);}});}}
}// 函数写法
function limitFetch(requestList, limit, cb) {let startIndex = 0;let results = {};let resultCount = 0;function batchRequest(num) {const endIndex = startIndex + (num || limit);for (let i = startIndex, len = requestList.length; i < endIndex; i++) {if (!requestList[i]) continue;startIndex++;requestList[i]().then((res) => {resultCount++;results[i] = res;if (i < len - 1) {batchRequest(1);}if (resultCount === len) {cb(results);}});}}batchRequest();
}let requestList = [];function fn(time) {return function () {// console.log(time);return new Promise((resolve, reject) => {setTimeout(() => {console.log(time);resolve(time);}, time);});};
}for (let i = 0; i < 5; i++) {requestList.push(fn(1 * 1000));
}
// limitFetch(requestList, 3, (res) => {
//   console.log(res);
// });new LimitFetch({requestList,limit: 3,cb: (res) => {console.log(res);},
});// 限制并发
// 可以新增加
class BtRequest{constructor(opts) {this.limit  = opts.limitthis.isRequest = falsethis.queue = []}add(fn) {this.queue.push(fn)if(!this.isRequest) {this.request()}}request(end) {this.isRequest = trueend = end || this.limitconst requestList = this.queue.splice(0, end)if(!requestList.length) {this.isRequest = false}requestList.forEach(item => {Promise.resolve(item()).then((res) => {console.log(1,res);this.request(1)})})}
}const request = new BtRequest({limit: 1})request.add(() => {console.log(100);// return 500
})
request.add(() => {console.log(200);// return 600})
request.add(() => {console.log(300);// return 700})
request.add(() => {console.log(400);// return 800})

5、手写发布订阅者

使用一个对象作为缓存

on 负责把方法发布到缓存的 EventName 对应的数组

emit 负责遍历触发(订阅) EventName 下的方法数组

off 找方法的索引,并删除

// 使用一个对象作为缓存
// on 负责把方法发布到缓存的 EventName 对应的数组
// emit 负责遍历触发(订阅) EventName 下的方法数组
// off 找方法的索引,并删除function indexOf(a, b) {return a.indexOf(b);
}class EventBus {constructor() {this.cache = {};}on(eventName, fn) {this.cache[eventName] = this.cache[eventName] || [];this.cache[eventName].push(fn);}off(eventName, fn) {const index = this.cache[eventName].indexOf(fn);if (index !== -1) {this.cache[eventName].splice(index, 1);}}emit(eventName) {this.cache[eventName].forEach((fn) => {fn();});}once(eventName, cb) {const one = (...args) => {cb(...args)this.off(eventName, one)}this.on(eventName,one)}
}

6、手写一个搜索的组件

支持防抖

<template><div>{{a}}<input type='text' @input="onInput()"><p>{{res}}</p></div>
</template>
<script>const fetch = () => Promise.resolve('this is fetch data')
export default{data() {return {a: '1',res: undefined}},methods: {deboundce(fn, time) {let timer;return function() {if(timer) {clearTimeout(timer)}timer = setTimeout(fn, time)}},async fetchData() {console.log(11)// return Promise.resolve(1)this.res = await fetch()},async onInput() {const fn =  this.deboundce(this.fetchData, 1000)fn()// console.log(data)}}
}</script>

7、手写Promise.allSettled

Promise.allSettled 只关心所有 promise 是不是都被 settle 了,不管其是 rejected状态的 promise,还是非 rejected状态(即fulfilled)的 promise, 我都可以拿到它的最终状态并对其进行处理

Promise.allSettled 的结果数组中可能包含以下两种格式的数据

{status:"fulfilled", value:result} 对于成功的响应

{status:"rejected", reason:error} 对于 error

const promise1 = Promise.resolve(3)
const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100,'foo'))
const promise3 = [promise1, promise2]Promise.myAllSettled = function(promises) {return new Promise(resolve => {const data = [], len = promises.lengthlet count = len;for(let i = 0; i < len; i++) {const promise = promises[i]promise.then(res => {data[i] = {status: 'fulfilled', value: res}},error => {data[i] = {status: 'rejected', value: error}}).finally(() => {if(!--count) {resolve(data)}})}})
}Promise.myAllSettled(promise3)
.then(results => results.forEach(result => console.log(result.status)))

8、手写bind

要支持能做为构造函数

思路:Function 的原型对象上增加一个函数,返回值是一个函数,函数的fn.prototype.constructor 指向函数和函数的 prototype 指向 Object.create(this.prototype)

const obj = {
name: 'xiao'
}function func(first,last){
console.log(first + this.name, last);}Function.prototype.myBind = function(context,...args ){
console.log(context);
context.fn = this;const fn = function() {
context.fn.apply(context,[...args])
}fn.prototype = Object.create(this.prototype)
fn.prototype.constructor = this;return fn
}
const fn1 = func.myBind(obj,'li', 'ming')
fn1()const fn2 = new fn1()console.log(fn2);

9、手写一个防抖

// 防抖 // 不管事件触发频率多高,一定在事件触发n秒后才执行,如果你在一个事件触发的 n 秒内又触发了这个事件,就以新的事件的时间为准,n秒后才执行,总之,触发完事件 n 秒内不再触发事件,n秒后再执行。 // 关联记忆: 函数防抖就是法师发技能的时候要读条,技能读条没完再按技能就会重新读条。

function debounce(fn, wait, immediate) {let timeout;return function () {let context = this;let args = arguments;if (timeout) clearTimeout(timeout);if (immediate) {var callNow = !timeout;timeout = setTimeout(() => {timeout = null;}, wait);if (callNow) fn.apply(context, args);} else {timeout = setTimeout(function () {fn.apply(context, args);}, wait);}};
}

10、手写一个 深拷贝

// 基础版本
function clone2=(target, map = new WeakMap()) {if (typeof target === 'object') {let cloneTarget = Array.isArray(target) ? [] : {};if(map.get(target)) return map.get(target)map.set(target, cloneTarget)for (const key in target) {cloneTarget[key] = clone(target[key], map);}return cloneTarget;} else {return target;}
};// 资深版本
function isObject (target) {const type = typeof targetreturn target !== null && (type === 'object' || type === 'function')
}function getType(target) {return Object.prototype.toString.call(target)
}function getInit(target) {const Ctor = target.constructorreturn new Ctor()
}
const mapTag = '[object Map]';
const setTag = '[object Set]';
const arrayTag = '[object Array]';
const objectTag = '[object Object]';
const argsTag = '[object Arguments]'const boolTag = '[object Boolean]';
const dateTag = '[object Date]';
const errorTag = '[object Error]';
const numberTag = '[object Number]';
const regexpTag = '[object RegExp]';
const stringTag = '[object String]';
const symbolTag = '[object Symbol]';
const funcTag = '[object Function]'function forEach(array, iteratee) {let index = -1;const length = array.length;while (++index < length) {iteratee(array[index], index);}return array;
}const deepTag = [mapTag, setTag, arrayTag, objectTag, argsTag]//TODO: Reg 的拷贝方法
function cloneReg(targe) {const reFlags = /\w*$/;const result = new targe.constructor(targe.source, reFlags.exec(targe));result.lastIndex = targe.lastIndex;return result;
}//TODO:  Symbol 的拷贝方法
function cloneSymbol(targe) {return Object(Symbol.prototype.valueOf.call(targe));
}//TODO: cloneFunction
function cloneFunction(func) {const bodyReg = /(?<={)(.|\n)+(?=})/m;const paramReg = /(?<=().+(?=)\s+{)/;const funcString = func.toString();if (func.prototype) {console.log('普通函数');const param = paramReg.exec(funcString);const body = bodyReg.exec(funcString);if (body) {console.log('匹配到函数体:', body[0]);if (param) {const paramArr = param[0].split(',');console.log('匹配到参数:', paramArr);return new Function(...paramArr, body[0]);} else {return new Function(body[0]);}} else {return null;}} else {return eval(funcString);}
}function cloneOtherType(targe, type) {//TODO: constructorconst Ctor = targe.constructor;switch (type) {case boolTag:case numberTag:case stringTag:case errorTag:case dateTag:return new Ctor(targe);case regexpTag:return cloneReg(targe);case symbolTag:return cloneSymbol(targe);case funcTag:return cloneFunction(targe)default:return null;}
}function clone(target, map = new WeakMap()) {if(!isObject(target)) return targetconst type = getType(target)let cloneTargetif(deepTag.includes(type)) {cloneTarget = getInit(target, type)}else {return cloneOtherType(target, type)}if (map.get(target)) {return map.get(target);}map.set(target, cloneTarget);if(type === setTag) {target.forEach(val => {cloneTarget.add(clone(val, map))})return cloneTarget}// 克隆mapif (type === mapTag) {target.forEach((value, key) => {cloneTarget.set(key, clone(value,map));});return cloneTarget;}// 克隆对象和数组const keys = type === arrayTag ? undefined : Object.keys(target);forEach(keys || target, (value, key) => {if (keys) {key = value;}cloneTarget[key] = clone(target[key], map);});return cloneTarget;}

相关文章:

前端面试经典手写题

1、手写Promise class Promise2 {state "pending";callbacks [];constructor(fn) {fn(this.resolve.bind(this), this.reject.bind(this));}resolve(result) {if (this.state ! "pending") return;this.state "fullFilled";nextTick(() > …...

Tomcat 部署及优化

Tomcat概述 Tomcat 是 Java 语言开发的&#xff0c;Tomcat 服务器是一个免费的开放源代码的 Web 应用服务器&#xff0c;是 Apache 软件基金会的 Jakarta 项目中的一个核心项目&#xff0c;由 Apache、Sun 和其他一些公司及个人共同开发而成。在中小型系统和并发访问用户不是很…...

Selenium入门详细教程+实例演示

目录 1.Selenium概述 1.1什么是Selenium 1.2Selenium的优势 1.3Selenium WebDriver原理 2.Selenium环境搭建 3.Selenium 简单示例 4.八大元素定位 4.1定位方式 4.2定位方式的用法 5.Selenium API 5.1WebDriver 常用 API 5.2WebElement 常用 API 5.3代码示例 6.元素等待机…...

ATFX汇评:美国7月CPI数据即将揭晓,市场预期将有所反弹

ATFX汇评&#xff1a;今日20:30&#xff0c;美劳工部将公布7月未季调CPI年率&#xff0c;前值为3%&#xff0c;预期值3.3%&#xff1b;同一时间公布7月未季调核心CPI年率&#xff0c;前值为4.8%&#xff0c;预期值持平&#xff1b;至8月5日当周初请失业金人数也将同时发布&…...

23、springboot日志使用入门-- SLF4J+Logback 实现(springboot默认的日志实现),日志打印到控制台及日志输出到指定文件

springboot日志使用入门 ★ 典型的Spring Boot日志依赖&#xff1a; spring-boot-start.jar -- spring-boot-starter-logging.jar (Spring Boot的日志包&#xff09;-- logback&#xff08;core、classic&#xff09;-- log4j-to-slf4j.jar-- jul-to-slf4j.jar就是springboo…...

【uniapp】 软键盘弹出后fixed定位被顶上去问题

问题描述 当手机设计的导航栏为fixed定位上去时&#xff0c;输入框获取焦点就会把顶部自定义的导航栏顶到上面去&#xff0c;如下图所示 解决办法 输入框设置 :adjust-position“false” <input type"text" :adjust-position"false" focus"i…...

HarmonyOS应用开发者基础认证考试题库

此博文为HarmonyOS应用开发者基础认证考试的最后的大考&#xff0c;要求100分取得90分方可获取证书、现将考试的题库进行分享&#xff0c;希望能帮到大家。但是需要注意的是&#xff0c;题库会不定时的进行题目删减&#xff0c;但是大概的内容是不会进行改变的。真心希望这篇博…...

FANUC机器人SRVO-105和SRVO-067故障报警原因分析及处理方法

FANUC机器人SRVO-105和SRVO-067故障报警原因分析及处理方法 如下图所示,公司的一台机器人在正常工作时突然报警SRVO-105门打开或紧急停止,同时还有SRVO-067 OHAL2报警(G:1 A:2),按Reset键无法消除报警, 那么遇到这种情况,首先,我们来看一下报警说明书上的解释: 首先…...

在vue中Antv G2 折线图如何添加点击事件获取折线上点的值

在项目中有个需求是点击折线图的点&#xff0c;获取当前点的信息&#xff0c;其它图形都可以参考相关的API获取到&#xff0c;但area做的折线图怎么都获取不到点击的信息&#xff0c;只能获取全部的信息&#xff0c;最终解决如下&#xff1a; 实现思路 用户的鼠标在折线图上移…...

深度学习中训练、推理和验证分别都是什么意思

在深度学习中&#xff0c;推理&#xff08;Inference&#xff09;、训练&#xff08;Training&#xff09;和验证&#xff08;Validation&#xff09;是三个关键概念&#xff0c;它们分别表示了不同的阶段和任务&#xff1a; 训练&#xff08;Training&#xff09;&#xff1a;…...

C语言规范

C语言规范 1.头文件 若包含了头文件aa.h&#xff0c;则就引入了新的依赖&#xff1a;一旦aa.h被修改&#xff0c;任何直接和间接包含aa.h代码都会被重新编译。如果aa.h又包含了其他头文件如bb.h&#xff0c;那么bb.h的任何改变都将导致所有包含了aa.h的代码被重新编译&#x…...

Express中间件

1.创建最基本的中间件 const express require(express); const send require(send);const app express()const mw function (req, res, next) {console.log(middleware);// 一定要调用next() 把流转关系交给下一个中间件或路由next() }app.listen(80, () > {console.l…...

124. 二叉树中的最大路径和

题目描述 二叉树中的 路径 被定义为一条节点序列&#xff0c;序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点&#xff0c;且不一定经过根节点。 路径和 是路径中各节点值的总和。 给你一个二叉树的根节点 root &…...

管理类联考——逻辑——论证逻辑——汇总篇——真题和典例——分析

分析 分析争论焦点题 199-2010-1-51——分析争论焦点题——论点争论模型 陈先生&#xff1a;未经许可侵入别人的电脑&#xff0c;就好像开偷来的汽车撞伤了人&#xff0c;这些都是犯罪行为。但后者性质更严重&#xff0c;因为它既侵占了有形财产&#xff0c;又造成了人身伤害…...

深度ip转换器:一键更换ip地址方法

很多网友问小编有关深度ip转换器怎么用&#xff1f;最新深度ip转换器手机版app&#xff1f;下面小编整理了深度ip转换器怎么修改ip地址的技巧和诀窍&#xff0c; 让我们来详细的了解一下深度id转换器&#xff0c; 一、深度ip转换器怎么用 1.深度ip转换器怎么用&#xff0c;深度…...

【TypeScript】类型断言-类型的声明和转换(五)

【TypeScript】类型断言-类型的声明和转换&#xff08;五&#xff09; 【TypeScript】类型断言-类型的声明和转换&#xff08;五&#xff09;一、简介二、断言形式2.1 尖括号语法2.2 as形式 三、断言类型3.1 非空断言3.2 肯定断言-肯定化保证赋值3.3 将任何类型断言为any3.4 调…...

行业追踪,2023-08-10

自动复盘 2023-08-10 凡所有相&#xff0c;皆是虚妄。若见诸相非相&#xff0c;即见如来。 k 线图是最好的老师&#xff0c;每天持续发布板块的rps排名&#xff0c;追踪板块&#xff0c;板块来开仓&#xff0c;板块去清仓&#xff0c;丢弃自以为是的想法&#xff0c;板块去留让…...

Nodejs下动态加载文件夹下的文件模块

个人博客 Nodejs下动态加载文件夹下的文件模块 个人博客&#xff0c;求关注&#xff0c;如果有不够清晰的&#xff0c;麻烦指出来&#xff0c;如果有很不正确的&#xff0c;多谢批评。 文章概叙 本文应用的场景是读取指定文件夹下面的所有文件&#xff0c;然后做操作&#…...

C#实现旋转图片验证码

开发环境&#xff1a;C#&#xff0c;VS2019&#xff0c;.NET Core 3.1&#xff0c;ASP.NET Core 1、建立一个验证码控制器 新建两个方法Create和Check&#xff0c;Create用于创建验证码&#xff08;返回1张图片和令牌&#xff09;&#xff0c;Check用于验证&#xff08;验证图…...

MySQL—缓存

目录标题 为什么要有Buffer Poolbuffer pool有多大buffer pool缓存什么 如何管理Buffer Pool如何管理空闲页如何管理脏页如何提高缓存命中率预读失效buffer pool污染 脏页什么时候会被刷入到磁盘 为什么要有Buffer Pool 虽然说MySQL的数据是存储在磁盘中&#xff0c;但是也不能…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

WPF八大法则:告别模态窗口卡顿

⚙️ 核心问题&#xff1a;阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程&#xff0c;导致后续逻辑无法执行&#xff1a; var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题&#xff1a…...

快速排序算法改进:随机快排-荷兰国旗划分详解

随机快速排序-荷兰国旗划分算法详解 一、基础知识回顾1.1 快速排序简介1.2 荷兰国旗问题 二、随机快排 - 荷兰国旗划分原理2.1 随机化枢轴选择2.2 荷兰国旗划分过程2.3 结合随机快排与荷兰国旗划分 三、代码实现3.1 Python实现3.2 Java实现3.3 C实现 四、性能分析4.1 时间复杂度…...