ARTS Week 47

Algorithm 本周的算法题为 1566. 重复至少 K 次且长度为 M 的模式 给你一个正整数数组arr,请你找出一个长度为m且在数组中至少重复k次的模式。 模式是由一个或多个值组成的子数组(连续的子序列),连续重复多次但不重叠。模式由其长度和重复次数定义。 如果数组中存在至少重复k次且长度为m的模式,则返回true,否则返回false。 示例 1: 输入:arr = [1,2,4,4,4,4], m = 1, k = 3 输出:true 解释:模式 (4) 的长度为 1 ,且连续重复 4 次。注意,模式可以重复 k 次或更多次,但不能少于 k 次。 实现代码如下: const containsPattern = function(arr, m, k) { const n = arr.length; if (n < m * k) return false; for (let i = 0; i <= n - m * k; i++) { let valid = true; for (let j = 1; j < k; j++) { for (let pos = 0; pos < m; pos++) { const currentPos = i + j * m + pos; const patternPos = i + pos; if (arr[currentPos] !== arr[patternPos]) { valid = false; break; } } if (!valid) break; } if (valid) return true; } return false; }; 解题思路: 首先检查数组的长度是否至少为 m * k。如果不足,则直接返回 false。 遍历所有可能的模式起始位置 i,确保这些位置可以容纳至少 k 个连续的模式(即 i 的范围是 0 到 arr.length - m * k)。 对于每个起始位置 i,检查从该位置开始的连续 k 个模式的元素是否完全一致。直接通过数组索引比较元素。 Review New Zealand relaxes visa rules for ‘digital nomads’ - Breaking News English Lesson ...

2025-02-08 · 1 分钟 · 181 字

ARTS Week 46

Algorithm 本周的算法题为 1156. 单字符重复子串的最大长度 如果字符串中的所有字符都相同,那么这个字符串是单字符重复的字符串。 给你一个字符串 text,你只能交换其中两个字符一次或者什么都不做,然后得到一些单字符重复的子串。返回其中最长的子串的长度。 示例 1: 输入:text = "ababa" 输出:3 实现代码如下: const maxRepOpt1 = function (text) { const count = {}; for (const char of text) { if (!count[char]) { count[char] = 0; } count[char]++; } let max_length = 0; const n = text.length; for (let i = 0; i < n; i++) { const char = text[i]; let length = 1; let j = i + 1; while (j < n && text[j] === char) { length++; j++; } if (length < count[char]) { if (j < n && text[j] !== char && j + 1 < n && text[j + 1] === char) { let k = j + 1; while (k < n && text[k] === char) { length++; k++; } if (length < count[char]) { length++; } } else { length++; } } max_length = Math.max(max_length, length); } return max_length; } 解题思路: 使用一个对象 count 来统计每个字符的出现次数。遍历字符串,将每个字符的出现次数记录在 count 中。 使用一个外层循环,从每个字符开始,向右扩展,找到当前字符的最长连续重复子串。 如果当前子串长度小于该字符的总出现次数,尝试检查子串两端是否有相同字符,或者中间是否有不同字符可以交换。 每次找到一个更长的子串时,更新 max_length。 Review Lunar New Year sees record migration in China - Breaking News English Lesson ...

2025-02-07 · 1 分钟 · 202 字

产品线上交付阶段出现的两次显著Bug分析

前言 近期,部门内部的A项目在线上使用时出现了两次较为明显的Bug。作为负责A项目需求梳理、原型设计和功能验收的产品经理,我将从这一角色出发进行思考和总结。 问题描述 前端页面编辑一个输入框时,显示“入参错误”。 前端页面修改模块A时,模块B和模块C的同一参数输入框出现联动,都变为了模块A的值。 前端页面调用的字段和后端定义的功能没有对应上。 问题分析 问题一的主要原因是后端相关的功能只发布在了开发和测试环境,而正式环境没有发布。 问题二的原因是模块A、B和C中同一参数是抽取复用的,但前端在处理时,没有使用对象解构赋值 {...parameter} 来创建一个新的对象副本,而是直接引用了同一份 parameter 对象导致。 问题三的原因是需求文档显示,前端在开发时,已经和后端同事约定好参数字段一一对应,但在后端实现时,沟通上面信息没有同步到位,字段和预期的不一致,导致功能出现异常。前端开发人员没有真正从用户角度出发,验证功能是否完善。产品交付时,产品经理没有依据需求文档进行验收,做好输入和输出两个关键部分,形成闭环。 经验教训 当需求中出现大量专业性较高的参数字段时,需要在需求文档中说明清楚,确保信息同步,毕竟这些不是像username、mobile、email等常识类的字段。 前端在开发功能后,通常容易陷入只要保证自己实现的功能页面增删改查没有问题,就可以了。很少多想一步,从用户角度出发,模拟用户的使用场景,然后再次确认功能是否正常,这个意识还是很重要的。因为一个功能模块不仅仅涉及前端,还有后端,功能的验收要结合后端进行,这个时候没办法把职责划分那么清晰,只能前端主导,后端配合,把整个功能模块验证流程都走一遍,而不是浮于表面。 在部门里,期望产品同事参与到项目中,具体除了整理需求文档和原型设计,最终的交付也是很重要的,这就需要产品切实参与到版本功能的验收,确保和预期的需求一致。这方面曾涉及到对研发的信任问题,其实和信任没有关系,能力再出众,功能做得再好,如果理解错了需求,最终交付的不是需求的本意,那也是有问题的,所以产品参与最终版本的功能确认,是很关键的一环。就好像封装一个函数,输入和输出,先不管函数里面到底是怎么实现的,最终还是以函数输出的结果为重,函数给的结果都不对,里面用了多好的技术和巧妙构思,都显得苍白无力。所以,产品对于每一个需求点,需求->验收,应形成闭环。 潜意识里还是觉得是内部的项目,导致重视程度不够,而且,忙并不是借口,对于负责A项目的产品工作来说,验收形成闭环这一块确实懈怠了,本就应该按标准的项目流程去走,必须做的就要去做,没办法省略掉。 预防措施 验收环节需提供详细测试用例,并且分为三个环节:研发自测、项目负责人验收和产品交付验收,基本覆盖了这个功能的开发人员、这个项目的负责人和这个需求的提出人。 发版节奏放缓,确保各个环节都做到位。贪图求快,功能质量出现问题,工作结果还是大打折扣的。

