【澳门葡京备用网址】面试题解答,教孩子学Scratch编制程序之0x捌

近1个月直接在写作业,空闲时间刷刷leetcode,刷题进度中相见了一道比较风趣的难点,和大家享受。

leetcode笔记:Divide Two Integers

1. 难点叙述

Divide two integers without using multiplication, division and mod
operator.

If it is overflow, return MAX_INT.

2. 题目分析

题材的意趣简单明了,正是需求不行使乘法、除法和取余mod,输入多个整数,输出除法操作的结果。

出来乘除法,剩下的只有加减法和位运算,那是轻巧想到的,而直接使用减法,对被除数逐次减去除数大小的值,记录被减次数,断定是足以得出和除法操作一样的结果,但该格局相比较傻瓜,且会晚点,时间复杂度为O(n)。

使用位运算能够达成O(logn)的复杂度,但要一步想到具体操作却也不那么轻巧,首先,咱们精通其余2个平头都足以代表成以贰的幂为底的一组基的线性组合,即num = flag0 * 2^0 + flag1 * 2^1 + flag2 * 2^2 + ... + flagn * 2^n
其中,flag0, flag1, flag2, ..., flagn 取值为0 & 1

基于以上实际,假使令:dividend / divisor = num,则有:

dividend = divisor * num = divisor * (flag0 * 2^0 + flag1 * 2^1 + flag2 * 2^2 + ... + flagn * 2^n)

对此除数,使用移动操作<<使其每一次翻倍,从而减弱减法求商的次数。以下是手续:

当被除数大于除数时,对除数乘二(代码中使用变量step用于记录每一回除数乘2),直到step大于被除数甘休。记录移位操作的次数i。
要是被除数大于除数,那么被除数减去step。直到被除数小于除数。保存结果。
输出结果result。

注:

byte:128~127 (1Byte)
short :32768~32767 (2Bytes)
int:-2147483648~2147483647 (4Bytes)
long:-9223372036854774808~9223372036854774807 (8Bytes)

3. 示例代码

class Solution {
public:
    int divide(int dividend, int divisor) {
        if (dividend == 0 || divisor == 0) return 0;
        if (dividend == INT_MIN && divisor == -1) return INT_MAX; // 溢出
        bool negative = (dividend > 0 && divisor < 0) || (dividend < 0 && divisor > 0);
        long positiveDividend = abs(long(dividend));
        long positiveDivisor = abs(long(divisor));
        long result = 0;

        while (positiveDividend >= positiveDivisor) // 被除数大于除数
        {
            long step = positiveDivisor;
            for (int i = 0; positiveDividend >= step; ++i, step <<= 1)
            {
                positiveDividend = positiveDividend - step;
                result += 1 << i;
            }
        }
        return negative ? -result : result;
    }
};

四. 小结

利用位运算来消除此类主题材料,是挺轻松想到的,可是具体怎么样操作又是别的二回事。

Two Integers 1. 标题叙述
Divide two integers without using multiplication, division and mod
operator. If it is overflow, return MAX_INT. 2. 标题分析…

基础知识

带余数除法涉及下边是计算公式和定义:

被除数 / 除数 = 商......余数
  • 被除数 dividend :除数 * 商 + 余数
  • 除数 divisor :(被除数 – 余数)/ 商
  • 商 quotient :(被除数 – 余数)/ 除数
  • 余数 remainder :被除数 – 除数 * 商
    总结公式中涉嫌多少个数字,知道了内部的一个,能够求出此外一个。
    除此以外1个器重的关系是:余数要比除数小

目录

 

Scratch编程

在微型计算机语言中,平时用 /
来代表“除以”得到,在不能够整除的事态下暗中认可会获得一个小数(关于整数和浮点数今后再讲);
用%来来总括余数【澳门葡京备用网址】面试题解答,教孩子学Scratch编制程序之0x捌。。
在scratch中也是要分头总计出两局地的。
先定义出大家要求的三个变量

  1. 计算商
    先是选用运算中的除法“/”
这样还不行,在不能整除的情况下得到的是小数,所以还需要使用**向下取整**取出整数部分  

贰.计量余数
余数的计量就一贯动用运算中的余数总结就可以。

八个壹体化的scratch程序:

戏台和剧中人物

scratch猫做除法题

  • 各种简要介绍
  • 不用*和/总括整数除法
  • 二五匹马找寻前5名
  • 估量题样例

题目叙述:

总结

此次学习了包括余数的除法总计。并且选用scratch中的block完毕一个除法总括。学习了那些现在,我们能够试①试:让scratch猫出除法题,然后大家应对,scratch猫再判定回答是还是不是正确。

