面试之算法一

题目:

李雷和韩梅梅坐前后排,上课想说话怕被老师发现,所以改为传纸条。为了不被老师发现他们纸条上写的是啥,,他们约定了如下方法传递信息:

将26个大写英文字母,外加空格,一共27个字符分成三组,每组9个。也就是ABCDEFGHI是第一组,JKLMNOPQR是第二组,STUVWXYZ*是第三组(此处用*代表空格)。

先根据月份数m,一整个分组为单位进行左移,移动(m-1)次。

然后根据日期数d,对每个分组内的字符进行循环左移,移动(n-1)次。

以3月8日为例,首先移动分组3-1=2次,变成:

STUVWXYZ*  ABCDEFGHI  JKLMNOPQR21

然后每组内字符移动8-1 = 7次,最终编码为:

Z*STUVWXY  HIABCDEFG  QRJKLMNOP

对于要传递的信息中的每个字符,用组号和组内序号两个数字来表示。

如果在3月8日传递信息 “HAPPY”,那么H位于第2组的第1个,A位于第二组 第3个 .....一次类推,纸条上会写成:

21,23,39,39,19

输入要求:

每个输入包含两行。第一行使用空格分隔的两个数字,第一个数字是月份,第二个数字是日期。输入保证是一个合法日期。

第二个行为需要编码的字符串,仅由A~Z和空格组成,长度不超过1024个字符

 

输出规范:

对每个输入,打印对应的编码,数字之间用空格分隔,每个输出占一行。

 

输入示例:

1 1

HI

输出示例:

18 19
      我看到这个一题的时候,首先想到用思路是先根据月份移动分组,然后根据日期移动各个分组内的字母,等这一切工作做完后在便利传递信息字符串一一和每个分组的字符串比较取得相应的组号和组内序号。当我开始写的时候,忽然发现前面的移动工作完全的没必要。我们只需要将字母分好组,组1:A-I,组2:J-R,组3:S-*(*代替空格),然后获取字符所在分组的组号和分组中的索引即可计算出相应移动后的组号和组内序号。如:如1月28号,字符A移动后的组号是3,组内序号为9,故A的密文为39。下面开始上代码:

<div style="font-size:18px;">
package com.doctor.message;

import java.util.Map;

public class App {
    private Map map;
    public static void main(String args[]){
        char a[][]=makeBase();
        for(int i=0;i<a.length;i++){
            for(int j=0;j<a[i].length;j++){
                System.out.print(a[i][j]);
            }
            System.out.println();
        }
        //加密
        int rs[] = encrypt("HELLO WORD",28,3);
        for(int i:rs){
            System.out.print(i+"  ");
        }
        System.out.println();
        //解密
        String msg = decode(rs,3,28);
        System.out.println(msg);
    }
    //加密时计算每个字母移动后的位置
    public static int movePosition(int base,int position,int num){
        int r=num%base;
        int b=position-r;
        if(b>=0){
            return b;
        }
        return base+b;
    }
    //加密
    public static int[] encrypt(String message,int day,int month){

        int result[]=new int[message.length()];
        for(int i=0;i<message.length();i++){
            char m = message.charAt(i);

            char az[][]=makeBase();

            for(int x=0;x<az.length;x++){
                if((az[x][0]<=m&&m<=az[x][8])||' '==m||m>='S'){
                    //计算组号
                    int grp = movePosition(3,x,month)+1;
                    //计算字母在组中的位置
                    for(int j=0;j<9;j++){
                        if(m==az[x][j]){
                            result[i]=grp*10+(movePosition(9,j,day)+1);
                            break;
                        }
                    }
                }
            }

        }
        return result;
    }
    //解密时计算密文移动前的位置
    public static int dePosition(int base,int position,int num){
        int r=num%base;
        int b=position+r;
        return b%base;
    }
    //输入密文解密
    public static String decode(int msg[],int month,int day){
        char base[][] = makeBase();
        String s="";
        for(int i=0;i<msg.length;i++){
            int screat = msg[i];
            //获取密文的个位数字
            int a = dePosition(9,screat%10-1,day);
            //获取十位数字
            int b= dePosition(3,screat/10-1,month);
            s= s+base[b][a];
        }
        return s;
    }
    //将A到*分组放入char字符数组中
    public static char [][] makeBase(){
        char a[][] = new char [3][27];
        String AZ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ ";
        for(int i=0;i<3;i++){
            for(int j=0;j<9;j++){
                int ps = i*9+j;
                a[i][j]=AZ.charAt(ps);
            }
        }
        return a;
    }
}

</div>

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值