20190403微软面试-虐惨

首先第一轮面试:

自我介绍+项目介绍+实习的任务

代码:现有一个全排列A,根据B[0] = 0,B[i] = A[B[i-1]]的方式构造B;并判断B是否是一个全排列?

方法一:直接先遍历生成B,再set(B);先判断len(B) < len(A)成立与否,如果成立,直接返回False.如果不成立,就遍历B中元素是否都在A 中,如果不在的话,返回False;如果在的话,到最后返回true.

方法二:先遍历生成B,直接判断B[i] == 0(如果为0,就形成了回到了B[0]的闭环,就直接返回False; 如果不为0的话,到最后返回True.)

S = [0,1,2,3,4,5,6,7,8]
# 方法一:
def find_permu1(A):
    In = 0
    B = [0] * len(A)
    for i in range(1,len(A)):
        B[0] = 0
        B[i] = A[B[i-1]] 
    B=set(B)
    if len(B) < len(A):
        return("False")
    else:
        for i in range(len(B)):
            if B[i] in A:
                In += 1
        if In == len(A):
            print("True")
        else:
            print("False")
# 调用:find_permu1(S)

# 方法二:
def find_permu(A):
    B = [0] * len(A)
    for i in range(1,len(A)):
        B[0] = 0
        B[i] = A[B[i-1]]
        if B[i] == 0:   # 判断是否形成一个环,且改环的起点和终点均是0
            return ("False")
    print("True") 
# 调用:find_permu(S)

第二轮被虐惨,主要考查了计算机各种知识,诸如:计算机组成原理,操作系统,数据结构。

1)自我介绍+进程+线程+项目+实习+梯度消失+CNN+LSTM+面向对象与面向过程+python是一种可解释性语言

2)假设p、p+2是孪生素数,证明p+1能被6整除(能被6整除,意味着需要被2和3整除)

3)马尔科夫模型(延伸:基于统计的算法)

4)编程: 现有一个二叉树,从上往下遍历,按照树的深度打印/排列数,同一深度的放在一起。

5)编程:现有一正数数组A = [1,2,3,4,1,3,1],S = 4,返回A中连续几个数的和等于S的连续数组合的情况数(遍历>O(n);不遍历:要求o(n))

6)编程:由rand7()生成rand10(),保证等概率的随机数生成:from 1/7  to 1/10.

1)进程+线程:

进程:进程就是一个应用程序在处理机上的一次执行过程,它是一个动态的概念,而线程是进程中的一部分,进程包含多个线程在运行。不同进程质相互独立的,一个进行崩了,另一个进程并不会受到影响。

线程:线程是指进程内的一个执行单元,也就是进程内的可调度实体。

与进程的区别:

1.地址空间:线程是进程内的一个执行单元;进程至少有一个线程;同一进程中的不同线程共享进程的地址空间。然而进程有着自己独立的地址空间;

2.资源拥有:进程是资源分配和拥有的单位,同一进程内的线程共享进程的资源;

3.线程是处理器调度的基本单位,但进程不是;

4.二者均可并发执行

进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。

进程与线程的区别:

简而言之,一个程序至少有一个进程,一个进程至少有一个线程;不同的进程的地址空间相互独立,相互之间不受影响。同一进程的不同线程之间是共用进程的地址空间的,相互之间影响,一个线程崩了,另一个线程也会崩;进程是分配和拥有资源的最小单元,线程是处理器调度的最小单元。

线程的划分尺度小于进程,使得多线程程序的并发性高。

进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大的提高了程序的运行效率。’

线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序的运行入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

进程具有一定独立功能的程序关于某个数据集上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。

线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位,线程自己基本上不拥有系统资源,只拥有一个点在运行中必不可少的资源(如程序计数器、一组寄存器和栈),但是它可与同属于一个进程的其他线程共享进程所拥有的全部资源

一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行。

2)面向对象和面向过程:

计算机语言可以归为面向过程语言和面向对象语言,那么到底什么是面向对象?什么是面向过程?

