当前位置:编程学习 > JAVA >>

求助一个算法题

今天笔试做的一个算法题,当时觉得很容易,结果越写越复杂,还求助一下各位网友给个答案。
题目是我映像中写下来的。
从控制台输入一个字符串,要求返回其二进制数。输入的数当成十六进制数处理,如输入3A,返回111010,输入17返回10001。如果输入的字符串不合法则提示错误,当然,要区分是因为输入的字符串是不能组成十六进制数的错误还是输入的数超过了范围的错误。 --------------------编程问答-------------------- Integer.parseInt(str,16); --------------------编程问答-------------------- Integer.toBinaryString(Integer.parseInt(str,16)); --------------------编程问答--------------------

public String getBinaryStr() {
    Scanner sc = new Scanner(System.in);
    System.out.println("Please input the hex number");
    String input = sc.next();
    while (input == null || input == "") {
        input = sc.next();
    }
    sc.close();
    String regex = "[1-9A-F][0-9A-F]*";
    // 不是很理解“要区分是因为输入的字符串是不能组成十六进制数的错误还是输入的数超过了范围的错误”
    // 输入不合格统一按非法处理
    if (!input.toUpperCase().matches(regex)) {
        return "Your input is illegal";
    }
    int tenRadix = Integer.parseInt(input, 16);
    String twoRadix = Integer.toBinaryString(tenRadix);
    return twoRadix;
}


欢迎探讨学习  --------------------编程问答-------------------- 这边有个想法,纸上谈兵一下:
1. 初始化一个Map<String,String>,0~9、A(a)~F(f)为key,0000~1001、1010~1111为value(16进制对应的2进制)
2. 入参解析,可以将字符串拆分成一个个单个字符的字符串,用Map一个个取对应value,也可以考虑用正则表达式匹配
3. 按位转换为2进制(16进制与2进制存在天然的转换关系:一个16进制,4位2进制),直接字符串拼接即可 --------------------编程问答-------------------- 用正则是必然的,但用Integer.parseInt(str,16); 函数,这道题立马就0分了;面试过程中(一定要理解出题者的意图,不能盲目的调用库函数,包括sort、binarySearch等等,不然就等着被pass),进制转换没有捷径,循环+栈是唯一的办法 --------------------编程问答--------------------
引用 1 楼 x19881216 的回复:
Integer.parseInt(str,16);

题目是要写算法,应该不是这么简单的转换一下吧。 --------------------编程问答--------------------
引用 2 楼 waynexuan 的回复:
Integer.toBinaryString(Integer.parseInt(str,16));


引用 3 楼 magi1201 的回复:

public String getBinaryStr() {
    Scanner sc = new Scanner(System.in);
    System.out.println("Please input the hex number");
    String input = sc.next();
    while (input == null || input == "") {
        input = sc.next();
    }
    sc.close();
    String regex = "[1-9A-F][0-9A-F]*";
    // 不是很理解“要区分是因为输入的字符串是不能组成十六进制数的错误还是输入的数超过了范围的错误”
    // 输入不合格统一按非法处理
    if (!input.toUpperCase().matches(regex)) {
        return "Your input is illegal";
    }
    int tenRadix = Integer.parseInt(input, 16);
    String twoRadix = Integer.toBinaryString(tenRadix);
    return twoRadix;
}


欢迎探讨学习 

一共三个算法题,年薪十二万。。应该不是简单调用库函数吧。对了,这也是最简单的那个题。 --------------------编程问答-------------------- 这种笔试题就看考官的意图了。
可能是以下几种:
1、就是考算法,让你自己实现;
2、考你javaAPI的熟练程度;
3、考你思维严谨度,比如边界值,收入输出,异常处理等,这时候用什么实现估计就不关心了。 --------------------编程问答--------------------
引用 4 楼 oh_Maxy 的回复:
这边有个想法,纸上谈兵一下:
1. 初始化一个Map<String,String>,0~9、A(a)~F(f)为key,0000~1001、1010~1111为value(16进制对应的2进制)
2. 入参解析,可以将字符串拆分成一个个单个字符的字符串,用Map一个个取对应value,也可以考虑用正则表达式匹配
3. 按位转换为2进制(16进制与2进制存在天然的转换关系:一个16进制,4位2进制),直接字符串拼接即可

