划分字母区间
划分字母区间
给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s 。返回一个表示每个字符串片段的长度的列表。
输入:s = “ababcbacadefegdehijhklij”
输出:[9,7,8]
解释:划分结果为 “ababcbaca”、”defegde”、”hijhklij” 。每个字母最多出现在一个片段中。像 “ababcbacadefegde”, “hijhklij” 这样的划分是错误的,因为划分的片段数较少。
输入:s = “eccbbbbdec”
输出:[10]
思路先统计每个字符的结束位置,再根据结束位置做切割
解题方法统计每个字符结束位置,放入哈希表中遍历字符串,找寻一定范围内字符最远出现的下标位置当最远下标位置等于当前下标,说明找到一个分割点
1234567891011121314151617181920var partitionLabels = function(s) { // 先找每个字母的边界,为了找一定范围内最大值 ...
下一个排列
整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。例如,arr = [1,2,3] 的下一个排列是 [1,3,2] 。类似地,arr = [2,3,1] 的下一个排列是 [3,1,2] 。而 arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。给你一个整数数组 nums ,找出 nums 的下一个排列。必须 原地 修改,只允许使用额外常数空间。
下一个排列
输入:nums = [1,2,3]
输出:[1,3,2]
输入:nums = [3,2,1]
输出:[1,2,3]
12345678 ...
最长特殊序列 II
最长特殊序列 II
给定字符串列表 strs ,返回其中 最长的特殊序列 的长度。如果最长特殊序列不存在,返回 -1 。特殊序列 定义如下:该序列为某字符串 独有的子序列(即不能是其他字符串的子序列)。s 的 子序列可以通过删去字符串 s 中的某些字符实现。例如,”abc” 是 “aebdc” 的子序列,因为您可以删除”aebdc”中的下划线字符来得到 “abc” 。”aebdc”的子序列还包括”aebdc”、 “aeb” 和 “” (空字符串)。
输入: strs = [“aba”,”cdc”,”eae”]
输出: 3
输入: strs = [“aaa”,”aaa”,”aa”]
输出: -1
1234567891011121314151617181920212223242526272829303132var findLUSlength = function(strs) { let map = {}, max = 0, str // 哈希表计数 并且寻找最长字符串 for (let i = strs.length - 1; ...
实现sum(1,2,3)==sum(1)(2)(3)
实现 sum(1,2,3)==sum(1)(2)(3)1234567891011121314151617function sum(...args){ function currySum(...rest){ args.push(...rest) return currySum } currySum.toString= function(){ return args.reduce((result,cur)=>{ return result + cur }) } currySum.toNumber= function(){ return args.reduce((result,cur)=>{ return result + cur }) } return currySum}
单例模式
单例模式
单例模式即一个类只能构造出唯一实例,单例模式的意义在于共享、唯一,Redux/Vuex 中的 store、JQ 的$或者业务场景中的购物车、登录框都是单例模式的应用
123456789101112131415161718class SingletonLogin { constructor(name,password){ this.name = name this.password = password } static getInstance(name,password){ //判断对象是否已经被创建,若创建则返回旧对象 if(!this.instance)this.instance = new SingletonLogin(name,password) return this.instance }} let obj1 = SingletonLogin.getInstance('CXK','123')let obj2 = Singleto ...
代理模式
代理模式
代理模式,为一个对象找一个替代对象,以便对原对象进行访问。即在访问者与目标对象之间加一层代理,通过代理做授权和控制。最常见的例子是经纪人代理明星业务,假设你作为一个投资者,想联系明星打广告,那么你就需要先经过代理经纪人,经纪人对你的资质进行考察,并通知你明星排期,替明星本人过滤不必要的信息。事件代理、JQuery 的$.proxy、ES6 的 proxy 都是这一模式的实现,下面以 ES6 的 proxy 为例:
1234567891011121314151617181920212223const idol = { name: '蔡x抻', phone: 10086, price: 1000000 //报价}const agent = new Proxy(idol, { get: function(target) { //拦截明星电话的请求,只提供经纪人电话 return '经纪人电话:10010' }, set: function(target, key, ...
适配器模式
适配器模式
适配器模式,将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作。我们在生活中就常常有使用适配器的场景,例如出境旅游插头插座不匹配,这时我们就需要使用转换插头,也就是适配器来帮我们解决问题。
123456789101112131415161718class Adaptee { test() { return '旧接口' }} class Target { constructor() { this.adaptee = new Adaptee() } test() { let info = this.adaptee.test() return `适配${info}` }} let target = new Target()console.log(target.test())
装饰器模式
装饰器模式
装饰器模式,可以理解为对类的一个包装,动态地拓展类的功能,ES7的装饰器语法以及React中的高阶组件(HoC)都是这一模式的实现。react-redux的connect()也运用了装饰器模式,这里以ES7的装饰器为例:
12345678910function info(target) { target.prototype.name = '张三' target.prototype.age = 10}@infoclass Man {}let man = new Man()man.name // 张三
观察者模式
观察者模式
观察者模式算是前端最常用的设计模式了,观察者模式概念很简单:观察者监听被观察者的变化,被观察者发生改变时,通知所有的观察者。观察者模式被广泛用于监听事件的实现,有关观察者模式的详细应用,可以看我另一篇讲解Redux实现的文章
12345678910111213141516171819202122232425262728//观察者class Observer { constructor (fn) { this.update = fn }}//被观察者class Subject { constructor() { this.observers = [] //观察者队列 } addObserver(observer) { this.observers.push(observer)//往观察者队列添加观察者 } ...
优化一个冒泡排序
优化一个冒泡排序
冒泡排序总会执行(N-1)+(N-2)+(N-3)+..+2+1 趟,但如果运行到当中某一趟时排序已经完成,或者输入的是一个有序数组,那么后边的比较就都是多余的,为了避免这种情况,我们增加一个 flag,判断排序是否在中途就已经完成(也就是判断有无发生元素交换)
12345678910111213141516function bubbleSort(arr){ for(let i = 0; i < arr.length; i++) { let flag = true for(let j = 0; j < arr.length - i - 1; j++) { if(arr[j] > arr[j+1]) { flag = false let temp = arr[j] arr[j] = arr[j+1] arr[j+1] = temp } } // 这个flag的含义是:如果`某次循环`中没有交换过 ...