剑指offer(Python版本)

本文精选《剑指Offer》中的经典算法题目,涵盖数组、链表、二叉树等多种数据结构,通过实例讲解算法设计与优化,适合算法初学者及面试备考人员。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

剑指offer(Python版本)

二维数组查找

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

# -*- coding:utf-8 -*-
class Solution:
    # array 二维列表
    def Find(self, target, array):
        # write code here
        for i in range(len(array)):
            for j in range(len(array[0])):
                if target==array[i][j]:
                    return True
        return False

替换空格

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

class Solution:
    def replaceSpace(self, s):
        return s.replace(" ","%20")

从尾到头打印链表

输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def printListFromTailToHead(self, listNode):
        result = []
        head = listNode
        while(head!=None):
            result.append(head.val)  #result.insert(0,head.val)
            head = head.next
        result.reverse()
        return result

重建二叉树

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

# -*- 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):
        length = len(tin)
        if length == 0:return None
        head = TreeNode(pre[0])
        head.left=self.reConstructBinaryTree(pre[1:tin.index(pre[0])+1],tin[:tin.index(pre[0])])
        head.right=self.reConstructBinaryTree(pre[tin.index(pre[0])+1:],tin[tin.index(pre[0])+1:])
        return head

用两个栈实现队列

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

# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.stack1 = []
        self.stack2 = []
    def push(self, node):
        self.stack1.append(node)
    def pop(self):
        if(self.stack2==[]):
            while(self.stack1):
                self.stack2.append(self.stack1.pop())
            return self.stack2.pop()
        return self.stack2.pop()

旋转数组的最小数字

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

# -*- coding:utf-8 -*-
class Solution:
    def minNumberInRotateArray(self, rotateArray):
        rotateArray.sort()
        return rotateArray[0]

斐波那契数列

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

# -*- coding:utf-8 -*-
class Solution:
    def Fibonacci(self, n):
        if n==0:
            return 0
        elif n==1:
            return 1
        else:
            a,b = 0,1
            while n>1:
                a,b = b,a+b
                n=n-1
            return b

跳台阶

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

# -*- coding:utf-8 -*-
class Solution:
    def jumpFloor(self, number):
        if number==1:
            return 1
        elif(number==2):
            return 2
        else:
            a=1
            b=2
            while(number>2):
                a,b=b,a+b
                number=number-1
            return b

矩阵覆盖

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

# -*- coding:utf-8 -*-
class Solution:
    def rectCover(self, number):
        if number == 0:
            return 0
        elif number ==1:
            return 1
        elif number ==2:
            return 2
        else:
            a,b = 1,2
            while(number>2):
                a,b = b,a+b
                number-=1
            return b

二进制1的个数

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

# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1(self, n):
        return sum([(n>>i & 1) for i in range(0,32)])

数值的整数次方

给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。

# -*- coding:utf-8 -*-
class Solution:
    def Power(self, base, exponent):
        return base**(exponent)

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

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

# -*- coding:utf-8 -*-
class Solution:
    def reOrderArray(self, array):
        result_even = []
        result_odd = []
        for i in range(len(array)):
            if(array[i]%2==0):
                result_even.append(array[i])
            else:
                result_odd.append(array[i])
        return result_odd+result_even

链表中倒数第k个结点

输入一个链表,输出该链表中倒数第k个结点。

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def FindKthToTail(self, head, k):
        p = head;
        for i in range(k):
            if p==None:
                return None
            else:
                p = p.next
        while(p!=None):
            p = p.next;
            head = head.next
        return head

反转链表

输入一个链表,反转链表后,输出新链表的表头。

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    # 返回ListNode
    def ReverseList(self, pHead):
        last = None
        while pHead:
            temp = pHead.next
            pHead.next = last
            last = pHead
            pHead = temp
        return last

合并两个排序的链表

