leetcode刷面试题(面试题05合集)

面试题 05.01. 插入

插入。给定两个32位的整数N与M,以及表示比特位置的i与j。编写一种方法,将M插入N,使得M从N的第j位开始,到第i位结束。假定从j位到i位足以容纳M,也即若M = 10 011,那么j和i之间至少可容纳5个位。例如,不可能出现j = 3和i = 2的情况,因为第3位和第2位之间放不下M。

示例1:
输入:N = 10000000000, M = 10011, i = 2, j = 6
输出:N = 10001001100

示例2:
输入: N = 0, M = 11111, i = 0, j = 4
输出:N = 11111

答:这道题给了我一个知识,就是java中int的左移,不是直接左移,而是对32位取余之后左移。比如1<<32=1<<0=1;而不是我想的是0;
本题思路:
例如实例1:
10000000000先和
11110000011进行&运算,再和
1001100进行|运算。
即把填入部分先清空,在填充

//判断j>=31的,就是我想要的左移和java中不一致,我要的左移32之后,肯定为0。
public int insertBits(int N, int M, int i, int j) {
    int k = j >= 31 ? ((1 << i) - 1) : (((~0) << (j + 1)) | ((1 << i) - 1));
    return (N & k) | (M << i);
}

面试题 05.02. 二进制数转字符串
二进制数转字符串。给定一个介于0和1之间的实数(如0.72),类型为double,打印它的二进制表达式。如果该数字无法精确地用32位以内的二进制表示,则打印“ERROR”。

示例1:
输入:0.625
输出:“0.101”

示例2:
输入:0.1
输出:“ERROR”
提示:0.1无法被二进制准确表示

提示:
32位包括输出中的"0."这两位

public String printBin(double num) {
    if (num == 0) {
        return num + "";
    }
    if (num < 0 || num >= 1) {
        return "ERROR";
    }
    //这么写不会通过,但是我认为是正确的。
	//int length = 32;这么写会通过,但是是错误的,因为明显是利用了double的精确度不够
    int length = (num + "").length();
    StringBuffer sb = new StringBuffer(length);
    sb.append("0.");
    int k = 0;
    while (num != 0 && (++k) <= length) {
        num *= 2;
        sb.append(num >= 1 ? "1" : "0");
        num = num % 1;
    }
    if (num == 0) {
        return sb.toString();
    }
    return "ERROR";
}

面试题 05.03. 翻转数位
给定一个32位整数 num,你可以将一个数位从0变为1。请编写一个程序,找出你能够获得的最长的一串1的长度。

示例 1:
输入: num = 1775(110111011112)
输出: 8

示例 2:
输入: num = 7(01112)
输出: 4

public int reverseBits(int num) {
    //不带翻转的长度
    int newLen = 0;
    //带一次翻转的长度
    int oldLen = 0;
    int lastOne = -3;
    int ans = 0;
    for (int i = 0; i < 32; i++) {
        if ((num & (1 << i)) == 0) {
            oldLen = newLen;
            oldLen++;
            newLen = 0;
        } else {
            newLen++;
            oldLen++;
            if (newLen == 1 && i - lastOne != 2) {
                oldLen = newLen;
            }
            lastOne = i;
        }
        ans = Math.max(ans, oldLen);
    }
    return ans;
}

面试题 05.04. 下一个数

下一个数。给定一个正整数,找出与其二进制表达式中1的个数相同且大小最接近的那两个数(一个略大,一个略小)。

示例1:
输入:num = 2(或者0b10)
输出:[4, 1] 或者([0b100, 0b1])

示例2:
输入:num = 1
输出:[2, -1]

提示:
num的范围在[1, 2147483647]之间;
如果找不到前一个或者后一个满足条件的正数,那么输出 -1。