A:面向过程就是分析出解决问题所需要的步骤,然后用什么函数把这些步骤一步一步的实现,使用的时候一个一个依次调用就可以了;面向对象是把构成问题事务分成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某事物在整个解决问题的步骤的行为。

举例五子棋的例子来说明面向过程和面向对象的区别:

面向过程的设计思路就是首先分析问题的步骤:1.开始游戏,2.黑子先走,3.绘制画面,4.判断输赢,5.轮到白子,6.绘制画面,7.判断输赢,8.返回步骤2,9.输出最后结果。把上面每个步骤用不同的方法来实现。

面向对象的设计规则是从另外的思路来解决问题。整个五子棋可以分为1.黑白双方,这两方的行为是一模一样的;2.棋盘系统,负责绘制画面;3.规则系统,负责判断诸如犯规、输赢等。。第一类对象(玩家对象)负责接受用户输入,并告知第二类对象(棋盘对象)棋子布局的变化,棋盘对象接受到了棋子的变化就要负责在屏幕上面显示出这种变化,同时利用第三类对象(规则系统)来对棋局进行判定。

可以明显看出:

面向对象是以功能来划分问题的,而不是步骤。同样是绘制棋局,这样的行为在面向过程的设计中分散在了多个步骤中,很可能出现不同的绘制版本,因为通常设计人员会考虑到实际情况进行各种各样的简化。而面向对象的设计中,绘图只可能在棋盘对象

中出现,从而保证了绘图的统一。

举例:大象装进冰箱。

面向过程:
打开冰箱--》存储大象 --》关上冰箱
对于面向过程思想,强调的是过程(动作)。
语言:C。

面向对象:
对于面向对象思想,强调的是对象(实体)。
冰箱打开--》冰箱存储大象 --》冰箱关上
语言:C++、Java、C#
特点:1、面向对象就是一种常见的思想,符合人们的思考习惯。
2、面向对象的出现,将复杂的问题简单化。
3、面向对象的出现,让曾经在过程中的执行者,变成了对象的指挥者。
 

面向过程

概念:面向过程是一种以过程为中心的编程思想,它是一种基础的顺序的思维方式,面向对象方法的基础实现中也包含面向过程思想。

特性:模块化,流程化

优点:性能比面向对象的语言高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用的是面向过程开发,性能是最重要的因素

缺点:没有面向对象的语言易维护、易复用、易扩展。

面向对象

概念:面向对象是按人们认识客观世界的系统思维方式,采用基于对象(实体)的概念建立模型,模拟客观世界分析、设计、实现软件的办法。通过面向对象的理念使计算机软件系统能与现实世界中的系统一一对应。

特性:抽象、封装、继承、多态

优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特点,可以设计出低耦合的系统,使系统更加灵活,更加易于维护。

缺点:性能比面向过程低。

面向对象与面向过程具体而言,有如下几个方面的不同:
1、出发点不同
面向对象方法是用符合常规思维的方式来处理客观世界的问题,强调把问题域的要领直接映射到对象之间的接口上。而面向过程的方法则强调的则是过程的抽象化与模块化,它是以过程为中心构造或处理客观世界问题的。
2、层次逻辑关系不同
面向对象的方法则是用计算机逻辑来模拟客观世界中的物理存在的,以对象的集合类作为处理问题的单位,尽可能地使计算机世界向客观世界靠拢,以使问题的处理更清晰直接,面向对象方法是用类的层次结构来体现类之间的继承与发展。面向过程方法处理问题的基本单位是能清晰准确地表达过程的模块,用模块的层次结构概括模块或模块间的关系与功能,把客观世界的问题抽象成计算机可以处理的过程。
3、数据处理方式与控制程序方式不同
面向对象方法将数据与对应的代码封装成一个整体,原则上其他对象不能直接修改其数据,即对象的修改只能由自身的成员函数完成,控制程序方式上是通过“事件驱动”来激活和运行程序。而面向过程方法是直接通过程序来处理数据,处理完毕后即可显示处理的结果,在控制方式上是按照设计调用或返回程序,不能自由导航,各模块之间存在着控制与被控制,调动与被调用的关系。
4、分析设计与编码转换方式不同
面向对象方法贯穿于软件生命周期的分析,设计及编码中,是一种平滑过程,从分析到设计再到编码是采用一致性的模型表示,即实现的是一种无缝连接。而面向过程方法强调分析、设计及编码之间按规则进行转换贯穿于软件生命周期的分析、设计及编码中,实现的是一种有缝的连接。

