剑指offer/Leecode思路及代码汇总(python)

文章目录

  • 剑指offer
    • JZ01 二维数组的查找
    • JZ02 替换空格
    • JZ03 从尾到头打印链表
    • JZ04 重建二叉树
    • JZ05:用两个栈实现队列
    • JZ06 旋转数组的最小数字
    • JZ7 斐波那契数列
    • JZ08:跳台阶
    • JZ9 跳台阶扩展问题
    • JZ10-矩阵覆盖
    • JZ11-二进制中1的个数
    • JZ12-数值的整数次方
    • JZ13-调整数组顺序使奇数位于偶数前面
    • JZ14-链表中倒数第k个结点
    • JZ15-反转链表
    • JZ16-合并有序链表
    • JZ17-树的子结构
    • JZ18-二叉树的镜像
    • JZ19-顺时针打印矩阵
    • JZ20-包含min函数的栈
    • JZ21-栈的压入、弹出序列
    • JZ22-从上到下打印二叉树
    • JZ23-二叉搜索树的后序遍历序列
    • JZ-24-二叉树中和为某一值的路径
    • JZ25-复杂链表的复制
    • JZ26-二叉搜索树与双向链表
    • JZ27-字符串的排列
    • JZ28-数组中出现次数超过一半的数字
    • JZ29-最小的K个数
    • JZ30-连续子数组的最大和
    • JZ31-整数中1出现的次数(从1到n整数中1出现的次数
    • JZ32-把数组排成最小的数
    • JZ33-丑数
    • JZ34-第一个只出现一次的字符
    • JZ35-数组中的逆序对
    • JZ36-两个链表的第一个公共结点
    • JZ37-数字在升序数组中出现的次数
    • JZ38-二叉树的深度
    • JZ39-平衡二叉树
    • JZ40-数组中只出现一次的两个数字
    • JZ41-和为S的连续正数序列
    • JZ42-和为S的两个数字
    • JZ43-左旋转字符串
    • JZ44-翻转单词顺序列
    • JZ45-扑克牌顺子
    • JZ46-孩子们的游戏(圆圈中最后剩下的数字)
    • JZ47-求1+2+3+...+n
    • JZ48-不用加减乘除做加法
    • JZ49-把字符串转换成整数
    • JZ50-数组中重复的数字
    • JZ51-构建乘积数组
    • JZ52-正则表达式匹配
    • JZ53-表示数值的字符串
    • JZ54-字符流中第一个不重复的字符
    • JZ55-链表中环的入口结点
    • JZ56-删除链表中重复的结点
    • JZ57-二叉树的下一个结点
    • JZ58 对称的二叉树
    • JZ59 按之字形顺序打印二叉树
    • JZ60-把二叉树打印成多行
    • JZ61-序列化二叉树
    • JZ62-二叉搜索树的第k个结点
    • JZ63-数据流中的中位数
    • JZ64-滑动窗口的最大值
    • JZ65-矩阵中的路径
    • JZ66-机器人的运动范围
    • JZ67-剪绳子
  • Leecode
    • L1278-分割回文串 III
    • 两数相加
    • 152. 乘积最大子数组
  • 面试笔试拓展题
    • 1. 旋转数组中查找某个值

剑指offer

以牛客网题号为准

JZ01 二维数组的查找

题目: 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
[
[1,2,8,9],
[2,4,9,12],
[4,7,10,13],
[6,8,11,15]
]
给定 target = 7,返回 true。
给定 target = 3,返回 false。

思路: 利用二维数组的特点。采用二分的思想,从数组的左下角开始遍历。

# -*- coding:utf-8 -*-
class Solution:
    # array 二维列表
    def Find(self, target, array):
        # write code here
        if len(array) == 0 and len(array[0]) == 0:
            return False
        i=len(array)-1
        j=0
        while i >= 0 and j <= len(array[0])-1:
            if target>array[i][j]:
                j+=1
            elif target<array[i][j]:
                i-=1
            else:
                return True
        return False

JZ02 替换空格

题目: 请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
思路: 把字符串中的每个字符一个个添加到新字符串中,如果遇到空格就把他换成%20。

class Solution:
    def replaceSpace(self , s ):
        # write code here
        res=[]
        for i in range(len(s)):
            if s[i]==' ':
                res.append('%20')
            else:
                res.append(s[i])
        ss=''.join(res)
        return ss

JZ03 从尾到头打印链表

**题目:**输入一个链表的头节点,按链表从尾到头的顺序返回每个节点的值(用数组返回)。
思路:利用insert函数。

# -*- 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
        pTempt=listNode
        res=[]
        while pTempt:
            res.insert(0,pTempt.val)
            pTempt=pTempt.next
        return res

JZ04 重建二叉树

题目: 给定某二叉树的前序遍历和中序遍历,请重建出该二叉树并返回它的头结点。
例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建出如下图所示。
剑指offer/Leecode思路及代码汇总(python)_第1张图片
思路:

  1. 首先根据前序遍历得到根节点
  2. 找到中序遍历中根节点的索引,即可分出左子树和右子树。
  3. 遍历建立左子树和右子树。
# -*- 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 or len(tin)==0:
            return None
        root=TreeNode(pre[0])
        ind=tin.index(pre[0])
        root.left=self.reConstructBinaryTree(pre[1:ind+1], tin[0:ind])
        root.right=self.reConstructBinaryTree(pre[ind+1:len(pre)], tin[ind+1:len(tin)])
        return root

JZ05:用两个栈实现队列

题目: 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
思路: 入栈时数据存入栈stackIn, 出栈时数据从stackOut弹出。执行入栈操作时,将数据源源不断的压入栈stackIn;执行出栈操作时,将stackIn的数据一次性全部弹出,存入到stackOut中。当stackOut栈非空时,不断弹出stackOut栈中的数据顺序即为队列的Pop顺序;当stackOut中的数据为空后,再将新入栈stackIn的数据一次性存入stackOut中即可。相比于上一种方式,这种方式极大降低了数据在栈stackIn和栈stackOut中来回无意义的腾挪操作,占据更低的存储空间,消耗更低的运算时间。

# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.stackIn = []
        self.stackOut = []

    def push(self, node):
        self.stackIn.append(node)

    def pop(self):
        if self.stackOut:
            return self.stackOut.pop()
        elif not self.stackIn:
            return None
        else:
            while self.stackIn:
                self.stackOut.append(self.stackIn.pop())
            return self.stackOut.pop()

JZ06 旋转数组的最小数字

题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

# -*- coding:utf-8 -*-
class Solution:
    def minNumberInRotateArray(self, rotateArray):
        # write code here
        if len(rotateArray)==0:
            return 0
        left=0
        right=len(rotateArray)-1
        
        while left<right:
            mid=(left+right)//2
            if rotateArray[mid]>rotateArray[right]:
                left=mid+1
            elif rotateArray[mid]<rotateArray[right]:
                right=mid
            else:
                right-=1
        return rotateArray[left]

JZ7 斐波那契数列

题目: 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,第1项是1)。
思路: 递归法时间复杂度过高。因此采用递推法,时间复杂度为O(n)。

