Python算法实战-牛客刷题-剑指offer通关

目录

 

二维数组中的查找

替换空格

从尾到头打印链表

重建二叉树

用两个栈实现队列

旋转数组的最小数字

斐波那契数列

跳台阶

变态跳台阶

矩阵覆盖

二进制中1的个数

数值的整数次方

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

链表中倒数第k个节点

反转链表

合并两个排序的链表

树的子结构

二叉树的镜像

顺时针打印矩阵

包含min函数的栈

栈的压入弹出序列

从上往下打印二叉树

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

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

复杂链表的复制

二叉搜索树与双向链表

字符串的排列

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

最小的k个数

连续子数组的最大和

整数中1出现的次数

把数组排成最小的数

丑数

第一次只出现1次的字符

数组中的逆序对

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

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

二叉树的深度

平衡二叉树

数组中只出现1次的数字

和为S的连续正数序列

和为S的两个数字

左旋转字符串

翻转单词顺序列

扑克牌顺子

孩子们的游戏

求1+2+。。。n

不用加减乘除做加法

把字符串转换成整数

数组中重复的数字

构建乘积数组

正则表达匹配

表示数值的字符串

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

链表中环的入口节点

删除链表中重复的节点

二叉树的下一个节点

对称的二叉树

按之字形顺序打印二叉树

把二叉树打印成多行

序列化二叉树

二叉搜索树的第K的节点

数据流中的中位数

滑动窗口的最大值

矩阵中的路径

机器人的运动范围

剪绳子


二维数组中的查找

题目描述

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

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

替换空格

题目描述

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

# -*- coding:utf-8 -*-
class Solution:
    # s 源字符串
    def replaceSpace(self, s):
        # write code here
        list_s = list(s)
        for index,i in enumerate(list_s):
            if i == " ":
                list_s[index] = "%20"
        s = "".join(list_s)
        return s

从尾到头打印链表

题目描述

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

# -*- 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
        arraylist = []
        head = listNode
        p = head
        if listNode == None:
            return []
        while p != None:
            arraylist.append(p.val)
            p = p.next
        arraylist.reverse()
        return arraylist

重建二叉树

题目描述

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{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):
        # write code here
        # TODO:检查是否为空,若只有1个值的时候直接返回
        if len(pre)==0:
            return None
        if len(pre)==1:
            return TreeNode(pre[0])
        for index,i in enumerate(tin):
            if i == pre[0]:
                root_index = index
                break
        root = TreeNode(pre[0])
        root_left_tin = tin[:root_index]
        root_right_tin = tin[root_index+1:]
        #这里可以改写成index用法,index输出序号位置,可以替代length
        root_left_pre = pre[1:len(root_left_tin)+1]
        root_right_pre = pre[len(root_left_tin)+1:]
        root.left = self.reConstructBinaryTree(root_left_pre,root_left_tin)
        root.right = self.reConstructBinaryTree(root_right_pre,root_right_tin)
        return root

用两个栈实现队列

题目描述

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

# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.stack1 = []
        self.stack2  = []
    def push(self, node):
        # write code here
        self.stack1.append(node)
        return self.stack1
    def pop(self):
        # return xx
        self.stack2.append(self.stack1[0])
        del self.stack1[0]
        return self.stack2[-1]
        

旋转数组的最小数字

题目描述

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

# -*- coding:utf-8 -*-
class Solution:
    def minNumberInRotateArray(self, rotateArray):
        # write code here
        if len(rotateArray)==0:
            return 0
        min = rotateArray[0]
        for i in rotateArray:
            if i<min:
                min = i
        return min
            

斐波那契数列

题目描述

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

n<=39

# -*- coding:utf-8 -*-
class Solution:
    def Fibonacci(self, n):
        # write code here
        first = 0
        second = 1
        while(n>0): #累加避免递归
            second = first + second
            first = second - first 
            n = n-1
        return first #这里之所以要返回first,是因为n差两个位置
            

跳台阶

题目描述

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

# -*- coding:utf-8 -*-
class Solution:
    def jumpFloor(self, number):
        # write code here
        first=1
        second =2
        while number>1:
            second = first+second
            first = second - first
            number = number-1
        return first

变态跳台阶

题目描述

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

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

矩阵覆盖

题目描述

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

比如n=3时,2*3的矩形块有3种覆盖方法:

# -*- coding:utf-8 -*-
class Solution:
    def rectCover(self, number):
        # write code here
        while number == 0:
            return number
        first = 1
        second = 2
        while number>=2:
            second = first + second
            first = second -first
            number = number-1
        return first
            
        #这里的number也是width,height固定
        
        

二进制中1的个数

题目描述

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

# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1(self, n):
        # write code here
        number = 0
        for i in range(32):
            #整数具有32位,右移n位相当于除以2的n次方,&为位运算,即比较2,3,4...32位是否为1
            if (n>>i) & 1 != 0:
                number = number+1
        return number

数值的整数次方

题目描述

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

保证base和exponent不同时为0

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

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

题目描述

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

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

链表中倒数第k个节点

题目描述

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

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