2025-01-02 · 1 分钟 · 22 字

ARTS Week 45

Algorithm 本周的算法题为 1475. 商品折扣后的最终价格 给你一个数组 prices ,其中 prices[i] 是商店里第 i 件商品的价格。 商店里正在进行促销活动,如果你要买第 i 件商品,那么你可以得到与 prices[j] 相等的折扣,其中 j 是满足 j > i 且 prices[j] <= prices[i] 的 最小下标 ,如果没有满足条件的 j ,你将没有任何折扣。 请你返回一个数组,数组中第 i 个元素是折扣后你购买商品 i 最终需要支付的价格。 示例 1: 输入:prices = [8,4,6,2,3] 输出:[4,2,4,2,3] 解释: 商品 0 的价格为 price[0]=8 ,你将得到 prices[1]=4 的折扣,所以最终价格为 8 - 4 = 4 。 商品 1 的价格为 price[1]=4 ,你将得到 prices[3]=2 的折扣,所以最终价格为 4 - 2 = 2 。 商品 2 的价格为 price[2]=6 ,你将得到 prices[3]=2 的折扣,所以最终价格为 6 - 2 = 4 。 商品 3 和 4 都没有折扣。 实现代码如下: const finalPrices = function (prices) { let priceDifferences = [] prices.forEach((currentPrice, currentIndex) => { let lowerPriceIndexes = [] let priceDifference = 0 prices.forEach((comparePrice, compareIndex) => { if (compareIndex > currentIndex && comparePrice <= currentPrice) { lowerPriceIndexes.push(compareIndex); } }) if (lowerPriceIndexes.length === 0) { priceDifference = currentPrice } else { let minIndex = Math.min(...lowerPriceIndexes) priceDifference = currentPrice - prices[minIndex] } priceDifferences.push(priceDifference) }) return priceDifferences } 解题思路: 先遍历查询满足条件的下标,然后获取最小下标。 如果没有符合条件的折扣,则使用当前价格。 Review Mystery drones in USA causing alarm - Breaking News English Lesson ...

2025-01-01 · 1 分钟 · 175 字

unplugin-vue-router 的基本使用

1. 前言 在Vue3开发过程中,每次创建新的页面都需要注册路由,需要在src/router.ts中新增页面的路径,并将URL路径映射到组件中,如下所示: import { createMemoryHistory, createRouter } from 'vue-router' import HomePageView from './HomePageView.vue' import DevListView from './DevListView.vue' const routes = [ { path: '/', component: HomePageView }, { path: '/DevListView', component: DevListView }, ] const router = createRouter({ history: createMemoryHistory(), routes, }) 虽然看起来工作量不大,但如果页面特别多,就会感到繁琐。即使是微小的改动,如组件名的修改,也需要在路由文件中反复确认,反复如此就会感到不便。为了简化这部分工作,我想到了一个解决方案,那就是开发一个Vue3菜单路由生成工具,只需填写组件的中文名称,根据树形结构生成一个与routes结构相同的数组,然后替换使用即可。但还是觉得不够好,随后想到既然自己能发现这个问题,别人可能早已有了应对方案。接着,我就发现了 unplugin-vue-router 插件。 2. 配置 2.1 安装 npm install -D unplugin-vue-router 2.2 vite.config.ts import VueRouter from 'unplugin-vue-router/vite' export default defineConfig({ plugins: [ VueRouter({ /* options */ }), // ⚠️ Vue must be placed after VueRouter() Vue(), ], }) 2.3 tsconfig.json { "include": [ // other files... "./typed-router.d.ts" ], "compilerOptions": { // ... "moduleResolution": "Bundler", // ... } } 2.4 vite-env.d.ts /// <reference types="unplugin-vue-router/client" /> 3. 应用 3.1 常规方式 因为项目布局是基于Element Plus组件库的<el-container>搭建的,其中对<e-main>进行了处理,<router-view>是 Vue Router 的一个内置组件,用于渲染匹配当前路由的组件,如下所示: ...

2024-12-29 · 2 分钟 · 286 字