# -*- coding:utf-8 -*-
class Solution:
    def Fibonacci(self, n):
        a,b=0,1
        for i in range(n):
            a,b=b,a+b
        return a

JZ08:跳台阶

递归

def numWays(self, n: int) -> int:
        if n == 0:
            return 1
        elif n == 1:
            return 1
        elif n == 2:
            return 2
        else:
            return (self.numWays(n - 1) + self.numWays(n-2)) 

非递归:

class Solution:
    def jumpFloor(self, number):
        # write code here
        if number<1:
            return 0
        a=1
        b=2
        for i in range(number-1):
            a,b=b,a+b
        return a

JZ9 跳台阶扩展问题

**题目:**一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶(n为正整数)总共有多少种跳法。
思路:
f [ n ] = f [ n − 1 ] + f [ n − 2 ] + . . . + f [ 0 ] f[n] = f[n-1] + f[n-2] + ... + f[0] f[n]=f[n1]+f[n2]+...+f[0]
f [ n − 1 ] = f [ n − 2 ] + f [ n − 3 ] + . . . + f [ 0 ] f[n-1] = f[n-2] + f[n-3] + ... + f[0] f[n1]=f[n2]+f[n3]+...+f[0]
所以一合并, f [ n ] = 2 ∗ f [ n − 1 ] = 2 n − 1 f[n] = 2*f[n-1]=2^{n-1} f[n]=2f[n1]=2n1,初始条件f[0] = f[1] = 1

# -*- coding:utf-8 -*-
class Solution:
    def jumpFloorII(self, number):
        # write code here
        return pow(2,number-1)

JZ10-矩阵覆盖

