vivo2020届春季校园招聘手机屏幕解锁模式


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

[编程题]手机屏幕解锁模式

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

输入:m,n
代表允许解锁的最少m个键和最多n个键
输出:
满足m和n个键数的所有有效模式的总数
在这里插入图片描述

输入例子1:

1,2

输入例子1:

56

输入例子1:

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

用Java解题,算出所有可能性包括无效的模式,如285是无效的,而528是有效的。

在编写过程中,我突然发现其实输入9,9其实和8,8是一样的可能性,也就是其实8和9就是一样可能性的,因为最后9x8x7x6x5x4x3x2=9x8x7x6x5x4x3x2x1。也就是说输入1,9其实等于1,8加上8,8的所有可能性。
代码如下 代码片.

// An highlighted block
//默认是flase,如果为true代表被选择。
 public  static boolean  select[] = new boolean[10];
 //写出所有无效的路线
    public static String numberStr[] ={"13","19","17","31","91","71","39","37","93","73","79","97","46","64","82","28"};
    //与无效路线集合下标对应,值为穿过的点
    public static String pont[] ={"2","5","4","2","5","4","6","5","6","5","8","8","5","5","5","5"};
    public  static int solution (int m, int n){
      
        if(n<0||n-m<0) {
            return 0;
        }
        int tot =0;
        if(n==9&&m<9||n>9&&m<9){

               tot=allselect(m,n)-(4*cal(m,8,1,1,"")+4*cal(m,8,2,1,"")+cal(m,8,5,1,""))-(4*cal(8,8,1,1,"")+4*cal(8,8,2,1,"")+cal(8,8,5,1,""));


        }else {
            //  1 3 7 9 类似情况合并   2 4 6 8 类似情况合并   5又是一种情况
            if(n==9&&m==9){
                n =8;
                m =8;
            }
             tot=allselect(m,n)-(4*cal(m,n,1,1,"")+4*cal(m,n,2,1,"")+cal(m,n,5,1,""));;
        }

        return tot;
    }
    public static int allselect(int m,int n){

        int total = 0;
        int initM= m;
        int initN = n;
        int maxSelect =9;
        if(n<m ||n==0){
            return 0;
        }
        if(n>9){
            initN = 9;
        }
   
      while (initM>0){
          if(total==0){
              total= maxSelect;
          }else{
              total =maxSelect*total;

          }
          maxSelect = maxSelect-1;
          initM--;
      }

      if((m+1)<=initN){
          total = total+ allselect(m+1,initN);
      }

        return total;
    }
    public static int cal(int m,int n,int start,int end,String str){
        String path = str+start;

        int count = 0;
        if(end>n){
            return 0;
        }

        if(end>=m&&path.length()>1&&end<n){
          //  System.out.println(path);
            int j =0;
            boolean isFound = false;
            while (j<numberStr.length&&!isFound){
                if(path.indexOf(numberStr[j])>=0){
                    if(path.indexOf(pont[j])==-1||path.indexOf(pont[j])>path.indexOf(numberStr[j])){
                 
                        isFound =true;
                        count++;
                    }
                }
                j++;
            }

        }

        select[start] =true;

        for(int i =1;i<10;i++){
            if(!select[i]&&end<n){
                count = count+cal(m,n,i,end+1,path);
            }
            if(!select[i]&&end==n&&n>1){
               int j =0;
               boolean isFound = false;
               while (j<numberStr.length&&isFound==false){
                   if(path.indexOf(numberStr[j])>=0){
                       if(path.indexOf(pont[j])==-1||path.indexOf(pont[j])>path.indexOf(numberStr[j])){
     
                           count++;
                           select[start] =false;
                           return count;
                       }
                   }
                   j++;
               }
            }
        }
        select[start] =false;
        return count;
    }

该方法参考了https://blog.csdn.net/weixin_42241455/article/details/105168526中的解题思路,不同的是本方法是算所有可能性包括无效模式再减去无效的模式,参考方法是直接计算所有有效的模式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值