几个面试常考的问题

前言

最近正在紧锣旗鼓的准备面试,期间遇到了许多好精巧的算法问题。于是大致实现了下,做个笔记。

判断一个数是否为2的幂

这个题有两种解法,一个是常规的,思路如下:

不断的将这个数除2,求得余数。当余数为1的时候,判断当前除数和2的大小关系,如果大于2,则说明此数不是2的幂,如果小于2则说明此数为2的幂。

另外一个方法就比较hack了,思路如下:

如果一个数为2的幂,则二进制首位必为1,其余位为0.
将这个数减一,得到的数与该数相与,结果为0则说明此数为2的幂数,否则不是。

代码可以大致写成这样。

public boolean isPowerOf2(int number) {
        return ((number-1)&number)==0?true:false;
}

这样是不是既高效又简便呢?

不使用if, while, for,switch,goto等关键字实现100行代码打印出1000个helloworld

按照常规理解,这是不可能的了。那么要怎么实现呢?

我个人倒是觉得绕开这些关键字倒是个不错的方法,比如使用更底层的语言。高级语言之下不是还有诸如汇编语言,机器语言这些的嘛,虽然可读性会很差,但是也不失为一个好办法。

但是非得让用某一个语言来实现,要怎么做呢?

答案之一就是用递归来实现。且看下面的代码。

# coding: utf8
number = 0

def p1():
    global number 
    number += 1
    print "Hello World"

def p2():
    p1()
    p1()

def p3():
    p2()
    p2()
    p2()

def p4():
    p3()
    p3()
    p3()
    p3()

def p5():
    p4()
    p4()
    p4()
    p4()
    p4()

def p6():
    p5()
    p5()
    p5()
    p5()
    p5()
    p5()

def p7():
    p6()
    p6()
    p6()
    p6()
    p6()
    p6()
    p6()
if __name__ == '__main__':
    p7()
    print "共执行了{}次,得到了{}个Hello World!".format(number, number)

得到的结果呢?


获取结果

这样,使用递归的方式便可以实现100行以内的代码获取到大于1000行Hello World!的输出了。

不使用+实现一个加法函数

这就有点难为人了,反正我是怎么想也没想出来。后来参考网上的思路,使用模拟与数字电路的方式可以实现。

原理就是:

两个数先异或运算
两个数相与的结果左移一位
递归判断,获取返回结果

使用代码实现起来可能如下:

public static int addWithoutOperators(int number1, int number2) {
        // 如果有一个数为0,则直接返回另一个数
        if(number2 == 0)
            return number1;
        if(number1 == 0)
            return number2;
        // 先异或运算
        int sum = number1 ^ number2;
        //求出进位,这时对于01,10,00都是不产生进位的,只有11才会产生进位
        int carry = ( number1 & number2 ) << 1;
        return addWithoutOperators(sum, carry);
    }

运算测试


加法运算结果

不使用-实现减法函数

两数相减,就是一个数加上另一个数的相反数呗。我们常规就是这么理解的,那么怎样才能获取一个数的相反数呢?

求相反数很简单,直接取反加一即可。也就是


求正数的相反数

负数同样适用。

那么利用这一点,就可以轻松的实现减法函数了。

public static int subtractWithoutOperators(int number1, int number2) {
        if(number1 == number2) 
            return 0;
        int reverse = addWithoutOperators(~number2, 1);
        return addWithoutOperators(number1, reverse);
    }

运算结果如下:


实现减法函数的结果

除此之外,还有一个直接操作二进制的方式,

int Subtract(int a, int b)
{
    while (b != 0) 
    {
        int sameBits = a & b;
        a ^= sameBits;
        b ^= sameBits;
        a |= b;
        b <<= 1;
    }

    return a;
}

还有其他的乘除运算的实现方法,详情请参考下面的链接:
http://www.cppblog.com/qingbizhu/archive/2012/03/30/168148.html

实现BMP算法

求子字符串在字符串中第一次出现的位置,这倒是一个挺简单的实现,至于那个改进版的,我还不太理解,就不写了。