输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    # 返回合并后列表
    def Merge(self, pHead1, pHead2):
        phead = ListNode(0)
        cur = phead
        while(True):
            if(pHead1==None):
                cur.next = pHead2
                break
            elif(pHead2==None):
                cur.next = pHead1
                break
            else:
                if(pHead1.val>pHead2.val):
                    cur.next = pHead2
                    cur = cur.next
                    pHead2 = pHead2.next
                else:
                    cur.next = pHead1
                    cur = cur.next
                    pHead1 = pHead1.next
        return phead.next

树的子结构

输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def HasSubtree(self, pRoot1, pRoot2):
        if(pRoot1==None):
            return False
        if(pRoot2==None):
            return False
        return (self.dfs(pRoot1,pRoot2) or self.HasSubtree(pRoot1.left,pRoot2) or self.HasSubtree(pRoot1.right,pRoot2))
    def dfs(self,R1,R2):
        if(R2==None):
            return True
        if(R1==None):
            return False
        if(R1.val!=R2.val):
            return False
        return self.dfs(R1.right,R2.right) and self.dfs(R1.left,R2.left)

二叉树的镜像

操作给定的二叉树,将其变换为源二叉树的镜像。

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回镜像树的根节点
    def Mirror(self, root):
        if not root:return
        temp = root.left
        root.left = root.right
        root.right = temp
        self.Mirror(root.left)
        self.Mirror(root.right)

顺时针打印矩阵

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

# -*- coding:utf-8 -*-
class Solution:
    # matrix类型为二维列表,需要返回列表
    def printMatrix(self, matrix):
        row = len(matrix)
        col = len(matrix[0])
        cir = 0
        ans = []
        while(row>2*cir and col>2*cir):
            #上面
            for i in range(cir,col-cir):
                ans.append(matrix[cir][i])
            #右面
            if(cir<row-cir-1):
                for i in range(cir+1,row-cir):
                    ans.append(matrix[i][col-cir-1])
            #下面
            if(col-cir-1>cir and row-1-cir>cir):
                a = [i for i in xrange(cir,col-cir-1)]
                a.reverse()
                for i in a:
                    ans.append(matrix[row-1-cir][i])
            #左面
            if(cir<col-cir-1 and cir<row-cir-2):
                a = [i for i in range(cir+1,row-cir-1)]
                a.reverse()
                for i in a:
                    ans.append(matrix[i][cir])
            cir = cir + 1
        return ans

包含Min函数的栈

定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。

# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.stack1 = []
        self.stackmin = []
    def push(self, node):
        self.stack1.append(node)
        if not self.stackmin or self.stackmin[-1]>=node:
            self.stackmin.append(node)
    def pop(self):
        if self.stack1[-1]==self.stackmin[-1]:
            self.stackmin.pop()
        self.stack1.pop()
    def top(self):
        return self.stack1[-1]
    def min(self):
        return self.stackmin[-1]
        # write code here

栈的压入、弹出序列

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

# -*- coding:utf-8 -*-
class Solution:
    def IsPopOrder(self, pushV, popV):
        length = len(pushV)
        stack = []
        for i in range(length):
            stack.append(pushV[i])
            while(len(stack)>0 and stack[-1]==popV[0]):
                stack.pop()
                popV = popV[1:]
        if len(stack)==0 and len(popV)==0:
            return True
        else:
            return False

从上往下打印二叉树

从上往下打印出二叉树的每个节点,同层节点从左至右打印。

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回从上到下每个节点值列表,例:[1,2,3]
    def PrintFromTopToBottom(self, root):
        result = []
        if root==None:
            return result
        q = [root]
        while(len(q)>0):
            fr = q.pop(0)
            result.append(fr.val)
            if fr.left!=None:
                q.append(fr.left)
            if fr.right!=None:
                q.append(fr.right)
        return result

二叉树搜索的后序遍历序列

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。

# -*- coding:utf-8 -*-
class Solution:
    def VerifySquenceOfBST(self, sequence):
        if not sequence:return False
        if len(sequence)==1:return True
        begin = 0
        end = len(sequence)-1
        index = begin
        root = sequence[end]
        i = 0
        while(sequence[i]<root):
            i = i + 1
        index = i
        for j in range(index,end):
            if(sequence[j]<root):
                return False
        left = True
        if(index>begin):
            left = self.VerifySquenceOfBST(sequence[0:index])
        right = True
        if(index<end-1):
            right = self.VerifySquenceOfBST(sequence[index:end])
        return (left and right)

