一道手机解锁模式的编程题--JS实现(排列组合算法)

现有一个 3x3 规格的智能手机锁屏程序和两个正整数 m 和 n ,请计算出使用最少m 个键和最多 n个键可以解锁该屏幕的所有有效模式总数。
其中有效模式是指:
1、每个模式必须连接至少m个键和最多n个键;
2、所有的键都必须是不同的;
3、如果在模式中连接两个连续键的行通过任何其他键,则其他键必须在模式中选择,不允许跳过非选择键(如图);
4、顺序相关,单键有效(这里可能跟部分手机不同)。

输入:m,n
代表允许解锁的最少m个键和最多n个键
输出:
满足m和n个键数的所有有效模式的总数

一道手机解锁模式的编程题--JS实现(排列组合算法)

题目原链接

解题思路

1、先要从9个键中选出x个键,且顺序相关,我们自然想到这是一个排列问题,若不考虑条件3,则选择x个键,模式有“Ax9”个(1<=x && x<=9)
2、条件3规定不允许跳过中间键,则这种特殊情况要剔除。比方说:若x=4,排列方式之一有“1324”即为不合法,“2134”为合法,因为2在1,3之间,若2排列在前,“13”可相邻,若2未选中或排列在其后,则1,3不可相邻

JavaScript实现如下:

/**
  * 实现方案
  * @param m int整型 最少m个键
  * @param n int整型 最多n个键
  * @return int整型
  */
function solution( m ,  n ) {
    // write code here
     //求从array中选出k个元素的排列函数
    function permute(array, k) {
        let res = [];
 
        if (k <= 0) {
            return res;
        }
 
        function generatePermutation(array, index, p) {
            if (index == k) {
                res.push(p.join(''));
                return;
            }
            for (let i of array) {
                if (p.indexOf(i) == -1) {
                    p.push(i);
                    generatePermutation(array, index + 1, p);
                    p.pop();
                }
            }
        }
        generatePermutation(array, 0, []);
        return res;
    }
 
    var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    var res = []; //此数组容纳“[n,m]”范围内的所有排列
    let maxNum = n > arr.length ? arr.length : n;
    for (let i = m; i <= maxNum; i++) {
        res = res.concat(permute(arr, i));
    }
 
    //特殊情况下的跨点路径
    imp = [
        ['13', '2'],
        ['17', '4'],
        ['19', '5'],
        ['28', '5'],
        ['31', '2'],
        ['37', '5'],
        ['39', '6'],
        ['46', '5'],
        ['64', '5'],
        ['71', '4'],
        ['73', '5'],
        ['79', '8'],
        ['82', '5'],
        ['91', '5'],
        ['93', '6'],
        ['97', '8']
    ];
    const map = new Map(imp);
 
    var count = res.length;
    for (let i of res) {
        for (let [k, v] of map) {
            let kIndex = i.indexOf(k);
            let vIndex = i.indexOf(v);
            if (kIndex != -1 && (vIndex > kIndex || vIndex == -1)) {
                count--;
                break;
            }
        }
    }
 
    return count;
}
module.exports = {
    solution : solution
};