您可以试着写下代码不?但是不能调用库函数。。 --------------------编程问答--------------------
引用 5 楼 SmallYamateh 的回复:
用正则是必然的,但用Integer.parseInt(str,16); 函数,这道题立马就0分了;面试过程中(一定要理解出题者的意图,不能盲目的调用库函数,包括sort、binarySearch等等,不然就等着被pass),进制转换没有捷径,循环+栈是唯一的办法

恩,您说的很对。您可以写下代码我参考下不? --------------------编程问答--------------------
引用 8 楼 zzq19860626 的回复:
这种笔试题就看考官的意图了。
可能是以下几种:
1、就是考算法,让你自己实现;
2、考你javaAPI的熟练程度;
3、考你思维严谨度,比如边界值,收入输出,异常处理等,这时候用什么实现估计就不关心了。

这个就是考算法。。考API会而外标注出来。。之前也遇到过很多考逻辑死思维的。。 --------------------编程问答--------------------
引用 4 楼 oh_Maxy 的回复:
这边有个想法,纸上谈兵一下:
1. 初始化一个Map<String,String>,0~9、A(a)~F(f)为key,0000~1001、1010~1111为value(16进制对应的2进制)
2. 入参解析,可以将字符串拆分成一个个单个字符的字符串,用Map一个个取对应value,也可以考虑用正则表达式匹配
3. 按位转换为2进制(16进制与2进制存在天然的转换关系:一个16进制,4位2进制),直接字符串拼接即可

如果算法题目 类似于版主的这种做法估计好点。 --------------------编程问答--------------------
引用 12 楼 zzq19860626 的回复:
Quote: 引用 4 楼 oh_Maxy 的回复:

这边有个想法,纸上谈兵一下:
1. 初始化一个Map<String,String>,0~9、A(a)~F(f)为key,0000~1001、1010~1111为value(16进制对应的2进制)
2. 入参解析,可以将字符串拆分成一个个单个字符的字符串,用Map一个个取对应value,也可以考虑用正则表达式匹配
3. 按位转换为2进制(16进制与2进制存在天然的转换关系:一个16进制,4位2进制),直接字符串拼接即可

如果算法题目 类似于版主的这种做法估计好点。

如果不考API的话,楼主的方法很快的,这个问题的主要点还在不能组成十六进制数的错误还是输入的数超过了范围的错误。输入的数操作用正则表达式就可以,超过的范围自己判断一下,16进制最多8位,就可以判断范围了吧? --------------------编程问答-------------------- 参照版主的思路写了一个,注意输出的时候要去掉多余的0.


import java.util.HashMap;

/**
 * 从控制台输入一个字符串,要求返回其二进制数。输入的数当成十六进制数处理,如输入3A,返回111010,输入17返回10001。
 * 如果输入的字符串不合法则提示错误,当然,要区分是因为输入的字符串是不能组成十六进制数的错误还是输入的数超过了范围的错误。
 * 
 * 
 */