class Solution:
    def FindKthToTail(self, head, k):
        # write code here
        if (head== None) or (k<=0):
            return None
        p1 = head
        p2 = head
        count = 0
        #因为0本身就要运行一次,所以这里设置为k-1
        while count<k-1:
            if p2.next != None:
                p2 = p2.next
                count = count+1
            else:
                return None
        while p2.next != None:
            p1 = p1.next
            p2 = p2.next
        return p1

反转链表

题目描述

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

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    # 返回ListNode
    def ReverseList(self, pHead):
        # write code here
        #本来需要考虑pHead.next的情况,但是检查程序时发现下面包含了
        if pHead == None:
            return None
        pre = None
        cur = pHead
        while cur != None:
            temp = cur.next #先存起来准备遍历,不然不好向下走
            cur.next = pre #翻转链表
            pre = cur #总是标志前一个
            cur = temp #这里准备向下走
        return pre #最后的pre就是cur的所在地,curl在上一轮为None了
        
            
            
            
        
            

合并两个排序的链表

题目描述

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

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    # 返回合并后列表
    def Merge(self, pHead1, pHead2):
        # write code here
        mergeHead = ListNode(100) #设置一个足够大的数,前面head设为空节点,返回next即可
        cur = mergeHead
        while pHead1 and pHead2:
            #确定指针移到哪个链表上
            if pHead1.val <pHead2.val:
                mergeHead.next = pHead1
                pHead1 = pHead1.next
            else:
                mergeHead.next = pHead2
                pHead2 = pHead2.next
            mergeHead = mergeHead.next #指针要移动
        if pHead1 == None:
            mergeHead.next = pHead2
        else:
            mergeHead.next = pHead1
        # return mergeHead 如果这里这么返回mergeHead指向链表的部分,不行
        return cur.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):
        # write code here
        if pRoot1 == None or pRoot2 ==None:
            return False
        # 左右子树是否存在其子结构,这里已经不是空树了
        return self.IsSubtree(pRoot1,pRoot2) or self.HasSubtree(pRoot1.left,pRoot2) or self.HasSubtree(pRoot1.right,pRoot2)
        
    def IsSubtree(self,A,B):
        if B==None:
            return True
        if A == None or A.val!=B.val:
            return False
        return self.IsSubtree(A.left,B.left) and self.IsSubtree(A.right,B.right)
        

二叉树的镜像

题目描述

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

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回镜像树的根节点
    def Mirror(self, root):
        # write code here
        if not root:
            return None
        root.left,root.right = root.right,root.left #python支持对象的交换
        self.Mirror(root.left) #因为已经交换过了,直接在下一层进行交换
        self.Mirror(root.right)
        return root
    

顺时针打印矩阵

题目描述

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下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):
        # write code here
        res = []
        if matrix == None:
            return res
        low,high,left,right = 0,len(matrix)-1,0,len(matrix[0])-1 #进行方向标记
        
        while low<=high and left<=right:
            # 先向右
            for i in range(left,right+1):
                res.append(matrix[low][i])
            # 再向下
            for i in range(low+1,high+1):
                res.append(matrix[i][right])
            # 再向左(考虑只有1行的情况,避免重复访问)
            if low<high:
                for i in range(right-1,left-1,-1):
                    res.append(matrix[high][i])
            #再向上(考虑只有1列)
            if left<right:
                for i in range(high-1,low,-1):
                    res.append(matrix[i][left])
            left = left+1
            right = right-1
            low = low+1
            high = high-1
        return res
                
        
        
        
            
            

包含min函数的栈

题目描述

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

注意:保证测试中不会当栈为空的时候,对栈调用pop()或者min()或者top()方法。

# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.stack = []
        self.min_stack = []
    def push(self, node):
        # write code here
        self.stack.append(node)
        if self.min_stack ==[] or node<=self.min_stack[-1]:
            self.min_stack.append(node)
    def pop(self):
        # write code here
        if self.stack == []:
            return None
        #这里一定不能忘记判断
        if self.stack[-1]==self.min_stack[-1]:
            self.min_stack.pop()
        self.stack.pop()
    def top(self):
        # write code here
        if self.stack ==[]:
            return None
        return self.stack[-1]
    def min(self):
        # write code here
        return self.min_stack[-1]

栈的压入弹出序列

题目描述

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列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):
        # write code here
        if not pushV or len(popV) != len(pushV):
            return False
        new_stack = [] #用于模拟塞入数据
        #j=0
        for i in pushV:
            new_stack.append(i)
            #while new_stack[-1] == popV[0] and len(new_stack):
            while len(new_stack) and new_stack[-1] == popV[0]:
                new_stack.pop()
                popV.pop(0) #pop顺序也要移动,传入0代表从左边出栈
        if len(new_stack):
            return False
        return True
                

从上往下打印二叉树

题目描述

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

# -*- 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):
        # write code here
        #广度遍历
        if not root:
            return []
        val = [] #存入值
        node = [root] #存入节点
        while len(node):
            t = node.pop(0) #队列的思想
            val.append(t.val)
            if t.left:
                node.append(t.left)
            if t.right:
                node.append(t.right)
        return val

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

题目描述

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