附上几个链接:

什么是面向对象,面试问到面向对象到底要怎么说?

面向对象(Python语言,算是比较全面) 会举例子说明继承、封装、多态的机制。


3)Python是一种可解释性语言:

目前,常用的解释性语言有 Perl,Python, Lisp/Scheme,Ruby等,究竟什么是解释性语言呢?
所谓的解释性语言主要包括两个方面:一是他们都有自己的解释器,也可以通俗的理解为翻译器;二是他们都是在其他的编译语言(通常是C语言)的基础上定义和扩充了自己的语法结构。

解释性语言的工作原理就是用自己定义的解释其解释并执行有自己定义的语法结构生成的程序代码。所以解释性语言并不编译。这里要区分Java,因为Java并不是单单是一门解释性语言,他为了提高效率而拥有他自己的即时解释器,实际上Java可以算作一门解释和编译的结合语言。

编译型和解释型语言:

计算机不能直接理解高级语言,只能直接理解机器语言,所以必须要把高级语言翻译成机器语言,计算机才能值型高级语言编写的程序。

翻 译的方式有两种,一个是编译,一个是解释。两种方式只是翻译的时间不同。编译型语言写的程序执行之前,需要一个专门的编译过程,把程序编译成为机器语言的 文件,比如exe文件,以后要运行的话就不用重新翻译了,直接使用编译的结果就行了(exe文件),因为翻译只做了一次,运行时不需要翻译,所以编译型语 言的程序执行效率高。

解释型语言则不同,解释性语言的程序不需要编译,省了道工序,解释性语言在运行程序的时候才翻译,比如解释性basic语言,专门有一个解释器能够直接执行basic程序,每个语句都是执行的时候才翻译。这样解释性语言每执行一次就要翻译一次,效率比较低。

java很特殊,java程序也需要编译,但是没有直接编译称为机器语言,而是编译称为字节码,然后用解释方式执行字节码。



Python为什么是一种解释性语言,解释性语言又有什么优越性呢?随着分布式概念的提出,计算机的应用越来越趋向于多平台实用性甚至是跨平台。而随着Web应用的普及,从而使的解释性语言得到空前发展,因为解释性语言拥有自己的解释器,所以这种语言对于平台的依赖性降低到最低程度,而Python就是在这种背景下发展起来的。

当然,虽然解释性语言对平台的依赖性相对小,甚至是独立于平台拥有很大的灵活性,但是由于他并不编译,所以用解释性语言编写的程序代码,在执行过程中要比编译性语言的效率要低得多。。。。

Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。

Python 的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言的一些标点符号,它具有比其他语言更有特色语法结构。

  • Python 是一种解释型语言: 这意味着开发过程中没有了编译这个环节。类似于PHP和Perl语言。

  • Python 是交互式语言: 这意味着,您可以在一个 Python 提示符 >>> 后直接执行代码。

  • Python 是面向对象语言: 这意味着Python支持面向对象的风格或代码封装在对象的编程技术。

  • Python 是初学者的语言:Python 对初级程序员而言,是一种伟大的语言,它支持广泛的应用程序开发,从简单的文字处理到 WWW 浏览器再到游戏。