/**
 * @Date 2017年3月5日
 *
 * @author 郭  璞
 *
 */
package interview;

/**
 * @author 郭 璞
 *
 *         关于字符串中字串位置的查找相关的几个实现
 *
 */
public class StringPiexl {

    public static void main(String[] args) {
        String original = "hello world!";
        String substr = "llo";

        StringPiexl piexl = new StringPiexl();
        System.out.println(piexl.bmp(original, substr));

    }

    public int bmp(String original, String substr) {
        if (original.length() < substr.length())
            return -1;

        char[] originals = original.toCharArray();
        char[] substrs = substr.toCharArray();

        for (int outter = 0; outter < originals.length - substrs.length; outter++) {

            for (int inner = 0; inner < substrs.length;) {
                if (originals[outter++] == substrs[inner++]) {
                    if (inner == substrs.length - 1) {
                        return outter - inner;
                    }
                } else {
                    outter = outter - inner;
                    break;
                }
            }
        }
        return -1;

    }

}

运算结果如下:

2

打靶问题

打靶10次,得到90分的方式有几种?
像这种问题还有很多,什么鸡兔同笼啊,百钱白鸡啊,都是类似的。

一方面我们可以采用枚举法来暴力破解,另一方面就只能采用递归。两者各有利弊吧,今天的这个打靶问题,我就用递归来实现一下。

/**
 * @Date 2017年3月3日
 *
 * @author 郭  璞
 *
 */
package interview;

/**
 * @author 郭 璞
 * 
 *         打靶的递归实现
 *
 */
public class ShootTest {

    /**
     * 设置为11位的数组是因为下边按1开始到10来使用!
     */
    public static int[] record = new int[11];
    public static int totalMethods = 0;

    public static void main(String[] args) {
        shoot(90, 10);
        System.out.println("共有的可能的解法为:" + totalMethods);
    }

    public static void shoot(int score, int number) {
        // 此处score > number*10 可用90替代,但是根据不同的要求还需要硬编码替换!
        if (score < 0 || score > number * 10) {
            return;
        }
        if (number == 1) {
            record[10-number] = score;
            print(record);
            totalMethods ++;
        }
        for (int index = 0; index <= 10; index++) {
            record[10-number] = index;
            shoot(score - index, number - 1);
        }
    }

    /**
     * @param record2
     * 打印的时候是按照第一枪到第number枪来计算的,因为要符合人类世界的从1开始的计算。
     */
    private static void print(int[] record2) {
        for (int index = 1; index < record2.length; index++) {
            System.out.print("\t" + record2[index]);
        }
        System.out.println("-----------------------------------");

    }

}

运算结果:


打靶问题结果

总结

好像面试的时候好多问题都是为了问题而问题,这样的考察我觉得不是很好,毕竟实际中不会有这么偏门的问题吧。但是为了更好的充实自己,了解一下还是不错的。

这篇文章就先这样啦,以后再遇到这类问题,也许会更新一下,也会会另写一篇。

如果看到了此文的你有类似的好的面试题的解法,也可以在下面留言评论,让我们一起进步吧。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • 归去来兮。 1.1 说明 本篇为《挑战程序设计竞赛(第2版)》[http://www.ituring.com.cn...
    尤汐Yogy阅读 14,270评论 0 160
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,560评论 18 399
  • 索引的实现方式 1、B+树我们经常听到B+树就是这个概念,用这个树的目的和红黑树差不多,也是为了尽量保持树的平衡,...
    大黄大黄大黄阅读 2,365评论 1 14
  • 生活可以平淡如水,但也需色彩点缀。 我可以抱着猫咪睡觉,却容不得狗狗在我面前嘚瑟。 我喜欢听怀旧风,民谣,却不喜欢...
    泡泡染阅读 511评论 16 7
  • 在某一瞬间,想起红楼梦,美好的姑娘和讨厌的婆子,于是曹选择写死姑娘……似乎回不去了哈,我在心里无数遍地跟自己说。 ...
    宁波小娘在杭州阅读 527评论 0 1