# -*- coding:utf-8 -*-
class Solution:
    def VerifySquenceOfBST(self, sequence):
        # write code here
        if not sequence:
            return False
        return self.IsBST(sequence,0,len(sequence)-1) #判断是否是二叉搜索树
    
    def IsBST(self,array,start,end):
        if start >= end:
            return True # 可以直接比较,就一个节点
        #下面应该寻找i分界线,分为左右子树,准备递归
        i = end -1
        #遍历时候先遍历右子树,所以都比根节点小,从后往前找分界点
        while i>start and array[i]>array[end]:
            i = i-1
        #下面遍历前半部分,即左子树
        j = 0
        for j in range(i-1,start-1,-1):
            if array[j]>array[end]:
                return False
        return self.IsBST(array,start,i-1) and self.IsBST(array,i,end-1)
            
            
    
        
        

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

题目描述

输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。

# -*- 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):
        # write code here
        #本质是个深度遍历
        if not root:
            return []
        if 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
            
        
        
        

复杂链表的复制

题目描述

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

# -*- coding:utf-8 -*-
# class RandomListNode:
#     def __init__(self, x):
#         self.label = x
#         self.next = None
#         self.random = None
class Solution:
    # 返回 RandomListNode
    def Clone(self, pHead):
        # write code here
        if not pHead:
            return None
        cur = pHead
        # 进行节点的复制
        while cur!=None:#这里不能使用not
            clone = RandomListNode(cur.label)
            nextnode = cur.next
            cur.next = clone
            clone.next = nextnode
            cur = nextnode #进行遍历插入
        # 第二趟遍历,进行random的复制,random存在原random的下一个节点
        cur = pHead
        while cur!= None:
            cur.next.random = cur.random.next if cur.random else None
            cur = cur.next.next
        # 进行拆分链表,通过断开链接的方式
        cur = pHead
        cloneList = pHead.next
        while cur!=None:
            clone = cur.next
            cur.next = clone.next
            clone.next = clone.next.next if clone.next else None
            cur = cur.next
        return cloneList
            
            
        

二叉搜索树与双向链表

题目描述

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。

要求不能创建任何新的结点,只能调整树中结点指针的指向。

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def Convert(self, root):
        # write code here
        # 下面是递归版本
        '''if not pRootOfTree:
            return None
        if not pRootOfTree.left and not pRootOfTree.right:
            return pRootOfTree
        # 先遍历左子树
        left = self.Convert(pRootOfTree.left)
        p = left
        while left and p.right:
            # 找到左子树遍历的最右节点,也就是对应链表的最右边
            p = p.right
        # 加入根节点
        if left:
            p.right = pRootOfTree
            pRootOfTree.left = p
        right = self.Convert(pRootOfTree)
        # 加入右子树
        if right:
            right.left = pRootOfTree
            pRootOfTree.right = right
        return left if left else root'''
        # 非递归要掌握
        if not root:
            return None
        stack= []
        resStack =[]
        p = root
        # 这个中序遍历的非递归写的太好; 
        while p or stack:
            if p:
                stack.append(p)
                p = p.left
            else:
                node = stack.pop()
                resStack.append(node)
                p = node.right
                
        resP = resStack[0]
        while resStack:
            top = resStack.pop(0) #从前向后pop()
            if resStack:
                top.right = resStack[0]
                resStack[0].left = top
        return resP
            
                

字符串的排列

题目描述

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

输入描述:

输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
# -*- coding:utf-8 -*-
class Solution:
    def Permutation(self, ss):
        # write code here
        if len(ss) <=1:
            return ss
        res = set() # 去重
        for i in range(len(ss)):
            for j in self.Permutation(ss[:i]+ss[i+1:]):
                res.add(ss[i]+j)
        return sorted(list(res))
            

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

题目描述

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

# -*- coding:utf-8 -*-
class Solution:
    def MoreThanHalfNum_Solution(self, numbers):
        # write code here
        partlength = int(len(numbers)/2)
        # 使用一个字典存储个数
        #dictnum = collections.defaultdict()
        dictnum = {}
        for i in numbers:
            #dictnum[numbers[i]].value +1 if value else 0
            if i not in dictnum.keys():
                dictnum[i] = 1
            else :
                dictnum[i] = dictnum[i] + 1
        # 遍历检查
        #for key , value in dictnum:
            #if value > partlength:
                #return key
        #return 0
        for key,value in dictnum.items():
            if value >= partlength+1:
                return key
        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):
        # write code here
        if k > len(tinput):
            return []
        
        sortedTinput = sorted(tinput)
        return sortedTinput[:k]

连续子数组的最大和

题目描述

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

# -*- coding:utf-8 -*-
class Solution:
    def FindGreatestSumOfSubArray(self, array):
        # write code here
        arraysum = []
        if not array:
            return None
        if len(array)==1:
            return array[0]
        maxsum = float('-inf')
        for i in range(len(array)):
            # 都记录下来即可
            if maxsum<array[i]:
                maxsum = array[i]
            temp = array[i]
            #maxsum都是与和作比较,但是没有和数作比较,所以前面得加上判断
            for j in array[i+1:]:
                temp = temp + j
                if temp > maxsum:
                    maxsum = temp
        return maxsum
            
            
            