二叉树中和为某一值的路径

输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回二维列表,内部每个列表表示找到的路径
    def FindPath(self, root, expectNumber):
        if root==None:
            return []
        if root and not root.left and not root.right and root.val == expectNumber:
            return [[root.val]]
        res = []
        left = self.FindPath(root.left, expectNumber-root.val)
        right = self.FindPath(root.right, expectNumber-root.val)
        for i in left+right:
            res.append([root.val]+i)
        return res

复杂链表的复制

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

# -*- coding:utf-8 -*-
# class RandomListNode:
#     def __init__(self, x):
#         self.label = x
#         self.next = None
#         self.random = None
class Solution:
    def Clone(self, pHead):
        head = pHead
        p_head = None
        new_head = None
        
        random = {}
        old2new = {}
        
        while head:
            node = RandomListNode(head.label)
            node.next = head.next
            node.random = head.random
            old2new[id(head)] = id(node)
            random[id(node)] = node
            head=head.next
            
            if new_head:
                new_head.next = node
                new_head = new_head.next
            else:
                p_head = node
                new_head = node
        new_head = p_head
        while new_head:
            if(new_head.random!=None):
                new_head.random = random[old2new[id(new_head.random)]]
            new_head=new_head.next
        return p_head

二叉搜索树与双向链表

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def Convert(self, pRootOfTree):
        if not pRootOfTree:
            return pRootOfTree
        if not pRootOfTree.left and not pRootOfTree.right:
            return pRootOfTree
        # 处理左子树
        self.Convert(pRootOfTree.left)
        left=pRootOfTree.left
        # 连接根与左子树最大结点
        if left:
            while(left.right):
                left=left.right
            pRootOfTree.left,left.right=left,pRootOfTree
# 处理右子树
        self.Convert(pRootOfTree.right)
        right=pRootOfTree.right
         # 连接根与右子树最小结点
        if right:
            while(right.left):
                right=right.left
            pRootOfTree.right,right.left=right,pRootOfTree
             
        while(pRootOfTree.left):
            pRootOfTree=pRootOfTree.left
        return pRootOfTree

字符串的排列

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

# -*- coding:utf-8 -*-
import itertools
class Solution:
    def Permutation(self, ss):
        # write code here
        if not ss:
            return []
        return sorted(list(set(map(''.join, itertools.permutations(ss)))))

数组中出现次数超过一半的数字

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

# -*- coding:utf-8 -*-
class Solution:
    def MoreThanHalfNum_Solution(self, numbers):
        length = len(numbers)
        number = []
        count = []
        for i in range(length):
            if numbers[i] not in number:
                number.append(numbers[i])
                count.append(1)
            else:
                count[number.index(numbers[i])] = count[number.index(numbers[i])]+1
        for i in range(len(count)):
            if count[i]>length/2:
                return number[i]
        return 0

最小的K个数

输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

# -*- coding:utf-8 -*-
class Solution:
    def GetLeastNumbers_Solution(self, tinput, k):
        tinput.sort()
        result = []
        if k>len(tinput):return []
        for i in range(k):
            result.append(tinput[i])
        return result

连续子数组的最大和

HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)

# -*- coding:utf-8 -*-
class Solution:
    def FindGreatestSumOfSubArray(self, array):
        res =max(array)
        temp = 0
        for i in array:
            temp = max(i,temp+i)
            res = max(res,temp)
        return res

整数中1出现的次数

求出113的整数中1出现的次数,并算出1001300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。

# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1Between1AndN_Solution(self, n):
        res=0
        tmp=n
        base=1
        while tmp:
            last=tmp%10
            tmp=tmp/10
            res+=tmp*base
            if last==1:
                res+=n%base+1
            elif last>1:
                res+=base
            base*=10
        return res