题目: 我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2n的大矩形,总共有多少种方法?
比如n=3时,2
3的矩形块有3种覆盖方法:
剑指offer/Leecode思路及代码汇总(python)_第2张图片思路: 假设2*n的第一个矩形竖着放,则剩下的就是f(n-1).假设第一个横着放,那么第二个必须在下面横着放,剩下的就是f(n-2)
则递推公式为f(n)=f(n-1)+f(n-2),且f(1)=1,f(2)=2.
(注意n<=1的情况)

class Solution:
    def rectCover(self, number):
        # write code here
        if number<=1:
            return number
        a=1
        b=2
        for i in range(number-1):
            a,b=b,a+b
        return a

JZ11-二进制中1的个数

题目: 输入一个整数,输出该数32位二进制表示中1的个数。其中负数用补码表示。

思路: 1100&1011=1000。也就是说,把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0。那么一个整数的二进制有多少个1,就可以进行多少次这样的操作。
但python当超出int的32位时会自动转化为long型,上述代码“n = n &(n - 1)”在执行时,当执行到倒数第二步,即原来的整数变成 1(31个0)时,该整数减一,在c++中结果为0(31个1),相与之后结果为0,终止循环。但是python在计算该整数减一时,会得到1(32个0),陷入无限循环。因此通过“n & 0xffffffff”实现python只取32位的功能,相与之后32位之前不会再有值。

class Solution:
    def NumberOf1(self, n):
        # write code here
        cou = 0
        if n < 0:
            n = n & 0xffffffff
        while n:
            cou = cou + 1
            n = n &(n - 1)
        return cou

JZ12-数值的整数次方

题目: 给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
保证base和exponent不同时为0
思路: 如果base为0,直接返回0。如果exponent为0,返回1.
采用递推公式,如果exponent为正数:Power(base, exponent)=base*Power(base, exponent-1)。
如果exponent为负数:Power(base, exponent)=(1/base)*Power(base, exponent+1)

class Solution:
    def Power(self, base, exponent):
        # write code here
        if base==0:
            return 0
        if exponent==0:
            return 1
        if exponent>0:
            return base*self.Power(base, exponent-1)
        else:
            return (1/base)*self.Power(base, exponent+1)
# -*- coding:utf-8 -*-
class Solution:
    def Power(self, base, exponent):
        # write code here
        if base==0:
            return 0
        if exponent>0:
            if exponent%2==0:
                result=self.Power(base, exponent//2)
                result=result**2
                return result
            elif exponent%2==1:
                result=self.Power(base, exponent//2)**2
                result=result*base
                return result
        elif exponent<0:
            result=self.Power(1/base, abs(exponent))
            return result
        else:
            return 1

JZ13-调整数组顺序使奇数位于偶数前面

**题目:**输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
思路: 遍历,若余数为1,append到奇数数组,反之append到偶数数组。最后讲奇数和偶数数组加起来即可。

class Solution:
    def reOrderArray(self , array ):
        # write code here
        oddarray=[]
        evenarray=[]
        for i in array:
            if i%2==0:
                evenarray.append(i)
            else:
                oddarray.append(i)
        return oddarray+evenarray

JZ14-链表中倒数第k个结点

题目: 输入一个链表,输出该链表中倒数第k个结点。
思路: 在链表中:倒数的+顺数的长度等于链表总长度,所以可以设置两个指针,一个先走K步,剩下的到链表的末尾要走的步数就是倒数第k个节点需要从头开始走的步数。
注意在先移动k步快指针时,需要先判断k是否为空再挪指针,因为当快指针第一次为空时,慢指针不是None。否则,若第k步正好快指针指向None时慢指针也会返回None,是不对的。

class Solution:
    def FindKthToTail(self , pHead , k ):
        # write code here
        fast=pHead
        slow=pHead
        for i in range(k):
            if not fast:
                return None
            fast=fast.next
        while fast:
            fast=fast.next
            slow=slow.next
        return slow

JZ15-反转链表

题目: 输入一个链表,反转链表后,输出新链表的表头。
思路: 先保留现有链表的第二个节点,将现有链表的头指向已反转的链表。从现有链表第二个节点开始为新的链表,更新已反转的链表。迭代至尾结点。

class Solution:
    # 返回ListNode
    def ReverseList(self, pHead):
        # write code here
        if pHead==None:
            return None
        last=None
        while pHead:
            tmp=pHead.next
            pHead.next=last 
            last=pHead
            pHead=tmp
        return last

JZ16-合并有序链表

题目: 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
思路: 利用递归,首先如果有一个链表为空,则直接返回另一个链表。比较两个链表的值,将表头小的链表指向下一个,并递归调用。

class Solution:
    

你可能感兴趣的:(python,python,面试)