整数中1出现的次数

题目描述

求出1~13的整数中1出现的次数,并算出100~1300的整数中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):
        # write code here
        # 每次都是考虑一个数位上的1出现次数
        count = 0 #1的个数
        i = 1 # 切分位置
        cur,after,before = 0,0,0
        #这里想百位就好理解,即i =100
        while n/i !=0:
            cur = (n/i) %10 #当前位
            before = n/(i*10) # 高位
            after = n-(n/i)*i # 低位
            if cur ==0:
                count +=before*i #百位上的1仅由高位决定
            elif cur ==1:
                count +=before*i + after+1 # 百位上的1由高位低位共同决定
            else:
                count+= (before+1)*i #仅由高位决定
                
            i = i*10
            
        return count

把数组排成最小的数

题目描述

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

# -*- coding:utf-8 -*-
class Solution:
    def PrintMinNumber(self, numbers):
        # write code here
        # 不要想多,就是两两比较,最后串起来
        length = len(numbers)
        if length ==0:
            return ''
        # 最后一个不用比较
        for i in range(length-1):
            for j in range(length-i-1):
                if int(str(numbers[j])+str(numbers[j+1]))>int(str(numbers[j+1])+str(numbers[j])):
                    numbers[j+1],numbers[j] = numbers[j],numbers[j+1]
                    
        return int(''.join(str(i) for i in numbers))

丑数

题目描述

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

# -*- coding:utf-8 -*-
class Solution:
    def GetUglyNumber_Solution(self, index):
        # write code here
        if index<=0:
            return False
        if index ==1:
            return 1
        ugly = [1]
        indextwo = 0
        indexthree = 0
        indexfive = 0
        for i in range(1,index):
            # 没必要维护三个队列,记录位置即可
            ugly.append(min(ugly[indextwo]*2,ugly[indexthree]*3,ugly[indexfive]*5))
            if ugly[i] == ugly[indextwo]*2:
                # 如果是从某个队列添加的,则该队列+1,之所以可以这样是因为基础数变了,以丑数队列为基准
                # 丑数队列中总是最小的数*2,3,5得出的
                indextwo +=1
            if ugly[i] ==ugly[indexthree]*3:
                indexthree +=1
            if ugly[i] == ugly[indexfive]*5:    
                indexfive +=1
        return ugly[index-1]

第一次只出现1次的字符

题目描述

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

# -*- coding:utf-8 -*-
class Solution:
    def FirstNotRepeatingChar(self, s):
        # write code here
        if len(s)==0:
            return -1
        if len(s)==1:
            return 0
        dic = {}
        for i in s:
            if i not in dic.keys():
                dic[i] = 1
            else:
                dic[i] +=1
        # 这里注意字典是无序的
        for index,i in enumerate(s):
            if dic[i] ==1:
                return index
        return -1
            

数组中的逆序对

题目描述

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

输入:1,2,3,4,5,6,7,0 输出 :7

# -*- coding:utf-8 -*-
count = 0
#class Solution:
    #def InversePairs(self, data):
        # write code here
        #if len(data)<=1:
            #return 0
        #count  = 0
        #for cur in range(len(data)-1,0,-1): # 当前数,从后向前
            #for j in range(len(data)-len(data[cur:])):
                #if data[j] > data[cur]:
                    #count +=1
        #return count % 1000000007
        #count = 0
class Solution:
    def InversePairs(self, data):
        global count
        self.MergeSort(data)
        return count%1000000007
    
    def MergeSort(self,lists):
        global count
        if len(lists) <= 1:
            return lists
        num = int(len(lists)/2)
        left = self.MergeSort(lists[:num])
        right = self.MergeSort(lists[num:])
        r, l=0, 0
        result=[]
        while l<len(left) and r<len(right):
            if left[l] < right[r]:
                result.append(left[l])
                l += 1
            else:
                result.append(right[r])
                r += 1
                # 剩余的左边的数都大于右边的那个数 所以加len(left)-l
                count += len(left)-l
        result += right[r:] # 这里是某个数组过长
        result += left[l:]
        return result

        
        
        

        

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

题目描述

输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    def FindFirstCommonNode(self, pHead1, pHead2):
        # write code here
        cur1 = pHead1
        cur2 = pHead2
        if cur1==None or cur2==None:
            return None
        while cur1!=cur2:
            # ENTJ : 如果没有公共点,两个指针会同时到达null,然后跳出循环,不会死循环的
            # 比较下一个
            cur1 = cur1.next
            cur2 = cur2.next
            if cur1 != cur2:
                # 这里有个特殊情况,即二者有一方为None的时候,链接两个链表使其等长
                # 这里已经是next了,无需再写cur.next
                if cur1 == None: cur1 = pHead2
                if cur2 == None: cur2 = pHead1
        return cur1

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

题目描述

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