把数组排成最小的数

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323

# -*- coding:utf-8 -*-
class Solution:
    def PrintMinNumber(self, numbers):
        if not numbers:
            return ""
        num = map(str,numbers)
        num.sort(lambda x,y:cmp(x+y,y+x))
        return "".join(num)

丑数

把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数

# -*- coding:utf-8 -*-
class Solution:
    def GetUglyNumber_Solution(self, index):
        if index<7:
            return index
        res = [0 for i in range(index)]
        res[0] = 1
        t2 = 0
        t3 = 0
        t5 = 0
        for i in range(1,index):
            res[i]=min(res[t2]*2,min(res[t3]*3,res[t5]*5))
            if(res[i]==res[t2]*2):t2 += 1
            if(res[i]==res[t3]*3):t3 += 1
            if(res[i]==res[t5]*5):t5 += 1
        return res[index-1]

第一次只出现一次的字符

在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写)

# -*- coding:utf-8 -*-
class Solution:
    def FirstNotRepeatingChar(self, s):
        if len(s)==0:
            return -1
        for i in range(len(s)):
            if s.count(s[i])==1:
                return i
        return -1

数组中的逆序对

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007

# -*- coding:utf-8 -*-
class Solution:
    def InversePairs(self, data):
        return self.inverseCount(data[:], 0, len(data)-1, data[:])%1000000007
       
    def inverseCount(self, tmp, start, end, data):
        if end-start <1:
            return 0
        if end - start == 1:
            if data[start]<=data[end]:
                return 0
            else:
                tmp[start], tmp[end] = data[end], data[start]
                return 1
        mid = (start+end)//2
        cnt = self.inverseCount(data, start, mid, tmp) + self.inverseCount(data, mid+1, end, tmp)
        # print(start, mid, end, cnt, data)
        i = start
        j = mid + 1
        ind = start
           
        while(i <= mid and j <= end):
            if data[i] <= data[j]:
                tmp[ind] = data[i]
                i += 1
            else:
                tmp[ind] = data[j]
                cnt += mid - i + 1
                j += 1
            ind += 1
        while(i<=mid):
            tmp[ind] = data[i]
            i += 1
            ind += 1
        while(j<=end):
            tmp[ind] = data[j]
            j += 1
            ind += 1
        return cnt

两个链表的第一个公共结点

输入两个链表,找出它们的第一个公共结点。

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    def FindFirstCommonNode(self, pHead1, pHead2):
        p1 = pHead1
        p2 = pHead2
        len1 = 0
        len2 = 0
        while(p1):
            len1+=1
            p1 = p1.next
        while(p2):
            len2+=1
            p2 = p2.next
        if(len1>len2):
            diff = len1 - len2
            p1 = pHead1
            p2 = pHead2
        else:
            diff = len2 - len1
            p1 = pHead2
            p2 = pHead1
        for i in range(diff):
            p1 = p1.next
        while(p1 and p2):
            if(p1==p2):
                break
            p1 = p1.next
            p2 = p2.next
        return p1

数字在排序数组中出现的次数

统计一个数字在排序数组中出现的次数。

# -*- coding:utf-8 -*-
class Solution:
    def GetNumberOfK(self, data, k):
        return data.count(k)

二叉树的深度

输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def TreeDepth(self, pRoot):
        if not pRoot:
            return 0
        return max(1+self.TreeDepth(pRoot.left),1+self.TreeDepth(pRoot.right))

平衡二叉树

输入一棵二叉树,判断该二叉树是否是平衡二叉树。

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def IsBalanced_Solution(self, pRoot):
        if(pRoot==None):return True
        left_depth = self.getdepth(pRoot.left)
        right_depth = self.getdepth(pRoot.right)
        if(left_depth>right_depth+1 or left_depth+1<right_depth):
            return False
        else:
            return self.IsBalanced_Solution(pRoot.left) and self.IsBalanced_Solution(pRoot.right)
    def getdepth(self,pRoot):
        if(pRoot==None):return 0
        return max(1+self.getdepth(pRoot.left),1+self.getdepth(pRoot.right))

