电话号码组合及卡牌分组

电话号码的组合 给定一个仅包含数字2-9的字符串,返回所有它能表示的字母组合。数字和字母的映射和电话的按键相同。注意:1不对应任何字母 示例: 输入:"23" 输出:["ad","ae","af","bd","be","bf","cd","ce","cf"] 说明:上面的答案是按照字典序排列的,但是你可以任意选择答案输出的顺序 思路:当数字只有2个的时候,进行排列组合会非常的容易计算和理解。所以无论多少个数字,都可以转换成22进行组合的情况。 export default (str) => { // 建立电话号码键盘映射 let map = ['', 1, 'abc', 'def', 'ghi', 'jkl', 'mno', 'pqrs', 'tuv', 'wxyz'] // 把输入字符串按单字符分隔变成数组,234=>[2,3,4] let num = str.split('') // 保存键盘映射后的字母内容,如 23=>['abc','def'] let code = [] num.forEach(item => { if (map[item]) { code.push(map[item]) } }) let comb = (arr) => { // 临时变量用来保存前两个组合的结果 let tmp = [] // 最外层的循环是遍历第一个元素,里层的循环是遍历第二个元素 for (let i = 0, il = arr[0].length; i < il; i++) { for (let j = 0, jl = arr[1].length; j < jl; j++) { tmp.push(`${arr[0][i]}${arr[1][j]}`) } } // 进行替换 arr.splice(0, 2, tmp) if (arr.length > 1) { comb(arr) } else { return tmp } return arr[0] } return comb(code) } 接下来写测试用例 import telComb from '../../code/array/lesson1' test('telComb:23', () => { expect(telComb('23')).toEqual(['ad', 'ae', 'af', 'bd', 'be', 'bf', 'cd', 'ce', 'cf']) }) test('telComb:234', () => { expect(telComb('234')).toEqual([ 'adg', 'adh', 'adi', 'aeg', 'aeh', 'aei', 'afg', 'afh', 'afi', 'bdg', 'bdh', 'bdi', 'beg', 'beh', 'bei', 'bfg', 'bfh', 'bfi', 'cdg', 'cdh', 'cdi', 'ceg', 'ceh', 'cei', 'cfg', 'cfh', 'cfi' ]) }) 然后npm test进行测试。 卡牌分组 给定一副牌,每张牌上都写着一个整数。 此时,你需要选定一个数字x,使我们可以将整副牌按下述规则分成1组或更多组: 每组都有x张牌 组内所有的牌上都写着相同的整数 仅当你可选的x>=2时返回true 示例1: 输入:[1,2,3,4,4,3,2,1] 输出:true 解释:可行的分组是[1,1],[2,2],[3,3],[4,4] 示例2: 输入:[1,1,1,2,2,2,3,3] 输出:false 解释:没有满足要求的分组 示例3: 输入:[1,1,2,2,2,2] 输出:true 解释:可行的分组是[1,1],[2,2],[2,2] export default (arr) => { // 对这副牌进行排序,升序、降序都可以 // 排序目标:让相同的数字紧挨着 arr.sort((a, b) => a - b) // 最小值是当前浏览器支持的最大值Number.MAX_SAFE_INTEGER let min = Number.MAX_SAFE_INTEGER let dst = [] let result = true // tmp临时变量 // 下面这个for循环作用是把arr按照不同的数字给分成单独的数组 // 每个数组里的数字是相同的 for (let i = 0, len = arr.length, tmp = []; i < len; i++) { tmp.push(arr[i]) for (let j = i + 1; j < len - 1; j++) { if (arr[i] === arr[j]) { tmp.push(arr[j]) } else { // 保障min代表的永远是相同数字组成的元素数量最小值 if (min > tmp.length) { min = tmp.length } // 数组是引用类型,所以下面这行代码不能直接pushtmp // 如果直接push的话,接下来的循环会改变tem // 会导致dst里面的tmp引用也跟着不停的变 // [].concat()相当于开辟了一个新的内存空间 dst.push([].concat(tmp)) // length等于0是真正的清空临时数组 tmp.length = 0 // 跳过相同数字 i = j break } } } // 循环dst里的每一项 // 只要有一项的长度不是最小长度的整数倍,就返回false // forEach不能中断循环,所有这里用的every dst.every(item => { if (item.length % min !== 0) { result = false return false } }) return result } 写测试用例 import cardGroup from '../../code/array/lesson2' test('cardGroup:[1,2,3,4,4,3,2,1]', () => { expect(cardGroup([1, 2, 3, 4, 4, 3, 2, 1])).toBe(true) }) test('cardGroup:[1,1,1,2,2,2,3,3]', () => { expect(cardGroup([1, 1, 1, 2, 2, 2, 3, 3])).toBe(false) }) test('cardGroup:[1,1,2,2,2,2]', () => { expect(cardGroup([1, 1, 2, 2, 2, 2])).toBe(true) }) 练习题:种花问题 假设你有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花卉不能种植在相邻的地块上,它们会争夺水源,两者都会死去。 给定一个花坛(表示为一个数组包含0和1,其中0表示没种植花,1表示种植了花),和一个数n,能否在不打破种植规则的情况下种入n朵花?能则返回true,不能则返回false 示例1: 输入:flowerbed = [1,0,0,0,1], n=1 输出:true 示例2: 输入:flowerbed = [1,0,0,0,1], n=2 输出:false 注意: 1.数组内已种好的花不会违反种植规则。 2.输入的数组长度范围为[1,20000] export default (arr, n) => { // 计数器 let max = 0 for (let i = 0, len = arr.length; i < len; i++) { if (arr[i] === 0) { // 判断一下是不是起始边界 if (i === 0 && arr[1] === 0) { max++ i++ } else if (arr[i - 1] === 0 && arr[i + 1] === 0) { max++ i++ } // 判断一下是不是结束边界 else if (i === Number(arr.length - 2) && arr[arr.length - 3] !== 0 && arr[arr.length - 1] === 0) { max++ console.log(max) } } } return max >= n } 测试用例: import flower from '../../code/array/lesson3' test('flower:[1,0,0,0,1],1', () => { expect(flower([1, 0, 0, 0, 1], 1)).toBe(true) }) test('flower:[1,0,0,0,1],2', () => { expect(flower([1, 0, 0, 0, 1], 2)).toBe(false) })

本文章由javascript技术分享原创和收集

发表评论 (审核通过后显示评论):