# -*- coding:utf-8 -*-
class Solution:
    def GetNumberOfK(self, data, k):
        # write code here
        if len(data)==0 or k>data[-1]:
            return 0
        mid = 0
        left =0
        right =len(data)-1
        count =0
        while left<=right:
            mid = int((left+right)/2)
            if data[mid]<k:
                # 中位数小于指定数字
                left = mid+1
            elif data[mid]>k:
                right = mid-1
            else:
                break
        # 找到了就向前向后找
        if left <=right:
            for i in range(mid,-1,-1):
                if data[i] ==k:
                    count+=1
                else:
                    # 找到第一个就别找了
                    break
            for i in range(mid+1,len(data)):
                if data[i]==k:
                    count +=1
                else:
                    break
                    
        return count
                
                
 

二叉树的深度

题目描述

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

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def TreeDepth(self, pRoot):
        # write code here
        #if not pRoot:
         #   return 0
        #left = self.TreeDepth(pRoot.left)
        #right = self.TreeDepth(pRoot.right)
        #res = left + 1 if left>right else right+1
        #return res
        # 下面使用层序遍历
        if not pRoot:
            return 0
        high = 0
        queue = [pRoot]
        while queue!= []:
            childqueue = []
            for node in queue:
                if node.left:
                    childqueue.append(node.left)
                if node.right:
                    childqueue.append(node.right)
            queue = childqueue
            high +=1
        return high
            
        
        
        

平衡二叉树

题目描述

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

注意:

在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树

# -*- 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):
        # write code here
        if not pRoot:
            return True # 前提搞清楚空子树是不是平衡二叉树
        left = self.depth(pRoot.left)
        right = self.depth(pRoot.right)
        #if (left-right) != (-1) or (left-right)!=1:
        if abs(left - right) >1:
            return False
        return self.IsBalanced_Solution(pRoot.left) and self.IsBalanced_Solution(pRoot.right)
        
    
    
    def depth(self,root):
        if not root:
            return 0
        left = self.depth(root.right)
        right = self.depth(root.left)
        return max(left,right)+1

        
        
        
        

数组中只出现1次的数字

题目描述

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

# -*- coding:utf-8 -*-
class Solution:
    # 返回[a,b] 其中ab是出现一次的两个数字
    def FindNumsAppearOnce(self, array):
        # write code here
        if len(array)<4:
            return False
        from collections import Counter
        array1 =Counter(array)
        res =[]
        for key,value in array1.items():
            if value ==1:
                res.append(key)
                
        return res

和为S的连续正数序列

题目描述

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

输出描述:

输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
# -*- coding:utf-8 -*-
class Solution:
    def FindContinuousSequence(self, tsum):
        # write code here
        res = []
        # 最大的两个数应该是二分之一
        for i in range(int(tsum/2)+1,0,-1):
            # 末尾数
            s = i
            sequence = [i] # 用于存放单个序列
            # 起始数从后向前
            for j in range(i-1,0,-1):
                # 向前遍历
                sequence.append(j)
                s+=j
                if s==tsum:
                    sequence = sorted(sequence)# 序列内排序
                    res.append(sequence)
                    break
                if s>tsum:
                    break
         # 下面进行序列间排序
        res = sorted(res,key=lambda x:x[0])
        # res = [[],[]]
        return res

和为S的两个数字

题目描述

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

输出描述:

对应每个测试案例,输出两个数,小的先输出。
# -*- coding:utf-8 -*-
class Solution:
    def FindNumbersWithSum(self, array, tsum):
        # write code here
        plow = 0
        phigh =len(array)-1
        res = []
        if not array:
            return []
        if array[phigh-1]+array[phigh]<tsum:
            return []
        # 下面使用双指针思想
        while plow<phigh:
            sequence = []
            if array[plow]+array[phigh]==tsum:
                sequence.append(array[plow])
                sequence.append(array[phigh])
                res.append(sequence)
                plow +=1
                phigh-=1
            elif array[plow]+array[phigh]>tsum:
                phigh-=1 #一侧指针动
            else:
                plow+=1
        # 输出乘积最小的数
        res = sorted(res,key = lambda x:x[0]*x[1]) 
        # res=[[]]
        return res[0] if res else []

左旋转字符串

题目描述

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

# -*- coding:utf-8 -*-
class Solution:
    def LeftRotateString(self, s, n):
        # write code here
        if n >len(s):
            return ""
        if not s:
            return ""
        sp1,sp2 = s[:n],s[n:]
        res = sp2+sp1
        return res
        

翻转单词顺序列

题目描述

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

# -*- coding:utf-8 -*-
class Solution:
    def ReverseSentence(self, s):
        # write code here
        s_lis = s.split(' ')
        s_lis.reverse() #这里注意返回的是一个None,是对原有序列的改变
        res = ' '.join(x for x in s_lis)
        return res
        

扑克牌顺子

题目描述

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):
        # write code here
        if numbers ==[]:
            return False
        dic = {
            'J':11,
            'Q':12,
            'K':13,
            'A':1
        }
        # 进行异常值替换
        for number in numbers:
            if number in dic.keys():
                number = dic[number]
                
        # 下面检查是不是顺子
        count = 0 #统计为王的数量
        cz = [] # 统计差值
        numbers.sort()
        for i in range(5):
            if numbers[i]==0:
                count +=1
        if count==4:
            return True
        # 存入差值
        for i in range(count,4):
            cz.append(numbers[i+1]-numbers[i])
        for i in cz:
            if i==0:
                return False
            if i ==1:
                continue
            if i >1:
                count =count -(i-1)
        if count !=0:
            return False
        return True
            
        