数组中只出现一次的数字

一个整型数组里除了两个数字之外,其他的数字都出现了偶数次。请写程序找出这两个只出现一次的数字。

# -*- coding:utf-8 -*-
class Solution:
    # 返回[a,b] 其中ab是出现一次的两个数字
    def FindNumsAppearOnce(self, array):
        result = []
        for i in array:
            if array.count(i)==1:
                result.append(i)
        return result

和为S的连续正数序列

小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!

# -*- coding:utf-8 -*-
class Solution:
    def FindContinuousSequence(self, tsum):
        # write code here
        count = []
        for n in range(1,tsum):
            m = 1
            while(True):
                if(2*n+m)*(m+1)<tsum*2:
                    m = m+1
                elif((2*n+m)*(m+1)==tsum*2):
                    num = [x for x in range(n,n+m+1)]
                    count.append(num)
                    break
                else:
                    break
        return count

和为S的两个数字

输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。

# -*- coding:utf-8 -*-
class Solution:
    def FindNumbersWithSum(self, array, tsum):
        result = []
        for i in array:
            senc = tsum - i
            if senc in array:
                result.append(i)
                result.append(senc)
                break
        return result

左旋转字符串

汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!

# -*- coding:utf-8 -*-
class Solution:
    def LeftRotateString(self, s, n):
        string = s[n:]+s[:n]
        return string

翻转单词顺序列

牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?

# -*- coding:utf-8 -*-
class Solution:
    def ReverseSentence(self, s):
        ll = s.split(" ")
        return " ".join(ll[::-1])

扑克牌顺子

LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张_)…他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子…LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何, 如果牌能组成顺子就输出true,否则就输出false。为了方便起见,你可以认为大小王是0。

# -*- coding:utf-8 -*-
class Solution:
    def IsContinuous(self, numbers):
        if not numbers:
            return False
        new_list = [i for i in numbers if i>0]
        new_list.sort()
        if len(new_list)==1:
            return True
        n = 0
        for i in range(len(new_list)-1):
            if(new_list[i+1]-new_list[i]>0):
                n += new_list[i+1]-new_list[i]
            else:
                return False
        if n<=4:
            return True
        else:
            return False

孩子们的游戏(圆圈中最后剩下的数)

每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0…m-1报数…这样下去…直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!_)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)

# -*- coding:utf-8 -*-
class Solution:
    def LastRemaining_Solution(self, n, m):
        if n==0:
            return -1
        s = 0
        for i in range(2,n+1):
            s = (s+m)%i
        return s

求1+2+3…+n

求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。

# -*- coding:utf-8 -*-
class Solution:
    def Sum_Solution(self, n):
        return n and self.Sum_Solution(n-1)+n

不用加减乘除做加法

写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。

# -*- coding:utf-8 -*-
class Solution:
    def Add(self, num1, num2):
        return sum([num1,num2])

把字符串转换成整数

将一个字符串转换成一个整数(实现Integer.valueOf(string)的功能,但是string不符合数字要求时返回0),要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0。

# -*- coding:utf-8 -*-
class Solution:
    def StrToInt(self, s):
        try:
            return int(s)
        except:
            return 0

数组中重复的数字

在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。

# -*- coding:utf-8 -*-
class Solution:
    # 这里要特别注意~找到任意重复的一个值并赋值到duplication[0]
    # 函数返回True/False
    def duplicate(self, numbers, duplication):
        if(len(numbers)==0):return False
        for i in numbers:
            if numbers.count(i)>1:
                duplication[0] = i
                return True
        return False

构建乘积数组

给定一个数组A[0,1,…,n-1],请构建一个数组B[0,1,…,n-1],其中B中的元素B[i]=A[0]A[1]…*A[i-1]A[i+1]…*A[n-1]。不能使用除法。

# -*- coding:utf-8 -*-
class Solution:
    def multiply(self, A):
        B = []
        for i in range(len(A)):
            number = 1
            for j in range(len(A)):
                if j==i:
                    continue
                else:
                    number *=A[j]
            B.append(number)
        return B