public int[] findClosedNumbers(int num) {
    int bigger = -1;
    int letter = -1;
    int n = num;
    boolean getOne = false;
    int oneNum = 0;
    //找到最小的01,改成10然后把排在后面的1全部安排在最后,这样才会最小
    for (int i = 0; i < 31; i++) {
        if ((n & (1 << i)) > 0) {
            n -= 1 << i;
            oneNum++;
            getOne = true;
        } else {
            if (getOne) {
                n += 1 << i;
                n += (1 << (oneNum - 1)) - 1;
                bigger = n;
                break;
            }
        }
    }
    n = num;
    boolean getZero = false;
    int zeroNum = 0;
    //找到最小的10,改成01然后把排在后面的1全部安排在前,这样才会最大
    for (int i = 0; i < 31; i++) {
        if ((n & (1 << i)) == 0) {
            zeroNum++;
            getZero = true;
        } else {
            n -= 1 << i;
            if (getZero) {
                n += ((1 << (i + 1 - zeroNum)) - 1) << (zeroNum - 1);
                letter = n;
                break;
            }
        }
    }
    return new int[]{bigger, letter};
}

面试题 05.06. 整数转换

整数转换。编写一个函数,确定需要改变几个位才能将整数A转成整数B。

示例1:
输入:A = 29 (或者0b11101), B = 15(或者0b01111)
输出:2

示例2:
输入:A = 1,B = 2
输出:2

提示:
A,B范围在[-2147483648, 2147483647]之间

答:>>>和>>的区别是,前者无符号
-1>>1=-1
-1>>>1=2147483647

public int convertInteger(int A, int B) {
    int c = A ^ B;
    int ans = 0;
    while (c != 0) {
        ans += c & 1;
        c = c >>> 1;
    }
    return ans;
}

面试题 05.07. 配对交换
配对交换。编写程序,交换某个整数的奇数位和偶数位,尽量使用较少的指令(也就是说,位0与位1交换,位2与位3交换,以此类推)。

示例1:
输入:num = 2(或者0b10)
输出 1 (或者 0b01)

示例2:
输入:num = 3
输出:3

提示:
num的范围在[0, 2^30 - 1]之间,不会发生整数溢出。

public int exchangeBits(int num) {
    int ans = 0;
    int k = 0;
    while (num > 0) {
        int v = num % 4;
        num = num / 4;
        if (v == 0 || v == 3) {
            ans += v << (2 * (k++));
        }
        if (v == 1) {
            ans += 2 << (2 * (k++));
        }
        if (v == 2) {
            ans += 1 << (2 * (k++));
        }
    }
    return ans;
}

面试题 05.08. 绘制直线
绘制直线。有个单色屏幕存储在一个一维数组中,使得32个连续像素可以存放在一个 int 里。屏幕宽度为w,且w可被32整除(即一个 int 不会分布在两行上),屏幕高度可由数组长度及屏幕宽度推算得出。请实现一个函数,绘制从点(x1, y)到点(x2, y)的水平线。

给出数组的长度 length,宽度 w(以比特为单位)、直线开始位置 x1(比特为单位)、直线结束位置 x2(比特为单位)、直线所在行数 y。返回绘制过后的数组。

示例1:

输入:length = 1, w = 32, x1 = 30, x2 = 31, y = 0
输出:[3]
说明:在第0行的第30位到第31为画一条直线,屏幕表示为[0b000000000000000000000000000000011]

示例2:

输入:length = 3, w = 96, x1 = 0, x2 = 95, y = 0
输出:[-1, -1, -1]

public int[] drawLine(int length, int w, int x1, int x2, int y) {
    int wn = w / 32;
    int[] ans = new int[length];
    for (int i = y * wn; i <= length; i++) {
        if (x1 >= 32) {
            x1 -= 32;
            x2 -= 32;
            continue;
        }
        if (x2 <= 31) {
            ans[i] = getAns(x1, x2);
            break;
        } else {
            ans[i] = getAns(x1, 31);
            x1 = 0;
            x2 -= 32;
        }
    }
    return ans;
}

private int getAns(int start, int end) {
    int len = end - start + 1;
    if (len == 32) {
        return -1;
    }
    return ((1 << len) - 1) << (31 - end);
}
发布了148 篇原创文章 · 获赞 18 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_33321609/article/details/104597613