牛客网剑指offer编程实践1-10题

    xiaoxiao2022-07-14  153

    牛客网剑指offer编程实践1-10题

    1、二维数组中的查找

    在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数

    解答:

    方法1:遍历整个二维数组,判断数组中是否含有该整数

    方法2:从二维数组的左下角tag开始判断,如果目标整数大于tag,tag右移,如果目标整数小于tag,tag上移。如果相等返回True

    class Solution:    # array 二维列表    def Find(self, target, array):        for i in array:            if target in i:                return True        return False ​    def Find(self, target, array):        raw = len(array)        col = len(array[0])        i = raw - 1        j = 0        while i >= 0 and j < col:            if array[i][j] < target:                j += 1            elif array[i][j] > target:                i -= 1            else:                return True        return False

    2、替换空格

    请实现一个函数,将一个字符串中的每个空格替换成 。例如,当字符串为We Are Happy.则经过替换之后的字符串为We Are Happy。

    解答:

    方法1:将字符串s变换成list,将list中的空格替换成“ ”,然后将list转换成字符串输出。缺点:不是原来的字符串s

    方法2:先遍历以便字符串s,判断有多少个空格,然后从后往前开始替换。

    # -*- coding:utf-8 -*- class Solution:    # s 源字符串    def replaceSpace(self, s):        # write code here        s = list(s)        for i in range(len(s)):            if s[i] == ' ':                s[i] = ' '        return ''.join(s)

    3、从尾到头打印链表

    输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。注意:自定义的listNode函数不能直接使用len(),使用while listNode:

    解答:

    方法1:使用一个栈,遍历链表进行进栈,然后出栈到ArrayList

    方法2:遍历链表到list,然后利用list[::-1]进行输出

    # -*- coding:utf-8 -*- # class ListNode: #     def __init__(self, x): #         self.val = x #         self.next = None ​ class Solution:    # 返回从尾部到头部的列表值序列,例如[1,2,3]    def printListFromTailToHead(self, listNode):        # write code here        if listNode is None:            return []        tmp = []        while listNode:            tmp.append(listNode.val)            listNode = listNode.next        return tmp[::-1]

    4、重建二叉树

    输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

    解答:

    方法:根据前序遍历第一个元素找到根节点,然后在中序遍历中找到根节点的index,index左边的为根节点的左子树,index右边的为根节点的右子树。然后在两个遍历中截取两个子树进行迭代

    注意:要返回二叉树,而不是数组,

    # -*- coding:utf-8 -*- # class TreeNode: #     def __init__(self, x): #         self.val = x #         self.left = None #         self.right = None class Solution:    # 返回构造的TreeNode根节点    def reConstructBinaryTree(self, pre, tin):        # write code here        if len(pre) == 0:            return None        else:            root = TreeNode(pre[0])            tag = tin.index(pre[0])            root.left = self.reConstructBinaryTree(pre[1:tag+1],tin[0:tag])            root.right = self.reConstructBinaryTree(pre[tag+1:],tin[tag+1:])        return root        

    5、用两个栈实现队列

    1、用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

    解答:

    方法:队列的Push操作就是一个栈A的进栈

    队列的Pop操作,判断栈B是否为空,如果为空,则将栈A中所有元素pop,并push进栈B,栈B出栈;如果不为空,栈B直接出栈。

    # -*- coding:utf-8 -*- class Solution:    def __init__(self):        self.stack0 = []        self.stack1 = []    def push(self, node):        # write code here        return self.stack0.append(node)    def pop(self):        # return xx        #出队:判断栈B是否为空,如果为空,则将栈A中所有元素pop,并push进栈B,栈B出栈;如果不为空,栈B直接出栈。        if self.stack1 == []:            while self.stack0:                self.stack1.append(self.stack0.pop())        return self.stack1.pop()

    2、用两个队列实现一个栈的功能?要求给出算法和思路!

    方法:

    入栈:将元素进队列A

    出栈:判断队列A中元素的个数是否为1,如果等于1,则出队列,否则将队列A中的元素以此出队列并放入队列B,直到队列A中的元素留下一个,然后队列A出队列,再把队列B中的元素出队列以此放入队列A中。

    6、旋转数组最小数字

    把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

    解答:

    方法1:遍历整个数组找到最小的元素。

    方法2:因为是非递减数组旋转,利用二分法进行判断,

    如果array[mid] > array[0],则最小元素在mid的右边。找到的第一个小于array[mid]的元素即最小元素

    如果array[mid] < array[0],则最小元素在mid的左边。找到的第一个大于array[mid]的元素,它的后一个元素即为最小元素

    注意数组为0,返回0。

    # -*- coding:utf-8 -*- class Solution:    def minNumberInRotateArray(self, rotateArray):    # write code here        if len(rotateArray) == 0:            return 0        tmp = rotateArray[0]        for i in rotateArray:            if i < tmp:                tmp = i        return tmp    #时间复杂度为O(lgn),二分法    def minNumberInRotateArray(self, rotateArray):    # write code here        if len(rotateArray) == 0:            return 0        mid = int((len(rotateArray) - 1) / 2)        if rotateArray[mid] >= rotateArray[0]:            for i in rotateArray[mid:]:                if i < rotateArray[mid]:                    return i        else:            for i in reversed(range(mid)):                if rotateArray[i] > rotateArray[mid]:                    return rotateArray[i + 1]            

    7、斐波那契数列

    大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。n<=39

    解答:

    方法:动态规划,一次的结果之和上两个数相关

    # -*- coding:utf-8 -*- class Solution:   def Fibonacci(self, n):       # write code here       if n == 0:           return 0       elif n == 1:           return 1       elif n == 2:           return 1       else:           tag = []           tag.append(1)           tag.append(1)           for i in range(2,n):               tag.append(tag[i-1]+tag[i-2])       return tag[n-1]   #从0开始,第0项为0,如果从第一项开始,则为while n > 1:   def Fibonacci(self, n):       f = 0       s = 1       while n:           s = f + s           f = s - f           n -= 1       return f

    8、跳台阶

    一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。

    解答:

    方法:

    a.如果两种跳法,1阶或者2阶,那么假定第一次跳的是一阶,那么剩下的是n-1个台阶,跳法是f(n-1);

    b.假定第一次跳的是2阶,那么剩下的是n-2个台阶,跳法是f(n-2)

    c.由a\b假设可以得出总跳法为: f(n) = f(n-1) + f(n-2)

    d.然后通过实际的情况可以得出:只有一阶的时候 f(1) = 1 ,只有两阶的时候可以有 f(2) = 2

    e.可以发现最终得出的是一个斐波那契数列:

    # -*- coding:utf-8 -*- class Solution:    def jumpFloor(self, number):        # write code here        if number == 1:            return 1        elif number == 2:            return 2        else:            tag = []            tag.append(1)            tag.append(2)            for i in range(2, number):                tag.append(tag[i - 1] + tag[i - 2])        return tag[number-1]    def jumpFloor(self, number):        f = 1        s = 2        while number > 1:            s = f + s            f = s - f            number -= 1        return f

    9、变态跳台阶

    一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

    解答:

    方法1:f(1) = 1

    f(2) = f(2-1) + f(2-2) f(2-2)表示一次跳2级台阶

    f(3) = f(3-1) + f(3-2) +f(3-3)

    f(n) = f(n-1) +…+ f(n-(n-1)) + f(n-n)

    = f(0) + f(1) +…+f(n-1)

    f(n-1) = f(0) + f(1) +…+f(n-2)

    f(n) = 2*f(n-1)

    方法2:每个台阶都有跳与不跳两种情况(除了最后一个台阶),最后一个台阶必须跳。所以共用2^(n-1)中情况

    # -*- coding:utf-8 -*- class Solution: def jumpFloorII(self, number): # write code here return 2**(number-1) def jumpFloorII(self, number): if number <= 0: return -1 elif number == 1: return 1 return 2*self.jumpFloorII(number-1)

    10、矩阵覆盖

    我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

    解答:

    方法:同上面的斐波那契数列,只是f(1) = 1,f(2) = 2

    # -*- coding:utf-8 -*- class Solution: def rectCover(self, number): # write code here if number == 0: return 0 if number == 1: return 1 elif number == 2: return 2 else: tag = [] tag.append(1) tag.append(2) for i in range(2, number): tag.append(tag[i - 1] + tag[i - 2]) return tag[-1] def rectCover(self, number): if number == 0: return 0 elif number == 1: return 1 elif number == 2: return 2 f = 1 s = 2 while number > 1: s = s + f f = s - f number -= 1 return f
    最新回复(0)