vivo2020届春季校园招聘在线编程考试(一)

题目:

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

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

在这里插入图片描述

示例1
输入例子: 1,2
输出例子: 65 例子说明:
输入m=1,n=2,表示最少1个键,最多2个键,符合要求的键数是1个键和2个键,其中1个键的有效模式有9种,两个键的有效模式有56种,所以最终有效模式总数是9+56=65种,最终输出65。

解题思路:
需要使用深度优先搜索(DFS)来遍历不同的解锁模式,并计算满足条件的模式数量,在遍历不同的起始点和连接不同数量的点时,使用了规则来判断有效的连接路径。
countPatterns方法:输入参数m和n,代表允许解锁的最少和最多键数,计算满足在范围[m,n]内允许的键数的所有有效模式的总数。
对于每个起始点(1,2和5),我们调用 dfs 方法,从该起始点开始,考虑连接 i - 1 个点的情况。疑问:为什么从1,2,5出发,其他点不要考虑吗?

  • 由于(1,3,7,9)角落点可以从四个不同的起始位置开始,它们连接其它点时会经过中间的点,所以我们乘以 4。
  • 对于从边上的点出发(2,4,6,8),它们不一定经过中间的点,所以也要乘4。
  • 对于中间点5,只需要考虑一种起始位置。
  • 所有这些结果累加起来,就得到在给定范围内满足条件的有效模式总数。

isValidPattern方法:输入参数:curr和next,代表当前键和下一个键的数字。该方法用于检查给定的当前键和下一个键是否构成有效的解锁模式。
dfs方法:输入参数:curr和remaining,代表当前键和剩余要连接的键数,该方法是一个深度优先搜索(DFS)的递归函数,用于计算在给定的键数限制下,从当前键开始的所有有效解锁模式的数量。

代码:

import java.util.*;


public class Solution {
    
    
    /**
     * 实现方案
     * @param m int整型 最少m个键
     * @param n int整型 最多n个键
     * @return int整型
     */
    
    private int [][]skip;//二维数组,表示两个键之间有需要跳过的键
    private boolean[] visited;//记录每个点是否已经被访问过
    public int solution (int m, int n) {
    
    
        // write code here
        skip = new int[10][10]; //
        skip[1][3] =skip[3][1] = 2;//表示键1和3之间有一个键2需要跳过,下面的以此类推
        skip[1][7] =skip[7][1] = 4;
        skip[3][9] = skip[9][3] = 6;
        skip[7][9] = skip[9][7] = 8;
        skip[1][9] = skip[9][1] = skip[3][7] = skip[7][3] = skip[2][8] = skip[8][2] = skip[4][6]= skip[6][4]= 5;
        visited = new boolean[10];
        int totalCount = 0;
        for(int i=m;i<=n;i++){
    
    
            totalCount += dfs(1,i-1)*4;//
            totalCount += dfs(6,i-1)*4;
            totalCount += dfs(5,i-1);
        }
        return totalCount;
    }
    private boolean isValidPattern(int curr,int next){
    
    
        if(visited[next]){
    
    
            return false; //如为真,代表已经被访问了
        }
        if(skip[curr][next]==0||visited[skip[curr][next]]){
    
    
            return true;
        }
        return false;
    }
    private int dfs(int curr,int remaining){
    
    
        if(remaining<0){
    
    
            return 0; //代表没有剩余要连接的点
        }
        if(remaining==0){
    
    
            return 1;
        }
        visited[curr] = true;
        int count = 0;
        for(int next=1;next<=9;next++){
    
    
            if(isValidPattern(curr,next)){
    
    
                count += dfs(next,remaining-1);
            }
        }
        visited[curr] = false;
        return count;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_45257495/article/details/132585614