public class Test019 {

final static HashMap<Character, String> BINARY_CODE_MAP = new HashMap<Character, String>();

static {
BINARY_CODE_MAP.put('0', "0000");
BINARY_CODE_MAP.put('1', "0001");
BINARY_CODE_MAP.put('2', "0010");
BINARY_CODE_MAP.put('3', "0011");
BINARY_CODE_MAP.put('4', "0100");
BINARY_CODE_MAP.put('5', "0101");
BINARY_CODE_MAP.put('6', "0110");
BINARY_CODE_MAP.put('7', "0111");
BINARY_CODE_MAP.put('8', "1000");
BINARY_CODE_MAP.put('9', "1001");
BINARY_CODE_MAP.put('A', "1010");
BINARY_CODE_MAP.put('B', "1011");
BINARY_CODE_MAP.put('C', "1100");
BINARY_CODE_MAP.put('D', "1101");
BINARY_CODE_MAP.put('E', "1110");
BINARY_CODE_MAP.put('F', "1111");
BINARY_CODE_MAP.put('a', "1010");
BINARY_CODE_MAP.put('b', "1011");
BINARY_CODE_MAP.put('c', "1100");
BINARY_CODE_MAP.put('d', "1101");
BINARY_CODE_MAP.put('e', "1110");
BINARY_CODE_MAP.put('f', "1111");
}


/**
 * 把字符串转化成2进制数,有效长度31位。
 * @param numStr 源字符串
 * @return 与源字符串对应的2进制数,字符串不合法则提示是不能组成十六进制数的错误还是输入的数超过了范围的错误
 */
static String fromIntegerToBinary(String numStr) {
return toBinary(numStr, 31);
}

/**
 * 把字符串转化成2进制数。
 * @param numStr 源字符串
 * @param range 2进制数有效长度
 * @return 与源字符串对应的2进制数,字符串不合法则提示是不能组成十六进制数的错误还是输入的数超过了范围的错误
 */
private static String toBinary(String numStr,int range) {
if(numStr == null || numStr.isEmpty()) {
return numStr;
}
char[] arr = numStr.toCharArray();
StringBuilder sb = new StringBuilder();
for (char c : arr) {
if(BINARY_CODE_MAP.containsKey(c)) {
sb.append(BINARY_CODE_MAP.get(c));
} else {
return "illegal char " + c;
}
}
//格式化输出字符串
String result = sb.toString();
if(!result.contains("1")) {
//全0
result = "0";
} else {
//去掉多余的0
result = result.substring(result.indexOf("1"));
}
//超过范围报错
if(result.length() > range) {
return "out of range size:" + result.length();
}
return result;
}

public static void main(String[] args) {
System.out.println(fromIntegerToBinary("0"));
System.out.println(fromIntegerToBinary("00000000"));
System.out.println(fromIntegerToBinary("3A"));
System.out.println(fromIntegerToBinary("017"));
System.out.println(fromIntegerToBinary("7FFFFFFF"));
System.out.println(fromIntegerToBinary("80000000"));
System.out.println(fromIntegerToBinary("dfg"));
System.out.println(fromIntegerToBinary("123呵呵12a"));
}
}

--------------------编程问答-------------------- 。。。直接去看Integer的算法难道不好么?


/**
     * Parses the string argument as a signed integer in the radix 
     * specified by the second argument. The characters in the string 
     * must all be digits of the specified radix (as determined by 
     * whether {@link java.lang.Character#digit(char, int)} returns a 
     * nonnegative value), except that the first character may be an 
     * ASCII minus sign <code>'-'</code> (<code>'\u002D'</code>) to 
     * indicate a negative value. The resulting integer value is returned. 
     * <p>
     * An exception of type <code>NumberFormatException</code> is
     * thrown if any of the following situations occurs:
     * <ul>
     * <li>The first argument is <code>null</code> or is a string of
     * length zero.
     * <li>The radix is either smaller than 
     * {@link java.lang.Character#MIN_RADIX} or
     * larger than {@link java.lang.Character#MAX_RADIX}. 
     * <li>Any character of the string is not a digit of the specified
     * radix, except that the first character may be a minus sign
     * <code>'-'</code> (<code>'\u002D'</code>) provided that the
     * string is longer than length 1.
     * <li>The value represented by the string is not a value of type
     * <code>int</code>. 
     * </ul><p>
     * Examples:
     * <blockquote><pre>
     * parseInt("0", 10) returns 0
     * parseInt("473", 10) returns 473
     * parseInt("-0", 10) returns 0
     * parseInt("-FF", 16) returns -255
     * parseInt("1100110", 2) returns 102
     * parseInt("2147483647", 10) returns 2147483647
     * parseInt("-2147483648", 10) returns -2147483648
     * parseInt("2147483648", 10) throws a NumberFormatException
     * parseInt("99", 8) throws a NumberFormatException
     * parseInt("Kona", 10) throws a NumberFormatException
     * parseInt("Kona", 27) returns 411787
     * </pre></blockquote>
     *
     * @param      s   the <code>String</code> containing the integer 
     *  representation to be parsed
     * @param      radix   the radix to be used while parsing <code>s</code>.
     * @return     the integer represented by the string argument in the
     *             specified radix.
     * @exception  NumberFormatException if the <code>String</code>
     *     does not contain a parsable <code>int</code>.
     */
    public static int parseInt(String s, int radix)