Python 特点

  • 1.易于学习:Python有相对较少的关键字,结构简单,和一个明确定义的语法,学习起来更加简单。

  • 2.易于阅读:Python代码定义的更清晰。

  • 3.易于维护:Python的成功在于它的源代码是相当容易维护的。

  • 4.一个广泛的标准库:Python的最大的优势之一是丰富的库,跨平台的,在UNIX,Windows和Macintosh兼容很好。

  • 5.互动模式:互动模式的支持,您可以从终端输入执行代码并获得结果的语言,互动的测试和调试代码片断。

  • 6.可移植:基于其开放源代码的特性,Python已经被移植(也就是使其工作)到许多平台。

  • 7.可扩展:如果你需要一段运行很快的关键代码,或者是想要编写一些不愿开放的算法,你可以使用C或C++完成那部分程序,然后从你的Python程序中调用。

  • 8.数据库:Python提供所有主要的商业数据库的接口。

  • 9.GUI编程:Python支持GUI可以创建和移植到许多系统调用。

  • 10.可嵌入: 你可以将Python嵌入到C/C++程序,让你的程序的用户获得"脚本化"的能力。

优点

  • 简单 -- Pytho n是一种代表简单主义思想的语言。阅读一个良好的 Python 程序就感觉像是在读英语一样,尽管这个英语的要求非常严格!Python 的这种伪代码本质是它最大的优点之一。它使你能够专注于解决问题而不是去搞明白语言本身。
  • 易学 -- 就如同你即将看到的一样,Python 极其容易上手。前面已经提到了,Python 有极其简单的语法。
  • 免费、开源 -- Python 是 FLOSS(自由/开放源码软件)之一。简单地说,你可以自由地发布这个软件的拷贝、阅读它的源代码、对它做改动、把它的一部分用于新的自由软件中。FLOSS 是基于一个团体分享知识的概念。这是为什么 Python 如此优秀的原因之一——它是由一群希望看到一个更加优秀的 Python 的人创造并经常改进着的。
  • 高层语言 -- 当你用 Python 语言编写程序的时候,你无需考虑诸如如何管理你的程序使用的内存一类的底层细节。
  • 可移植性 -- 由于它的开源本质,Python 已经被移植在许多平台上(经过改动使它能够工作在不同平台上)。如果你小心地避免使用依赖于系统的特性,那么你的所有 Python 程序无需修改就可以在下述任何平台上面运行。这些平台包括 Linux、Windows、FreeBSD、Macintosh、Solaris、OS/2、Amiga、AROS、AS/400、BeOS、OS/390、z/OS、Palm OS、QNX、VMS、Psion、Acom RISC OS、VxWorks、PlayStation、Sharp Zaurus、Windows CE 甚至还有 PocketPC、Symbian 以及 Google 基于 Linux 开发的 Android 平台!
  • 解释性 -- 这一点需要一些解释。一个用编译性语言比如 C 或 C++ 写的程序可以从源文件(即 C 或 C++ 语言)转换到一个你的计算机使用的语言(二进制代码,即0和1)。这个过程通过编译器和不同的标记、选项完成。当你运行你的程序的时候,连接/转载器软件把你的程序从硬盘复制到内存中并且运行。而 Python 语言写的程序不需要编译成二进制代码。你可以直接从源代码运行程序。在计算机内部,Python 解释器把源代码转换成称为字节码的中间形式,然后再把它翻译成计算机使用的机器语言并运行。事实上,由于你不再需要担心如何编译程序,如何确保连接转载正确的库等等,所有这一切使得使用 Python 更加简单。由于你只需要把你的 Python 程序拷贝到另外一台计算机上,它就可以工作了,这也使得你的 Python 程序更加易于移植。
  • 面向对象 -- Python 既支持面向过程的编程也支持面向对象的编程。在“面向过程”的语言中,程序是由过程或仅仅是可重用代码的函数构建起来的。在“面向对象”的语言中,程序是由数据和功能组合而成的对象构建起来的。与其他主要的语言如 C++ 和 Java 相比,Python 以一种非常强大又简单的方式实现面向对象编程。
  • 可扩展性 -- 如果你需要你的一段关键代码运行得更快或者希望某些算法不公开,你可以把你的部分程序用 C 或 C++ 编写,然后在你的 Python 程序中使用它们。
  • 丰富的库 -- Python 标准库确实很庞大。它可以帮助你处理各种工作,包括正则表达式、文档生成、单元测试、线程、数据库、网页浏览器、CGI、FTP、电子邮件、XML、XML-RPC、HTML、WAV 文件、密码系统、GUI(图形用户界面)、Tk 和其他与系统有关的操作。记住,只要安装了 Python,所有这些功能都是可用的。这被称作 Python 的“功能齐全”理念。除了标准库以外,还有许多其他高质量的库,如 wxPython、Twisted 和 Python 图像库等等。
  • 规范的代码 -- Python 采用强制缩进的方式使得代码具有极佳的可读性。