孩子们的游戏

题目描述

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

注意:

如果没有小朋友,请返回-1

# -*- coding:utf-8 -*-
class Solution:
    def LastRemaining_Solution(self, n, m):
        # write code here
        if n<1:
            return -1
        n_child = [i for i in range(n)]
        while len(n_child) >1:
            gift_child = (m-1)%len(n_child)
            # 取完礼物就走,根据索引删除,这里不对,不是从0重头唱歌,而是下一位接着唱
            n_child.pop(gift_child)
            # 保证下一次唱歌的为列表开头
            n_child = n_child[gift_child:]+n_child[:gift_child]
        return n_child[0]

                
                
            

求1+2+。。。n

题目描述

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

# -*- coding:utf-8 -*-
class Solution:
    def Sum_Solution(self, n):
        # write code here
        return sum(range(n+1))

不用加减乘除做加法

题目描述

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

# -*- coding:utf-8 -*-
class Solution:
    def Add(self, num1, num2):
        # write code here
        MAX = 0x7fffffff # 最大整数
        mask = 0xffffffff # 求补码
        while num2 != 0: # 直到无进位
            num1, num2 = (num1 ^ num2), ((num1 & num2) << 1)
            num1 = num1 & mask #数
            num2 = num2 & mask # 进位
        return num1 if num1 <= MAX else ~(num1 ^ mask)

                    
            
        

把字符串转换成整数

题目描述

将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0

输入描述:

输入一个字符串,包括数字字母符号,可以为空
+2147483647
1a33

输出描述:

如果是合法的数值表达则返回该数字,否则返回0
# -*- coding:utf-8 -*-
class Solution:
    def StrToInt(self, s):
        # write code here
        if s =='':
            return 0
        numList = ['0','1','2','3','4','5','6','7','8','9'] # 数字和index要相对应
        flag = 1
        if s[0] == '+' and len(s)>1: # 先解决符号问题
            flag = 1
            s = s[1:]
        if s[0] == '-' and len(s)>1:
            flag = -1
            s = s[1:]
        # 下面进行求和
        sum1 = 0
        for i in s:
            if i in numList:
                sum1 = sum1*10+ numList.index(i)
            else:
                return 0
        return flag*sum1
       

数组中重复的数字

题目描述

在一个长度为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):
        # write code here
        from collections import Counter
        count = dict(Counter(numbers))
        for key ,value in count.items():
            if value > 1:
                duplication[0] =key
                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]。不能使用除法。(注意:规定B[0] = A[1] * A[2] * ... * A[n-1],B[n-1] = A[0] * A[1] * ... * A[n-2];)

# -*- coding:utf-8 -*-
class Solution:
    def multiply(self, A):
        # write code here
        if not A:
            return []
        # 题目的意思是B[n] = B[n-1]*A[n-1]*A[i+1]...A[n-1],少了A[i]那一项的乘积
        # 不要看注意内容,太容易带偏
        B = [1]*len(A)
        # 将B做切割,先看A[i-1]部分,记得i>=0
        for i in range(1,len(A)):
            B[i] = B[i-1]*A[i-1]
        # 下面看后面,当i = n-1时候,没有后面,n-2时候*A[n-1],n-3时候*A[n-2]*A[n-1]
        tmp = 1 # 暂存乘积结果
        for i in range(len(A)-2,-1,-1):
            tmp = tmp*A[i+1]
            B[i] = B[i]*tmp
            
        return B
        
        # B[1]=A[0];B[2]=A[0]*A[1]

        #if len(A)<=0:
        #    return None
        #B = [1] *len(A)
        #if len(A)==1:
        #    B = A
        #    return B
        #for i in A:
        #    B[0] =B[0]*i
       # for i in range(1,len(B)):
        #    for j in range(i):
        #        B[i] = B[i]*A[j]
                
       # return B
         #这题和我想的不一样啊,我觉得题目有问题
         
            
            


 

正则表达匹配

题目描述

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

# -*- coding:utf-8 -*-
class Solution:
    # s, pattern都是字符串
    def match(self, s, pattern):
        # write code here
        if len(s)==0 and len(pattern)==0:
            return True
        elif len(s)!=0 and len(pattern)==0:
            return False
        elif len(s)==0 and len(pattern)!=0:
            if len(pattern)>1 and pattern[1]=='*':
                # 因为s为空
                return self.match(s,pattern[2:])
            else:
                return False
        else:
            # pattern 第二个字符为*
            if len(pattern)>1 and pattern[1] =='*':
                # s与pattern首位不同
                if s[0]!=pattern[0] and pattern[0]!='.':
                    return self.match(s,pattern[2:])
                else:
                    # pattern中*为空;pattern中*为1;【s后移1个,*可以多位匹配】
                    return self.match(s,pattern[2:]) or self.match(s[1:],pattern[2:]) or self.match(s[1:],pattern)
            else:
                if s[0]==pattern[0] or pattern[0]=='.':
                    return self.match(s[1:],pattern[1:])
                else:
                    return False
                    
        

