电话号码组合及卡牌分组

电话号码的组合

给定一个仅包含数字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)
})
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容