throws NumberFormatException
    {
        if (s == null) {
            throw new NumberFormatException("null");
        }

if (radix < Character.MIN_RADIX) {
    throw new NumberFormatException("radix " + radix +
    " less than Character.MIN_RADIX");
}

if (radix > Character.MAX_RADIX) {
    throw new NumberFormatException("radix " + radix +
    " greater than Character.MAX_RADIX");
}

int result = 0;
boolean negative = false;
int i = 0, max = s.length();
int limit;
int multmin;
int digit;

if (max > 0) {
    if (s.charAt(0) == '-') {
negative = true;
limit = Integer.MIN_VALUE;
i++;
    } else {
limit = -Integer.MAX_VALUE;
    }
    multmin = limit / radix;
    if (i < max) {
digit = Character.digit(s.charAt(i++),radix);
if (digit < 0) {
    throw NumberFormatException.forInputString(s);
} else {
    result = -digit;
}
    }
    while (i < max) {
// Accumulating negatively avoids surprises near MAX_VALUE
digit = Character.digit(s.charAt(i++),radix);
if (digit < 0) {
    throw NumberFormatException.forInputString(s);
}
if (result < multmin) {
    throw NumberFormatException.forInputString(s);
}
result *= radix;
if (result < limit + digit) {
    throw NumberFormatException.forInputString(s);
}
result -= digit;
    }
} else {
    throw NumberFormatException.forInputString(s);
}
if (negative) {
    if (i > 1) {
return result;
    } else { /* Only got "-" */
throw NumberFormatException.forInputString(s);
    }
} else {
    return -result;
}
    }



  /**
     * Convert the integer to an unsigned number.
     */
    private static String toUnsignedString(int i, int shift) {
char[] buf = new char[32];
int charPos = 32;
int radix = 1 << shift;
int mask = radix - 1;
do {
    buf[--charPos] = digits[i & mask];
    i >>>= shift;
} while (i != 0);

return new String(buf, charPos, (32 - charPos));
    }
--------------------编程问答--------------------
 /**
     * Returns the numeric value of the specified character (Unicode
     * code point) in the specified radix.
     * 
     * <p>If the radix is not in the range <code>MIN_RADIX</code> <=
     * <code>radix</code> <= <code>MAX_RADIX</code> or if the
     * character is not a valid digit in the specified
     * radix, <code>-1</code> is returned. A character is a valid digit
     * if at least one of the following is true:
     * <ul>
     * <li>The method {@link #isDigit(int) isDigit(codePoint)} is <code>true</code> of the character
     *     and the Unicode decimal digit value of the character (or its
     *     single-character decomposition) is less than the specified radix.
     *     In this case the decimal digit value is returned.
     * <li>The character is one of the uppercase Latin letters
     *     <code>'A'</code> through <code>'Z'</code> and its code is less than
     *     <code>radix + 'A' - 10</code>.
     *     In this case, <code>ch - 'A' + 10</code>
     *     is returned.
     * <li>The character is one of the lowercase Latin letters
     *     <code>'a'</code> through <code>'z'</code> and its code is less than
     *     <code>radix + 'a' - 10</code>.
     *     In this case, <code>ch - 'a' + 10</code>
     *     is returned.
     * </ul>
     *
     * @param   codePoint the character (Unicode code point) to be converted.
     * @param   radix   the radix.
     * @return  the numeric value represented by the character in the
     *          specified radix.
     * @see     java.lang.Character#forDigit(int, int)
     * @see     java.lang.Character#isDigit(int)
     * @since   1.5
     */
    public static int digit(int codePoint, int radix) {
        int digit = -1;

        if (codePoint >= MIN_CODE_POINT && codePoint <= FAST_PATH_MAX) {
            digit = CharacterDataLatin1.digit(codePoint, radix);
        } else {
            int plane = getPlane(codePoint);
            switch(plane) {
            case(0):
                digit = CharacterData00.digit(codePoint, radix);
                break;
            case(1):
                digit = CharacterData01.digit(codePoint, radix);
                break;
            case(2):
                digit = CharacterData02.digit(codePoint, radix);
                break;
            case(3): // Undefined
            case(4): // Undefined
            case(5): // Undefined
            case(6): // Undefined
            case(7): // Undefined
            case(8): // Undefined
            case(9): // Undefined
            case(10): // Undefined
            case(11): // Undefined
            case(12): // Undefined
            case(13): // Undefined
                digit = CharacterDataUndefined.digit(codePoint, radix);
                break;
            case(14): 
                digit = CharacterData0E.digit(codePoint, radix);
                break;
            case(15): // Private Use
            case(16): // Private Use
                digit = CharacterDataPrivateUse.digit(codePoint, radix);
                break;
            default:
                // the argument's plane is invalid, and thus is an invalid codepoint
                // digit remains -1;
                break;
            }
        }
        return digit;
    }



