zoukankan      html  css  js  c++  java
  • 搜狗笔试题——密码生成

    问题:

    小汪作为一个有数学天分的程序猿,设计了一套密码生成器来搞定自己的密码问题。
    密码生成器由N个槽位组成,槽位的下标为0~N-1,每个槽位存储一个数。起初每个槽位都是0。
    密码生成器会进行M轮计算,每轮计算,小汪会输入两个数L,R(L<=R),密码生成器会将这两个数作为下标,将两个下标之间(包含)的所有槽位赋值为i(i为当前的轮次,i∈[1,M])。
    M轮计算完成后,密码生成器会根据槽位的最终值生成一条密码,密码的生成规则为:
    (0*a[0] + 1*a[1] + 2*a[2] + ... + (N-1)*a[N-1]) mod 100000009
    其中a[i]表示第i个槽位的最终值。
    请帮助小汪把他的密码生成器实现为代码。

    链接:https://www.nowcoder.com/questionTerminal/96bf0c548a094de7a05919e0b32b1a5a?toCommentId=6455114
    来源:牛客网

    分析

      (1)第一种方式,根据题意使用数组表示槽位。但是最坏的时间复杂度达到O(m*n),我的代码只能通过30%的测试。  (2)第二种方式,使用问题转换。只记录分割片段,输入数据的同时实时更新已经记录的片段。最后通过数学公式获得最终值。我的代码在本地能通过题目提供的测试,但是在web端提交运行出现错误且未通过(您的代码已保存

    请检查是否存在数组越界等非法访问情况)。在这种方法中,槽位n并没有被实际用到。

    代码

    方式1代码:

     1 import java.util.Arrays;
     2 import java.util.Scanner;
     3 
     4 /**
     5  *题目:小汪的密码问题
     6  * 使用数组记录每个槽位
     7  */
     8 public class Main6_1{
     9     public static void main(String args[]){
    10         Scanner in = new Scanner(System.in);
    11         int n,m;
    12         n = in.nextInt();   //槽位
    13         m = in.nextInt();   //运算轮次
    14         int[] dp = new int[n];  //创建槽位
    15         int x,y;
    16         //循环计算
    17         for(int i=1;i<=m;i++){
    18             x = in.nextInt();
    19             y = in.nextInt();
    20             /*while(x<=y){
    21                 dp[x++]=i;
    22                 dp[y--]=i;
    23             }*/
    24             //内部实际也是遍历填充
    25             Arrays.fill(dp,x,y+1,i);
    26             //System.out.println(Arrays.toString(dp)); //显示每一轮计算后的结果
    27         }
    28         //根据规则计算结果值
    29         double res = 0;
    30         for(int i=0;i<n;i++){
    31             res+=i*dp[i];
    32         }
    33         //对结果值取模
    34         System.out.printf("%.0f",res%100000009);
    35     }
    36 }
    View Code

    方式2代码:

     1 import java.util.*;
     2 
     3 /**
     4  *题目:小汪的密码问题
     5  * 使用map记录片段
     6  * 动态分割片段:使用新片段分割老片段
     7  *
     8  * 存在四种情况
     9  * 设已经存在的片段端点为a1,b1,新片段端点为a2,b2
    10  * case1:a1<a2<=b1
    11  * 分割结果:(a1,a2-1),(a2,b2)
    12  * case2:a2<=a1 && b2>=b1
    13  * 分割结果:(a2,b2)
    14  * case3:a1<=b2<b1
    15  * 分割结果:(b2+1,b1),(a2,b2)
    16  * case4:a1<a2 && b2 > b1
    17  * 分割结果:(a1,a2-1) (a2,b2),(b2+1,b1)
    18  *
    19  * 运行结果提示:请检查是否存在数组越界等非法访问情况
    20  * 猜测:在外部对map进行了修改。测序出现错误
    21  */
    22 public class Main6_2{
    23     public static void main(String args[]){
    24         Scanner in = new Scanner(System.in);
    25         int m,n;
    26         n = in.nextInt();
    27         m = in.nextInt();
    28         //记录每次轮次的所有片段,因为前面的片段可能被后面的轮次进行更细小的切割
    29         Map<Integer,Map<Integer,Integer>> dp = new HashMap<>();
    30         int a2,b2;
    31         //循环轮次
    32         for(int i=1;i<=m;i++){
    33             a2 = in.nextInt();
    34             b2 = in.nextInt();
    35 
    36             //更新已经存在的片段:覆盖、再分割
    37             for(int j=1;j<i;j++){
    38                 //如果存在该轮dp.get(i)!=null && dp.get(i).size()>0次的片段,实施分割
    39                 if(dp.get(j)!=null && dp.get(j).size()>0){
    40                     Map<Integer,Integer> curMap = dp.get(j);
    41                     for(Map.Entry<Integer,Integer> entry:curMap.entrySet()){
    42                             int a1 = entry.getKey();
    43                             int b1 = entry.getValue();
    44                         if(a2>a1 && a2<=b1){  //case1:a1<a2<=b1
    45                             entry.setValue(a2-1);
    46                         }else if(a2<=a1 && b2>=b1){  //case2:a2<=a1 && b2>=b1
    47                            curMap.remove(a1);
    48                         }else if(b2>=a1 && b2<b1){ //case3:a1<=b2<b1
    49                             curMap.remove(a1);
    50                             curMap.put(b2+1,b1);
    51                         }else if(a1<a2 && b2>b1){     //case4:a1<a2 && b2 > b1
    52                             entry.setValue(a2-1);
    53                             curMap.put(b2+1,b1);
    54                         }
    55                     }
    56                 }
    57             }
    58             //放入当前片段
    59             Map<Integer,Integer> tmp = new HashMap<>();
    60             tmp.put(a2,b2);
    61             dp.put(i,tmp);
    62 
    63         }
    64         double res = 0;
    65         /*
    66         单个片段的计算公式:
    67         (1)片段长度为count
    68         (2)片段轮次为i
    69         (3)片段首位坐标为为x,y
    70         (4)计算公式整合:x*i+(x+1)*i .... +y*i = (x+(x+1)+...+y)*i
    71          */
    72         for(int i=1;i<=m;i++){
    73             if(dp.get(i)!=null && dp.get(i).size()>0){
    74                 Map<Integer,Integer> curMap = dp.get(i);
    75                 for(Map.Entry<Integer,Integer> entry:curMap.entrySet()){
    76                     int x = entry.getKey();
    77                     int y = entry.getValue();
    78                     int count = y-x+1;
    79                     double v = (count*(x+y))/2.0;
    80                     res+=i*v;
    81                 }
    82             }
    83         }
    84         System.out.printf("%.0f",res%100000009);
    85     }
    86 }
    View Code
  • 相关阅读:
    shiro学习详解(开篇)
    好记性不如烂笔头之Maven使用小记
    【转】log4j.properties文件的配置
    undefined和NUll的区别
    select选择框在谷歌火狐和IE样式的不同
    windows.onload和 document.ready区别
    深入理解line-height
    display:none,overflow:hidden,visibility:hidden之间的区别
    diplay:table-cell和伪元素:after方法让图片居中
    弹性布局各种坑爹兼容
  • 原文地址:https://www.cnblogs.com/dream-flying/p/13295606.html
Copyright © 2011-2022 走看看