缺点

  • 运行速度,有速度要求的话,用 C++ 改写关键部分吧。
  • 国内市场较小(国内以 Python 来做主要开发的,目前只有一些 web2.0 公司)。但时间推移,目前很多国内软件公司,尤其是游戏公司,也开始规模使用他。
  • 中文资料匮乏(好的 Python 中文资料屈指可数,现在应该变多了)。托社区的福,有几本优秀的教材已经被翻译了,但入门级教材多,高级内容还是只能看英语版。
  • 构架选择太多(没有像 C# 这样的官方 .net 构架,也没有像 ruby 由于历史较短,构架开发的相对集中。Ruby on Rails 构架开发中小型web程序天下无敌)。不过这也从另一个侧面说明,python比较优秀,吸引的人才多,项目也多。

4)解释:二叉树的构建和遍历

用python实现树的构造和几种遍历算法,虽然不难,不过还是把代码作了一下整理总结。实现功能:

  • 树的构造
  • 递归实现先序遍历、中序遍历、后序遍历
  • 堆栈实现先序遍历、中序遍历、后序遍历
  • 队列实现层次遍历
# coding = utf-8
class Node(object):
    """节点类"""
    def __init__(self, elem=-1, lchild=None, rchild=None):
        self.elem = elem
        self.lchild = lchild
        self.rchild = rchild

class Tree(object):
    def __init__(self):
        self.root = Node()
        self.myQueue = []

    def add(self, elem):
        """为树添加节点"""
        node = Node(elem)
        if self.root.elem == -1:   # 如果树为空的,则对根节点赋值
            self.root = node
            self.myQueue.append(self.root)
        else:
            treeNode = self.myQueue[0]  # 此结点的子树还没有齐
            if treeNode.lchild == None:
                treeNode.lchild = node
                self.myQueue.append(treeNode.lchild)
            else:
                treeNode.rchild = node
                self.myQueue.append(treeNode.rchild)
                self.myQueue.pop(0)  # 如果该结点存在右子树,将此结点丢弃。

    def front_digui(self, root):
        """利用递归实现树的先序遍历"""
        if root == None:
            return
        print(root.elem)
        self.front_digui(root.lchild)
        self.front_digui(root.rchild)

    def middle_digui(self, root):
        """利用递归实现树的中序遍历"""
        if root == None:
            return
        self.middle_digui(root.lchild)
        print(root.elem)
        self.middle_digui(root.rchild)

    def later_digui(self, root):
        """利用递归实现树的后序遍历"""
        if root == None:
            return
        self.later_digui(root.lchild)
        self.later_digui(root.rchild)
        print(root.elem)

    def front_stack(self, root):
        """利用栈堆实现树的先序遍历"""
        if root == None:
            return
        myStack = []
        node = root
        while node or myStack:
            while node:    # 从根节点开始,一直找它的左子树
                print(node.elem)
                myStack.append(node)
                node = node.lchild
            node = myStack.pop()     # while结束表示当前节点node为空,即前一个节点没有左子树了

            node = node.rchild        # 开始查看它的右子树

    def middle_stack(self, root):
        """利用栈堆实现树的中序遍历"""
        if root == None:
            return
        myStack = []
        node = root
        while node or myStack:
            while node:    # 从根节点开始,一直找它的左子树
                myStack.append(node)
                node = node.lchild
            node = myStack.pop()   # while结束表示当前节点node为空,即前一个节点没有左子树了
            print(node.elem)
            node = node.rchild   # 开始查看它的右子树

    def later_stack(self,root):
        """利用栈堆实现树的后序遍历"""
        if root == None:
            return
        myStack1 = []
        myStack2 = []
        node = root
        myStack1.append(node)
        while myStack1:   # 这个while循环的功能是找出后序遍历的逆序,存在myStack2里面
            node = myStack1.pop()
            if node.lchild:
                myStack1.append(node.lchild)
            if node.rchild:
                myStack1.append(node.rchild)

        while myStack2:    # 将myStack2中的元素出栈,即为后序遍历次序
            print(myStack2.pop().elem)

    def level_queue(self,root):
        """利用队列实现树的层次遍历"""
        if root == None:
            return
        myQueue = []
        node = root
        myQueue.append(node)
        while myQueue:
            node = myQueue.pop(0)   # 返回这个树的第一个,并将其从原来的queue中删除。
            print(node.elem)
            if node.lchild != None:
                myQueue.append(node.lchild)
            if node.rchild != None:
                myQueue.append(node.rchild)