上一篇:教孩子学Scratch编制程序之0x7:星型与纺锤形
下一篇:教孩子学Scratch编程之0x拾:圣诞欢畅!关于scratch.mit.edu

 

给定七个整数,被除数 dividend 和除数 divisor。将两数相除,要求不应用乘法、除法和
mod 运算符。重返被除数 dividend 除以除数 divisor 得到的商。

层层简单介绍:

示例 1:

  《算法设计手册》(The Algorithm Design
马努al)是本相比较优异的算法书了。假如说《算法导论》偏向于数学,那么《算法设计手册》更偏向于工程应用(至于《Computer程序设计方法》,近期自家是没时间通读,只是有时当工具书查查,就不提了)。前者的课后题中的面试题部分挺潮的,要是在google上寻找一下,发掘多数都以名企考过的,大概是因为第壹版问世时间比较近的缘由?作者非常的小相信是作者自身出的下一场被大厂家拿去面试的,而是小编引用的考过的面试题。有了这壹层筛选,这个面试题品质有保障啊。

输入: dividend = 10, divisor = 3
输出: 3

  由于看的是英文版,大多数题都以本身翻译过来的,个人英文水准有限,有的不佳精通的地点尽量参照相关解答来驾驭,并发问了在外国留学的心上人,恐怕仍不怎么措辞不标准或有误的地点,伏乞谅解并应接提出。同时,有的难题用到的可比偏僻的文化可能会和正文有涉及,这种景况会鲜明注脚。

示例 2:

  纵然官方网站上有个wiki
answer提供了超越45%答案,可是有的不很适量,笔者写的和整理的都以相比较好的解答。

输入: dividend = 7, divisor = -3
输出: -2

  原版的书文者的wiki
answer页面早就失效。

说明:

  另附上在线校订表:

  • 被除数和除数均为
    32 位有标记整数。
  • 除数不为 0。
  • 假定大家的条件只可以存储32 位有暗记整数,其数值范围是 [澳门葡京备用网址 ,−2**31,  2**31 −
    1]。本题中,如若除法结果溢出,则赶回 2**31 − 1。

 

 

第1章:

首先感应是那道题还是挺简单的,用减法达成除法不就好了,python刷题达成以致能够直接使用range()来兑现除法,须求专注的点如下:

1-28

一.提早决断结果的正负号

  不用*和/计算整数除法。请寻找最快的秘籍。

2.结果在[-2**31,2**31-1]中,要看清结果是还是不是移除

解答:

叁.采纳range()来计量除法时,1旦除法能够整除大家要对结果+一,因为len(range(叁,七,3))的结果是2,len(range(3,玖,三))的结果也是贰

  即便初叶化三个计数变量,每当被除数减去除数的一遍就自增一直到被除数小于除数这些暴力解法可行,但明显不快。那是wiki
answer答案,但它在数不尽动静下都悲哀,比如100/一。其实行的次数正好和相除的结果一律,用m表示除数,n表示被除数,时间复杂度是O(m/n)。

 

// Note: This only works for positive values!
int divide(int numerator, int denominator) {
  int quotient = 0;

  while(numerator >= denominator) {
      numerator -= denominator;
      quotient++;
  }
  return quotient;
}

代码如下:

   下边看看另一种解法。

class Solution(object):
    def divide(self, dividend, divisor):
        """
        :type dividend: int
        :type divisor: int
        :rtype: int
        """
        below = 1
        if dividend < 0 < divisor or divisor < 0 < dividend:
            below = -1

        dividend,  divisor = abs(dividend),  abs(divisor)
        if dividend < divisor:
            return 0
        elif divisor == 1:
            result = dividend * below
            if result >= 2**31-1:
                return 2**31-1
            return result


        result = len(range(divisor, dividend, divisor))
        if (result+1) * divisor == dividend:
            result += 1 
        return result * below

  一般限制使用*和/时,很轻易思量使用位移运算来代表,因为对于无符号数,左移1位(在不溢出时)也就是乘以2,右移一位相当于除以二。借使在纸上海展览中心开掉法的笔算,是只用到了乘法和减法的。不过一般的10进制整数除法和位运算有如何关系呢?为了将两边建立联系,必须把10进制数转化成二进制数,观望除法的展开状态来找规律。比如十0/7,写成2进制来拓展笔算,总括进程如下图:

友善写了成都百货上千case来测试都以没难题的,代码提交到leetcode,正剧了。。。内存错误,看来是内部存款和储蓄器超了。难点出在中央语句len(range(divisor,
dividend,
divisor))上,怎么既能有限扶助近日代码的简洁性又能降低内部存款和储蓄器使用啊。小编化解办法是行使xrange取代range,一句话来说range重回的靶子是个list,会开荒3个相当的大的半空中,而xrange不一样,重返的是生成器,所以对内部存款和储蓄器的施用获得了间接的优化。重新提交,果然通过了。

澳门葡京备用网址 1

 

  那样就简单了,从那一个姿势能够看到,2进制除法笔算只关乎了减法和带有的移动与大小相比较,原先的乘法已经被移位所代替。由此,具体的编码,便是把用笔算除法的经过转化成代码而已。

最终代码如下:

  但是,一般思考选择除法的条件,必然要思量除数是或不是为0。除数为0时以此除法是不法的,不可能一而再开始展览,需求报错。

class Solution(object):
    def divide(self, dividend, divisor):
        """
        :type dividend: int
        :type divisor: int
        :rtype: int
        """
        below = 1
        if dividend < 0 < divisor or divisor < 0 < dividend:
            below = -1

        dividend,  divisor = abs(dividend),  abs(divisor)
        if dividend < divisor:
            return 0
        elif divisor == 1:
            result = dividend * below
            if result >= 2**31-1:
                return 2**31-1
            return result


        result = len(xrange(divisor, dividend, divisor))
        if (result+1) * divisor == dividend:
            result += 1 
        return result * below

  既然涉及了编码,假如利用C语言来落成,要专注的是:在C标准中,带符号数右移的结果在C语言里是完成相关的,具体结果取决于落成,而不必然是用符号位补、用一补或许用0补最高位。为了避免那么些陷阱,提议先分明结果——也等于商的标记,然后把被除数和除数都转载为无符号数,那样位移时就不会出错。

 

  然而,那又关联了有带符号数与无符号数的转换,它们2者的象征范围的难点是例外的。幸好被除数和除数从带符号数转化为无符号数时并不会丢掉数据,而且商的相对值必然小于被除数的相对值(因为除数是整数,为0时报错,大于等于壹时才继续打开),那时把商转化回带符号数时也不会丢掉数据,能够放心的开始展览。可是这点最棒在面试时告诉面试官你曾经注意到了这几个标题,料定会为你的影像加分。

目的在于对我们持有帮忙~

 

int division(int m,int n) {
    //calculate m/n without * and /
    unsigned int rest,divisor, op,result = 0;
    int flag;
    int bits = 0;
    //bits用于记录商的1在哪一位
    assert(n!=0);
    if((m<0 && n>0) || ( m>0 && n<0 ))
        flag = -1;
    else
        flag = 1;
    rest = m>0?m:-m;
    divisor = n>0?n:-n;
    if(rest < divisor)
        return 0;

    op = divisor;

    /*            2013.8.30           */
    /*经过博客园园友infinityu的提醒重写 */
    while(op<=rest) {
        bits++; 
        op=op<<1;
    }
    op=op>>1;
    bits--;

    while(op>=divisor) {
        if(rest>=op) {
            rest-=op;
            result += 1<<bits;
        }
        op = op>>1;
        bits--;

    }
    /*      重写部分结束         */

    return flag * result;
}

 

 

 

  由于供给把被除数转化为二进制举办测算,最多做了其2进制表示位数1八遍的减法,因而对于被除数m,算法复杂度为O(logm)。

  稍作修改,把最终的小于除数divisor的result抽取正是余数,那样就能把除法运算改写为取模运算%了。要是把参数表修改为传送结果地址,同时获得商和余数也是足以的。

  可知,那一道面试题考到了算法优化、除法除数为0以此广阔错误、将除法从10进制引申到二进制、二进制的位运算、语言特色中的无符号数和带符号数的运动、无符号数和带符号数的并行转变,你还能更进一步追究算法复杂度、以及算法的扩大性,确实很能观测被面试者对算法的精晓意况。

  p.s.经过园友infinityu的提醒,发掘源代码中有bug,重写之后已经对一~一千中间具备整数相互相除的测试。为了便于记录商的一相应在哪一位,使用变量bits来提醒。

 

1-29:

  2五匹马,三回最多伍匹马比赛,如何用最少的比赛次数找到最快的前3匹马?(即使全部马的速度在每场比赛的宣布都同一且各匹马之间区别样,比赛时惊慌失措记录具体每匹马跑完全程的大运)