正则表达式匹配

请实现一个函数用来匹配包括’.‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"ab*a"均不匹配。

# -*- coding:utf-8 -*-
class Solution:
    # s, pattern都是字符串
    def match(self, s, pattern):
        if(len(s)==0 and len(pattern)==0):return True
        if(len(s)>0 and len(pattern)==0):return False
        if(len(pattern)>1 and pattern[1]=="*"):
            if(len(s)>0 and (s[0]==pattern[0] or pattern[0]==".")):
                return self.match(s[1:],pattern) or self.match(s,pattern[2:])
            else: 
                return self.match(s,pattern[2:])
        if(len(s)>0 and (pattern[0]=="." or pattern[0]==s[0])):
            return self.match(s[1:],pattern[1:])
        return False

表示数值的字符串

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100",“5e2”,"-123",“3.1416"和”-1E-16"都表示数值。 但是"12e",“1a3.14”,“1.2.3”,"±5"和"12e+4.3"都不是。

# -*- coding:utf-8 -*-
class Solution:
    # s字符串
    def isNumeric(self, s):
        try:
            p = float(s)
            return True
        except:
            return False

字符流中第一个不重复的字符

请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。

# -*- coding:utf-8 -*-
class Solution:
    # 返回对应char
    def __init__(self):
        self.s = ""
        self.direct = {}
    def FirstAppearingOnce(self):
        for i in self.s:
            if self.direct[i]==1:
                return i
        return '#'
    def Insert(self, char):
        self.s += char
        if char in self.direct:
            self.direct[char] += 1
        else:
            self.direct[char] = 1

链表中环的入口结点

给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    def EntryNodeOfLoop(self, pHead):
        temp = []
        p = pHead
        while p:
            if p in temp:
                return p
            else:
                temp.append(p)
            p = p.next

删除链表中重复的结点

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5。

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    def deleteDuplication(self, pHead):
        result=ListNode(0)
        res=result
        result.next=pHead
        tmp=pHead
        while tmp and tmp.next:
            if tmp.val==tmp.next.val:
                while tmp.next and tmp.val==tmp.next.val:
                    tmp=tmp.next
            else:
                res.next=tmp
                res=res.next
            tmp=tmp.next
        res.next=tmp
        return result.next

二叉树的下一个结点

给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

# -*- coding:utf-8 -*-
# class TreeLinkNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
#         self.next = None
class Solution:
    def GetNext(self, pNode):
        if(pNode==None):
            return None
        if(pNode.right!=None):
            pNode = pNode.right
            while(pNode.left):
                pNode = pNode.left
            return pNode
        while(pNode.next!=None):
            proot = pNode.next
            if(proot.left==pNode):
                return proot
            pNode = pNode.next
        return None

对称二叉树

请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def isSymmetrical(self, pRoot):
        return self.issymmetrical(pRoot,pRoot)
    def issymmetrical(self,pRoot1,pRoot2):
        if(pRoot1==None and pRoot2==None):
            return True
        if(pRoot1==None or pRoot2==None):
            return False
        if(pRoot1.val!=pRoot2.val):
            return False
        return self.issymmetrical(pRoot1.left,pRoot2.right) and self.issymmetrical(pRoot1.right,pRoot2.left)

按之字形顺序打印二叉树

请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def Print(self, pRoot):
        result = []
        stack = [pRoot]
        level = 1
         
        while len(stack) > 0:
            ns = []
            rs = []
            for i in stack:
                if i != None:
                    rs.append(i.val)
                    if i.left != None:
                        ns.append(i.left)
                    if i.right != None:
                        ns.append(i.right)
                         
            if level % 2 == 0:
                rs.reverse()
            if len(rs) > 0:
                result.append(rs)
                 
            stack = ns
            level += 1
        return result

把二叉树打印成多行