if __name__ == '__main__':
    """主函数"""
    elems = range(10)             # 生成十个数据作为树节点
    tree = Tree()                 # 新建一个树对象\
    for elem in elems:
        tree.add(elem)            # 逐个添加树的节点

    print('队列实现层次遍历:')
    tree.level_queue(tree.root)

    print('\n\n递归实现先序遍历:')
    tree.front_digui(tree.root)
    print('\n递归实现中序遍历:' )
    tree.middle_digui(tree.root)
    print('\n递归实现后序遍历:')
    tree.later_digui(tree.root)

    print('\n\n堆栈实现先序遍历:')
    tree.front_stack(tree.root)
    print( '\n堆栈实现中序遍历:')
    tree.middle_stack(tree.root)
    print('\n堆栈实现后序遍历:')
    tree.later_stack(tree.root)

结果:
 

队列实现层次遍历:
0
1
2
3
4
5
6
7
8
9


递归实现先序遍历:
0
1
3
7
8
4
9
2
5
6

递归实现中序遍历:
7
3
8
1
9
4
0
5
2
6

递归实现后序遍历:
7
8
3
9
4
1
5
6
2
0


堆栈实现先序遍历:
0
1
3
7
8
4
9
2
5
6

堆栈实现中序遍历:
7
3
8
1
9
4
0
5
2
6

堆栈实现后序遍历:

首先定义Node类:根据elem设置左右节点;然后再定义Tree类:根据传入的参数定义节点,初始化空队列。

1. 为树增添加节点,如果树为空的,则对根节点进行赋值,并将其放在队列queue中,否则该节点的子节点为空时,判断是左节点还是右节点为空,那个为空就为相应的子节点增添节点值。

2. 遍历:包括利用递归实现先序遍历、利用递归实现中序遍历、利用递归实现后序遍历;利用栈堆实现树的先序、中序、后序遍历。

递归的方式进行遍历的时候,先、中、后序其实有着很大的相似性,不同点在于:先print(root.elem)后左、右;还是先左后print(root.elem)再右;先左、右,再print(root.elem) 。注意在左右的时候,都是递归的调用相应的函数。

堆栈的方式较复杂:需要预先定义myStack=[]和node = root,然后

while node or myStack:
    while node:

接着接就有先序、中序、后序之分了,先序:先print,后左、右;先左、print、右;后序是不同的机制。.


总结:

树的遍历主要有两种,一种是深度优先遍历,像前序、中序、后序;另一种是广度优先遍历,像层次遍历。在树结构中两者的区别还不是非常明显,但从树扩展到有向图,到无向图的时候,深度优先搜索和广度优先搜索的效率和作用还是有很大不同的。 
深度优先一般用递归,广度优先一般用队列。一般情况下能用递归实现的算法大部分也能用堆栈来实现。

我印象中是有递归构造树的方法,却一直想不出该怎么构造。后来仔细想了一下,递归思想有点类似深度优先算法,而树的构造应该是广度优先的。如果用递归的话一定要有个终止条件,例如规定树深等。不然构造出来的树会偏向左单子树或者右单子树。所以一般树的构造还是应该用队列比较好。