表示数值的字符串

题目描述

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

# -*- coding:utf-8 -*-
class Solution:
    def isNumeric(self, s):
        # write code here
        import re
        pattern = '[+-]?[0-9]*([.][0-9]*)?([eE][+-]?[0-9]+)?'
        return True if re.match(pattern,s).group() == s else False

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

题目描述

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

输出描述:

如果当前字符流没有存在出现一次的字符,返回#字符。
# -*- coding:utf-8 -*-
class Solution:
    # 返回对应char
    s = ''
    def FirstAppearingOnce(self):
        # write code here
        from collections import Counter
        count = Counter(self.s)
        for i in self.s:
            if count[i] ==1:
                return i
        return '#'
    def Insert(self, char):
        # write code here
        self.s += char

链表中环的入口节点

题目描述

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

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    def EntryNodeOfLoop(self, pHead):
        # write code here
        fast = pHead
        low = pHead
        while(fast!=None and fast.next!=None):
            fast = fast.next.next
            low = low.next
            if fast ==low:
                break
        # 根据上面的退出条件写一下!!!
        if fast==None or fast.next ==None:
            return None
        low = pHead
        while fast!=low:
            fast = fast.next
            low = low.next
            
        return low

删除链表中重复的节点

题目描述

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表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):
        # write code here
        if not pHead:
            return None
        pPreNode = None #先前链接节点
        pNode = pHead #遍历节点
        while pNode:
            pNext = pNode.next
            needDelete = False
            # 判断是否相等
            if pNext and pNode.val ==pNext.val:
                needDelete = True
            if not needDelete:
                # 如果没有重复
                pPreNode = pNode
                pNode = pNext
            else:
                #核心如果有重复
                deleteVal = pNode.val
                deleteNode = pNode #需要把源节点一起删除
                # 删除操作
                while deleteNode and deleteNode.val ==deleteVal:
                    pNext = deleteNode.next #保存后一个节点
                    del deleteNode # 删除操作
                    deleteNode = pNext #删除后移
                if not pPreNode:
                    #如果连头结点都删掉了
                    pHead = pNext # 就从下一个节点开始
                    
                else:
                    pPreNode.next = pNext
                pNode = pNext # 从该节点开始遍历
        return pHead
                    

            
                
            

二叉树的下一个节点

题目描述

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

# -*- 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):
        # write code her
        if not pNode:
            return None
        if pNode.right:
            # 存在右子树
            pNode = pNode.right
            while pNode.left:
                pNode = pNode.left
            return pNode
        # 如果不存在右子树,检查其是否是父节点的左孩子
        while pNode.next:
            pRoot = pNode.next #指向父节点
            if pRoot.left == pNode:
                return pRoot
            else:
                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):
        # write code here
        # 这题使用递归
        if not pRoot:
            return True
        return self.issymmer(pRoot.left,pRoot.right)
    def issymmer(self,left,right):
        if not left and not right:
            return True
        if not left or not right:
            return False
        # 值相等且镜像位置的子树相等
        return left.val == right.val and self.issymmer(left.left,right.right) and self.issymmer(left.right,right.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):
        # write code here
        if not pRoot:
            return [] # 一般不要轻易返回None值
        queue = [pRoot]
        result = []
        # 先层序遍历存进去再说,但稍微不同的是存列表
        while queue:
            res = []
            nextqueue = []
            for i in queue:
                res.append(i.val)
                if i.left:
                    nextqueue.append(i.left)
                if i.right:
                    nextqueue.append(i.right)
            queue = nextqueue
            result.append(res)
            
        for i in range(len(result)):
            if i %2!=0:
                # 逆序
                result[i].reverse() # 这个是对源数据进行反向,不会返回数据,注意reversed返回的是个迭代器
        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):
        # write code here
        if not pRoot:
            return []
        
        result =[]
        queue = [pRoot]
        while queue:
            res = []
            nextqueue = []
            for i in queue:
                res.append(i.val)
                if i.left:
                    nextqueue.append(i.left)
                if i.right:
                    nextqueue.append(i.right)
            queue = nextqueue
            result.append(res)
        return result

序列化二叉树

题目描述

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

注意:

二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#),以 ! 表示一个结点值的结束(value!)。

二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。
举例:例如,我们可以把一个只有根节点为1的二叉树序列化为"1,",然后通过自己的函数来解析回这个二叉树

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    flag = -1 # s标识位
    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 #一定要加self
        lis = s.split(',')
        if self.flag >=len(s):
            # 当指针超过s时
            return None
        root = None # 设置一个节点
        if lis[self.flag]!= '#':
            root = TreeNode(int(lis[self.flag])) # 注意TreeNOde传入的是一个值
            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.result = []
    def KthNode(self, pRoot, k):
        # write code here
        # 中序遍历会得到从小到大的顺序
        #strr = self.KthNode(pRoot.left)+str(pRoot.val)+self.KthNode(pRoot.right)
        #global result
        #result = [] # 不能设在函数之外
        self.Zhongxu(pRoot)
        if k<=0 or len(self.result)<k: # 如果超过strr范围,k<=0一般放前面
            return None
        return self.result[k-1]
    
    def Zhongxu(self,pRoot):
        if not pRoot:
            return None
        self.Zhongxu(pRoot.left)
        self.result.append(pRoot)
        self.Zhongxu(pRoot.right)
        
        