解答:

  老调重弹的标题,关键是寻觅每便的不易候选以及尽大概利用上次竞赛得到的新闻。

  先分5组A、B、C、D、E,组内比赛,若是A一为A组第二。一共伍场。

  将A1~E一进展较量,不要紧设第二是A1,那么最快就是A一。

  第叁快不得不在A二、B一~E第11中学出现。同时,这时知道了B一~E一的快慢,无妨B1>C一>D1>E一,那样D一、E1以及任何D组和E组可以被铲除出第一和第壹的候选。同时,C贰决然不可能是第二快。那时候选为A贰、A三、B壹、B2、C一,比赛3回,前两名即为第二和第贰。

  (注意:那里分析时不曾”足够”利用具有已知音讯。更进一步行使已知消息的点子请看扩充一。)

  综上,一共竞技了5遍。

 

扩展1:

  6四匹马,每一趟最多八匹竞技,要求用最少场次获得前四名。其余规格同上题。

 解答:

  遵照上题的解析方法并不能够收获最少比赛次数,上面看看怎么样丰盛利用已知音信来到达至少竞赛次数。

  首先分8组A~H决出各组顺序,共需八场,并且组内顺序排列为A1>A二>…>A八。

  第一名在A一~H第11中学决出,不要紧设为A1>B一>…>H一,要求1场比赛。

  此时第叁名只可以是A二和B一个中之一(分化于上题分析,C1~H1实际上可以直接放弃),但决出第一名只用三个赛道太浪费了。为此进一步分析,即使A二>B一,那么第三名只可以是A三、B一之一;纵然B1>A二,那么第2名只好是A二、B2、C一。那三种状态都只提到5匹马仍旧不满8匹。用那种思路张开全面剖析,表示为树状并把叶子处必要比较的马的数码举办标注:

  角逐第2名时A2>B1

    第3名候选A3,B1

    角逐第3名时A3>B1

      第4名候选A4,B1    
————(A2,A3,A4,B1)

    角逐第3名时A3<B1

      第4名候选A3,B2,C1   
————(A2,A3,B1,C1)

  角逐第2名时A2<B1

    第3名候选A2,B2,C1

    角逐第3名时A2>B2>C1

      第4名候选B2,A3     ————(A2,A3,B1,B2,C1)

    角逐第3名时A2>C1>B2

      第4名候选C1,A3     ————(A2,A3,B1,B2,C1)

    角逐第3名时B2>A2>C1

      第4名候选A2,B3     ————(A2,B1,B2,B3,C1)

    角逐第3名时B2>C1>A2

      第4名候选B3,C1     ————(A2,B1,B2,B3,C1)

    角逐第3名时C1>A2>B2

      第4名候选A2,C2,D1    ————(A2,B1,B2,C1,C2,D1)

    角逐第3名时C1>B2>A2

      第4名候选C2,B2,D1    ————(A2,B1,B2,C1,C2,D1)

  可知,即使能够3次交锋收获A二,A三,福克斯,B壹,B贰,B三,C1,C贰,D一的欧洲经济共同体排列次序才干领略前2~肆名。很惋惜一共是九匹马,不大概一场交锋一定获得结果。那么求最优方案,正是将以上各分支出现最晚出现的马去掉,即C二或D1,举办一场较量。运气好的话那壹轮能够决出前2~四,1共比赛十轮,运气不佳的话还亟需加赛一轮。而去掉C二或D1能够确认保证只比赛十轮的可能率最大。

 

扩展2:

  25匹马,5个赛道,决出前5。

解答:

  分析和“扩大一”类似,留给读者自身做到。假如想核查答案,能够查阅:

 

=============================================================

  1-30~1.3四是多少个测度题,当年google确实考过在那之中的主题材料。可是那里不做解答了。

  关于猜想标题标思绪和平消除法,能够参照《编制程序珠玑》《编制程序珠玑(续)》和本人写的连带文章:[珠玑之椟]预计的采纳与Little定律

  另外,“决不再去算壹辆校车上可以装多少个高尔夫球了。”因为
Google已确认,那一个用来测试求职者的智慧题/脑筋急转弯(环球有稍许钢琴调音师?为啥井盖是圆的?),就不或然预测出求职者是不是会形成一个人好职工。
“未来相信更平日方法去面试潜在职员和工人”。连带链接

1.30

  世界上有多少个钢琴调音师?

1.31

  U.S.A.有些许个加油站?

1.32

  曲棍篮球场上的雪有多种?

1.33

  美利坚联邦合众国公路累计有多少长度?

1.34

  平均来看,你查看1本曼哈顿电话簿时,你需求自由翻开多少次才干找到二个加以的名字?

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website