5) 数组中连续几个数的和为一固定值的情况,并返回:

def find_continuousfigure(A,S):
    sub_sum = 0
    step = 0
    for i in range(len(A)):
        sub_sum += A[i]
        if sub_sum > S:
            sub_sum = 0
            step = 0
            continue
        elif sub_sum < S:
            step += 1
            continue
        elif sub_sum == S:
            print(A[i-j] for i in range(step+1))
            print('\n')
A = [1,2,3,4,1,3,1]
S = 4
print(find_continuousfigure(A, S))
>>><generator object find_continuousfigure.<locals>.<genexpr> at 0x0000025D56DFF0F8>
>>><generator object find_continuousfigure.<locals>.<genexpr> at 0x0000025D56DFF0F8>
None


返回是这样的,应该不对,看到后有会的大佬请指教。。。。

6) 由random7()生成random10(),但是保证仍是等概率,即1/7 to 1/10

【试题描述】

已知有个rand7()的函数,返回1到7随机自然数,让利用这个rand7()构造rand10()随机1~10。

【试题分析】

1)要保证rand10()在整数1-10的均匀分布,可以构造一个1-10*n的均匀分布的随机整数区间(n为任何正整数)。假设x是这个1-10*n区间上的一个随机整数,那么x%10+1就是均匀分布在1-10区间上的整数。

2)接下来利用(rand7()-1)*7+rand7()构造出均匀分布在1-49的随机数:

首先rand7()-1得到一个离散整数集合{0,1,2,3,4,5,6},其中每个整数的出现概率都是1/7。那么(rand7()-1)*7得到一个离散整数集合A={0,7,14,21,28,35,42},其中每个整数的出现概率也都是1/7。而rand7()得到的集合B={1,2,3,4,5,6,7}中每个整数出现的概率也是1/7。显然集合A和B中任何两个元素组合可以与1-49之间的一个整数一一对应,也就是说1-49之间的任何一个数,可以唯一确定A和B中两个元素的一种组合方式,反过来也成立。由于A和B中元素可以看成是独立事件,根据独立事件的概率公式P(AB)=P(A)P(B),得到每个组合的概率是1/7*1/7=1/49。因此(rand7()-1)*7+rand7()生成的整数均匀分布在1-49之间,每个数的概率都是1/49。

3)由于出现的每个数的出现都是相对独立的,所以剔除41-49后剩下1-40也应该是均匀分布。

# C版本
nt rand10() {
    int x = 0;
    do {
        x = (rand7()-1)*7+rand7();
    }while(x > 40);
    return x % 10 + 1;
}

# python版本,在letcode上有相应的题
class Solution:
    def rand10(self):
        """
        最后的返回结果记得加1
        """
        res = self.rand40()
        while res >= 40:
            res = self.rand40()
        return res % 10 +1
    '''
    产生0-39 40个数 是10 的倍数
    '''
    def rand40(self):
        res = 7 * (rand7()-1) + rand7()  # 该数为[1,49]之间的均匀分布
        return res

注:下面是一个讲一个字符串S,向左移动N个单位的函数。(在做算法题的时候,分析题很重要)

def move(S, N):
    if N >len(S):
        N -= len(S)
    S = S[N:] + S[:N]
    return S
S = 'hello world!'
N  = 2
print(move(S,N))
>>> llo world!he

注二:诡异问题:TypeError: data type not understood

 解答:

如何使用Python产生一个数组,数组的长度为1024,数组的元素全为0?

很简单啊, 使用zeros(1024) 即可实现!

如何产生一个2×1024的全0矩阵呢?是否是zeros(2,1024) ?

若是上述这种写法就会出现 TypeError: data type not understood  这种错误; 
 正确的写法是 zeros((2,1024)),python的二维数据表示要用二层括号来进行表示。
 

猜你喜欢

转载自blog.csdn.net/Jasminexjf/article/details/88997316