--------------------编程问答-------------------- 直接转,有异常就说明参数非法,多快捷
--------------------编程问答-------------------- 参考14L吧,他写的蛮好的,注释也蛮清晰。 --------------------编程问答--------------------
引用 10 楼 ifvlr 的回复:
Quote: 引用 5 楼 SmallYamateh 的回复:

用正则是必然的,但用Integer.parseInt(str,16); 函数,这道题立马就0分了;面试过程中(一定要理解出题者的意图,不能盲目的调用库函数,包括sort、binarySearch等等,不然就等着被pass),进制转换没有捷径,循环+栈是唯一的办法

恩,您说的很对。您可以写下代码我参考下不?


public class Parse {

/**
 * output:10101011110101
 */
public static void main(String[] args) {
parse16To2("2AF5");
}
/**
把任意一位16进制数字转换为2进制
由于0转换为0000、F转换为1111,写死了4位,可以不用stack
 */
private static String parseOne(int k){
int[] array=new int[4];
int i=3;
while(k>0){
array[i]=k%2;
k/=2;
i--;
}
String str="";
for(i=0;i<=3;i++){
str+=array[i];
}
return str;

}
/**
 * 遍历str 
 *     判断这一位是数字还是字母,并把这一位转换为2进制
 *     (请在面试时牢记A的AscII码为65,0的AscII码为48,a的AscII码为97)
 * 最后,去掉前面的0
 */
public static void parse16To2(String str){
if(!str.matches("[\\dA-F]{1,8}")){
System.out.println("不符合!");
}else{
String total="";
char c=0;
int k=0;
int i=0;
for(;i<str.length();i++){
c=str.charAt(i);
if(c>='A'&&c<='F'){
k=c-55;
}else{
k=c-'0';
}
total+=parseOne(k);
}
for(i=0;i<total.length();i++){
if(total.charAt(i)=='1'){
break;
}
}
System.out.println(total.substring(i));
}
}
}

--------------------编程问答-------------------- 来个人来修正一下,我忘写小写字母的情况了。 --------------------编程问答--------------------
引用 14 楼 zyc13701469860 的回复:
参照版主的思路写了一个,注意输出的时候要去掉多余的0.


import java.util.HashMap;

/**
 * 从控制台输入一个字符串,要求返回其二进制数。输入的数当成十六进制数处理,如输入3A,返回111010,输入17返回10001。
 * 如果输入的字符串不合法则提示错误,当然,要区分是因为输入的字符串是不能组成十六进制数的错误还是输入的数超过了范围的错误。
 * 
 * 
 */