数据流中的中位数

题目描述

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

# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.lis = []
        self.count = 0
    def Insert(self, num):
        # write code here
        self.lis.append(num)
        self.count +=1
    def GetMedian(self,n=None):
        # write code here
        self.lis = sorted(self.lis)
        if self.count == 0:
            return 0
        if self.count%2!=0:
            return self.lis[int(self.count/2)]
        else:
            return (self.lis[self.count/2]+self.lis[self.count/2 -1])/2.0

滑动窗口的最大值

题目描述

给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{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):
        # write code here
        # 存在len(num)-size+1个滑动窗口
        if size>len(num):
            return []
        if size<=0:
            return []
        maxlis = []
        for i in range(len(num)-size+1):
            # 滑动窗口可以看做切片
            slic = num[i:i+size]
            maxlis.append(max(slic))
        return maxlis
            

矩阵中的路径

题目描述

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如

矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。

# -*- coding:utf-8 -*-
class Solution:
    def hasPath(self, matrix, rows, cols, path):
        # write code here
        # 标志位
        flag = [False]*rows*cols
        for i in range(rows):
            for j in range(cols):
                # 找起始点
                # 为什么不一样??
                if self.judge(list(matrix),rows,cols,path,i,j,0,flag):
                    # 一维数组来判断,k是path起始位
                    return True
        return False
    
    def judge(self,matrix,rows,cols,path,i,j,k,flag):
        index = i*cols+j #标志位
        # 递归终止条件
        if i<0 or j<0 or i>=rows or j>=cols or matrix[index]!=path[k] or flag[index] ==True:
            return False
        if k == len(path)-1:
            return True
        # 首标志位为True
        flag[index] = True
        # 判断是否能走
        if self.judge(matrix,rows,cols,path,i-1,j,k+1,flag) or self.judge(matrix,rows,cols,path,i+1,j,k+1,flag) or self.judge(matrix,rows,cols,path,i,j-1,k+1,flag) or self.judge(matrix,rows,cols,path,i,j+1,k+1,flag):
            return True
        flag[index] = False # 不通则还原标志位
        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 movingCount(self, threshold, rows, cols):
        # write code here
       # count = rows*cols # 假设一开始全能到达
        #for i in range(rows):
           # for j in range(cols):
            #    if self.chai(i) + self.chai(j) > threshold:
             #       count -=1
       # return count
    
    #def chai(self,number):
      #  # 这个作用是对数字进行拆分,并返回其和
       # summ = 0
       # lis = map(int,list(str(number)))
       # summ = sum(lis)
       # return summ
    def __init__(self):
        self.count = 0
        
    def movingCount(self, threshold, rows, cols):
        arr = [[1 for _ in range(cols)] for _ in range(rows)]
        self.findway(0,0,threshold,arr) # 如果能到达则设为1
        return self.count
    
    def findway(self,i,j,threshold,arr):
        # 递归停止条件
        if i<0 or j<0 or i>=len(arr) or j >=len(arr[0]):
            return 
        lis1 = list(map(int,list(str(i)))) # 字符串变数字的优化解法
        lis2 = list(map(int,list(str(j))))
        sum1 = sum(lis1)
        sum2 = sum(lis2)
        if sum1 +sum2>threshold or arr[i][j]!=1:
            return 
        # 如果可以走
        self.count +=1
        arr[i][j] = 0
        # 下面就是继续走的递归了
        self.findway(i+1,j,threshold,arr)
        self.findway(i-1,j,threshold,arr)
        self.findway(i,j+1,threshold,arr)
        self.findway(i,j-1,threshold,arr)
        
        
        
        

剪绳子

题目描述

给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],...,k[m]。请问k[0]xk[1]x...xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。

输入描述:

输入一个数n,意义见题面。(2 <= n <= 60) 8

输出描述:

输出答案。18
# -*- coding:utf-8 -*-
class Solution:
    def cutRope(self, number):
        # write code here
        # 这题可以用贪婪,但我选择动态规划
        if number <=1:
            return 0
        if number==2:
            return 1
        if number ==3:
            return 2
        # 下面是number>=4的情况
        space = [0]* (number+1) # 辅助空间需要包含0
        space[0] = 0
        space[1] = 1
        space[2] = 2
        space[3] = 3 #这里f(x) = max(f(x-i)*f(i)),这里两个子部分可以不切,所以和上面值不同
        for i in range(4,number+1):
            maxx = 0 # 用于记录每一个f(i)的最大值
            for j in range(i/2+1): # 这里是对f(i)的切分,本质还是max(f(x-i)*f(i))
                maxx = max(maxx,space[j]*space[i-j])
            space[i] = maxx
        return space[number]
            
            
                
 

猜你喜欢

转载自blog.csdn.net/weixin_40539952/article/details/106438594