从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回二维列表[[1,2],[4,5]]
    def Print(self, pRoot):
        if not pRoot:
            return []
        ans = []
        q = [pRoot]
        while q:
            p = []
            temp = []
            if(len(q)>0):
                for i in q:
                    temp.append(i.val)
                    if i.left:
                        p.append(i.left)
                    if i.right:
                        p.append(i.right)
            q = p
            ans.append(temp)
        return ans

序列化二叉树

请实现两个函数,分别用来序列化和反序列化二叉树

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    flag = -1
    def Serialize(self, root):
        # write code here
        if not root:
            return '#'
        return str(root.val) + ',' + self.Serialize(root.left) + ',' + self.Serialize(root.right)
     
    def Deserialize(self, s):
        # write code here
        self.flag += 1
         
        l = s.split(',')
        if self.flag >= len(s):
            return None
         
        root = None
        if l[self.flag] != '#':
            root = TreeNode(int(l[self.flag]))
            root.left = self.Deserialize(s)
            root.right = self.Deserialize(s)
        return root

二叉搜索树的第k个结点

给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回对应节点TreeNode
    def __init__(self):
        self.count = 0
    def KthNode(self, pRoot, k):
        if(pRoot!=None):
            ret = self.KthNode(pRoot.left,k)
            if(ret!=None):
                return ret
            self.count = self.count + 1
            if(self.count==k):
                return pRoot
            ret = self.KthNode(pRoot.right,k)
            if(ret!=None):
                return ret
        return None

数据流中的中位数

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数

# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.data = []
    def Insert(self, num):
        self.data.append(num)
        self.data.sort()
    def GetMedian(self,data):
        length = len(self.data)
        if length%2==0:
            return (self.data[length//2]+self.data[length//2-1])/2.0
        else:
            return self.data[length//2]

滑动窗口的最大值

给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。

# -*- coding:utf-8 -*-
class Solution:
    def maxInWindows(self, num, size):
        count = len(num)-size+1
        result = []
        max_number = 0
        if size==0 or len(num)==0:
            return []
        for i in range(count):
            max_number = max(num[i:i+size])
            result.append(max_number)
        return result

矩阵中的路径

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则之后不能再次进入这个格子。 例如 a b c e s f c s a d e e 这样的3 X 4 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。

# -*- coding:utf-8 -*-
class Solution:
    def hasPath(self, matrix, rows, cols, path):
        # write code here
        for i in range(rows):
            for j in range(cols):
                if matrix[i*cols+j] == path[0]:
                    if self.find(list(matrix),rows,cols,path[1:],i,j):
                        return True
        return False
    def find(self,matrix,rows,cols,path,i,j):
        if not path:
            return True
        matrix[i*cols+j]='0'
        if j+1<cols and matrix[i*cols+j+1]==path[0]:
            return self.find(matrix,rows,cols,path[1:],i,j+1)
        elif j-1>=0 and matrix[i*cols+j-1]==path[0]:
            return self.find(matrix,rows,cols,path[1:],i,j-1)
        elif i+1<rows and matrix[(i+1)*cols+j]==path[0]:
            return self.find(matrix,rows,cols,path[1:],i+1,j)
        elif i-1>=0 and matrix[(i-1)*cols+j]==path[0]:
            return self.find(matrix,rows,cols,path[1:],i-1,j)
        else:
            return False

机器人的运动范围

地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?

# -*- coding:utf-8 -*-
class Solution:
     
    def __init__(self):
        self.vis = {}
         
    def movingCount(self, threshold, rows, cols):
        # write code here
        return self.moving(threshold, rows, cols, 0, 0)
         
    def moving(self, threshold, rows, cols, row, col):
        if row/10 + row%10 + col/10 + col%10 > threshold:
            return 0
        if row >= rows or col >= cols or row < 0 or col < 0:
            return 0
        if (row, col) in self.vis:
            return 0
        self.vis[(row, col)] = 1
         
        return 1 + self.moving(threshold, rows, cols, row-1, col) + self.moving(threshold, rows, cols, row+1, col) + self.moving(threshold, rows, cols, row, col-1) + self.moving(threshold, rows, cols, row, col+1)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值