public class Test019 {

final static HashMap<Character, String> BINARY_CODE_MAP = new HashMap<Character, String>();

static {
BINARY_CODE_MAP.put('0', "0000");
BINARY_CODE_MAP.put('1', "0001");
BINARY_CODE_MAP.put('2', "0010");
BINARY_CODE_MAP.put('3', "0011");
BINARY_CODE_MAP.put('4', "0100");
BINARY_CODE_MAP.put('5', "0101");
BINARY_CODE_MAP.put('6', "0110");
BINARY_CODE_MAP.put('7', "0111");
BINARY_CODE_MAP.put('8', "1000");
BINARY_CODE_MAP.put('9', "1001");
BINARY_CODE_MAP.put('A', "1010");
BINARY_CODE_MAP.put('B', "1011");
BINARY_CODE_MAP.put('C', "1100");
BINARY_CODE_MAP.put('D', "1101");
BINARY_CODE_MAP.put('E', "1110");
BINARY_CODE_MAP.put('F', "1111");
BINARY_CODE_MAP.put('a', "1010");
BINARY_CODE_MAP.put('b', "1011");
BINARY_CODE_MAP.put('c', "1100");
BINARY_CODE_MAP.put('d', "1101");
BINARY_CODE_MAP.put('e', "1110");
BINARY_CODE_MAP.put('f', "1111");
}


/**
 * 把字符串转化成2进制数,有效长度31位。
 * @param numStr 源字符串
 * @return 与源字符串对应的2进制数,字符串不合法则提示是不能组成十六进制数的错误还是输入的数超过了范围的错误
 */
static String fromIntegerToBinary(String numStr) {
return toBinary(numStr, 31);
}

/**
 * 把字符串转化成2进制数。
 * @param numStr 源字符串
 * @param range 2进制数有效长度
 * @return 与源字符串对应的2进制数,字符串不合法则提示是不能组成十六进制数的错误还是输入的数超过了范围的错误
 */
private static String toBinary(String numStr,int range) {
if(numStr == null || numStr.isEmpty()) {
return numStr;
}
char[] arr = numStr.toCharArray();
StringBuilder sb = new StringBuilder();
for (char c : arr) {
if(BINARY_CODE_MAP.containsKey(c)) {
sb.append(BINARY_CODE_MAP.get(c));
} else {
return "illegal char " + c;
}
}
//格式化输出字符串
String result = sb.toString();
if(!result.contains("1")) {
//全0
result = "0";
} else {
//去掉多余的0
result = result.substring(result.indexOf("1"));
}
//超过范围报错
if(result.length() > range) {
return "out of range size:" + result.length();
}
return result;
}

public static void main(String[] args) {
System.out.println(fromIntegerToBinary("0"));
System.out.println(fromIntegerToBinary("00000000"));
System.out.println(fromIntegerToBinary("3A"));
System.out.println(fromIntegerToBinary("017"));
System.out.println(fromIntegerToBinary("7FFFFFFF"));
System.out.println(fromIntegerToBinary("80000000"));
System.out.println(fromIntegerToBinary("dfg"));
System.out.println(fromIntegerToBinary("123呵呵12a"));
}
}




引用 19 楼 SmallYamateh 的回复:
Quote: 引用 10 楼 ifvlr 的回复:

Quote: 引用 5 楼 SmallYamateh 的回复:

用正则是必然的,但用Integer.parseInt(str,16); 函数,这道题立马就0分了;面试过程中(一定要理解出题者的意图,不能盲目的调用库函数,包括sort、binarySearch等等,不然就等着被pass),进制转换没有捷径,循环+栈是唯一的办法

恩,您说的很对。您可以写下代码我参考下不?


public class Parse {

/**
 * output:10101011110101
 */
public static void main(String[] args) {
parse16To2("2AF5");
}
/**
把任意一位16进制数字转换为2进制
由于0转换为0000、F转换为1111,写死了4位,可以不用stack
 */
private static String parseOne(int k){
int[] array=new int[4];
int i=3;
while(k>0){
array[i]=k%2;
k/=2;
i--;
}
String str="";
for(i=0;i<=3;i++){
str+=array[i];
}
return str;

}
/**
 * 遍历str 
 *     判断这一位是数字还是字母,并把这一位转换为2进制
 *     (请在面试时牢记A的AscII码为65,0的AscII码为48,a的AscII码为97)
 * 最后,去掉前面的0
 */
public static void parse16To2(String str){
if(!str.matches("[\\dA-F]{1,8}")){
System.out.println("不符合!");
}else{
String total="";
char c=0;
int k=0;
int i=0;
for(;i<str.length();i++){
c=str.charAt(i);
if(c>='A'&&c<='F'){
k=c-55;
}else{
k=c-'0';
}
total+=parseOne(k);
}
for(i=0;i<total.length();i++){
if(total.charAt(i)=='1'){
break;
}
}
System.out.println(total.substring(i));
}
}
}


不好意思,许久未登录CSDN了,今天才来回复。顺便结贴了。
仔细看了两位的代码,受益良多,想请问一下算法这个东西该如何才能提高呢?
补充:Java ,  Java SE
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,