剑指offer代码下

#40.py

# 输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
# 示例 1:
# 输入:arr = [3,2,1], k = 2
# 输出:[1,2] 或者 [2,1]
# 示例 2:
# 输入:arr = [0,1,2,1], k = 1
# 输出:[0]
class Solution:
    def getLeastNumbers(self, arr: List[int], k: int) -> List[int]:
        q=[]
        heapq.heapify(arr)
        for i in range(k):
            q.append(heapq.heappop(arr))
        res3=q
        return res3

#41.py

# 输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。

# 要求时间复杂度为O(n)。
# 示例1:

# 输入: nums = [-2,1,-3,4,-1,2,1,-5,4]
# 输出: 6
# 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        dp=[0]*len(nums)
        dp[0]=nums[0]
        
        for i in range(1,len(nums)):
            dp[i]=max(dp[i-1]+nums[i],nums[i])
        return max(dp)

#42.py

# 输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。
# 例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。
# 示例 1:
# 输入:n = 12
# 输出:5
# 示例 2:
# 输入:n = 13
# 输出:6
class Solution:
    def countDigitOne(self, n: int) -> int:
        res=0
        digit=1
        high,cur,low=n//10,n%10,0
        while high!=0 or cur!=0:
            if cur == 0: res += high * digit
            elif cur == 1: res += high * digit + low + 1
            else: res += (high + 1) * digit
            low+=cur*digit
            cur=high%10
            high=high//10
            digit*=10
        return res

#43.py

# 输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。

# 例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。

#  

# 示例 1:

# 输入:n = 12
# 输出:5
# 示例 2:

# 输入:n = 13
# 输出:6
class Solution:
    def countDigitOne(self, n: int) -> int:
        res=0
        digit=1
        high,cur,low=n//10,n%10,0
        while high!=0 or cur!=0:
            if cur == 0: res += high * digit
            elif cur == 1: res += high * digit + low + 1
            else: res += (high + 1) * digit
            low+=cur*digit
            cur=high%10
            high=high//10
            digit*=10
        return res

#44.py

# 数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。

# 请写一个函数,求任意第n位对应的数字。

#  

# 示例 1:

# 输入:n = 3
# 输出:3
# 示例 2:

# 输入:n = 11
# 输出:0
class Solution:
    def findNthDigit(self, n: int) -> int:
        #1位数字1-9一共9个(1*9)
        #2位数字10-99一共90个 (2*90)
        #3位数字100-999一共900个(3*900)
        #4位1000-9999,9000个(4*9000)
        
        digit=1
        start=1
        count=9
        while n>count:
            n=n-count
            digit+=1
            start*=10
            count=digit*start*9
        return int(str(start+(n-1)//digit)[(n-1)%digit])

#45.py

# 数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。
# 请写一个函数,求任意第n位对应的数字。
# 示例 1:
# 输入:n = 3
# 输出:3
# 示例 2:
# 输入:n = 11
# 输出:0
class Solution:
    def minNumber(self, nums: List[int]) -> str:
        def rules(a,b):
            if a+b>b+a:return 1
            if a+b<b+a:return -1
            else:return 0

        nums=[str(i) for i in nums]

        nums.sort(key=functools.cmp_to_key(rules))
        return "".join(nums)

#46.py

# 给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。

# 示例 1:

# 输入: 12258
# 输出: 5
# 解释: 12258有5种不同的翻译,分别是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"
class Solution:
    def translateNum(self, num: int) -> int:
        s=str(num)
        res=1
        tmp=1
        for i in range(2,len(s)+1):
            if "10" <= s[i - 2:i] <= "25":
                c=res+tmp
            else:
                c=res
            tmp=res
            res=c

        return res

#47.py

# 在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?

# 示例 1:

# 输入: 
# [
#   [1,3,1],
#   [1,5,1],
#   [4,2,1]
# ]
# 输出: 12
# 解释: 路径 1→3→5→2→1 可以拿到最多价值的礼物
class Solution:
    def maxValue(self, grid: List[List[int]]) -> int:
        m=len(grid)
        n=len(grid[0])
        dp=[[0]*n for _ in range(m)]
        dp[0][0]=grid[0][0]
        for i in range(1,n):
            dp[0][i]=dp[0][i-1]+grid[0][i]
        for i in range(1,m):
            dp[i][0]=dp[i-1][0]+grid[i][0]
        for i in range(1,len(grid)):
            for j in range(1,len(grid[0])):
                dp[i][j]=max(dp[i-1][j],dp[i][j-1])+grid[i][j]

        return dp[-1][-1]

#48.py

# 请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
# 示例 1:
# 输入: "abcabcbb"
# 输出: 3 
# 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
# 示例 2:
# 输入: "bbbbb"
# 输出: 1
# 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
# 示例 3:
# 输入: "pwwkew"
# 输出: 3
# 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
#      请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        tmp=0
        res=0
        d={}
        for i in range(len(s)):
            j=d.get(s[i],-100)
            d[s[i]]=i
            if i-j<=tmp:
                tmp=i-j
            else:
                tmp=tmp+1
            res=max(res,tmp)
            print(res,tmp)
        return res

#49.py

# 我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。
# 示例:

# 输入: n = 10
# 输出: 12
# 解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。

class Solution:
    def nthUglyNumber(self, n: int) -> int:
        heap=[1]
        heapq.heapify(heap)
        i=0
        res=[]
        while i<n:
            cur=heapq.heappop(heap)
            if cur not in res:
                i+=1
                res.append(cur)
                for j in [2,3,5]:
                    
                    x=j*cur
                    heapq.heappush(heap,x)
        return res[-1]

#5.py

# 请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
# 示例 1:

# 输入:s = "We are happy."
# 输出:"We%20are%20happy."


class Solution:
    def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
        if len(matrix)==0:return False
        i=0
        j=len(matrix[0])-1
        while i<len(matrix) and j>=0:
            if matrix[i][j]<target:
                i+=1
            elif matrix[i][j]>target:
                j-=1
            else:
                return True
        return False

#50.py

# 在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。

# 示例:
# s = "abaccdeff"
# 返回 "b"
# s = "" 
# 返回 " "
class Solution:
    def firstUniqChar(self, s: str) -> str:
        c=Counter(s)
        uniqset=set()
        for k,v in c.items():
            if v==1:
                uniqset.add(k)
        for i in s:
            if i in uniqset:
                return i
        return " "

#51.py

# 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
# 示例 1:

# 输入: [7,5,6,4]
# 输出: 5
class Solution:
    def reversePairs(self, nums: List[int]) -> int:
        self.cnt=0
        def merge(nums,start,mid,end):
            tmp=[]
            i=start
            j=mid+1
            while i<=mid and j<=end:
                if nums[i]<=nums[j]:
                    tmp.append(nums[i])
                    i+=1
                else:
                    self.cnt+=mid-i+1
                    tmp.append(nums[j])
                    j+=1
            
            while i<=mid:
                tmp.append(nums[i])
                i+=1
            while j<=end:
                tmp.append(nums[j])
                j+=1
            for i in range(len(tmp)):
                nums[start+i]=tmp[i]

        def mergeSort(nums,start,end):
            if start>=end:return
            mid=(start+end)//2
            mergeSort(nums,start,mid)
            mergeSort(nums,mid+1,end)
            merge(nums,start,mid,end)

        mergeSort(nums,0,len(nums)-1)
        return self.cnt

#52.py

#输入两个链表,找出它们的第一个公共节点。
class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        p=headA
        q=headB

        while p!=q:
            if not p:
                p=headB
            else:
                p=p.next
            if not q:
                q=headA 
            else:
                q=q.next
        return q

#53.py

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

#  

# 示例 1:

# 输入: nums = [5,7,7,8,8,10], target = 8
# 输出: 2
# 示例 2:

# 输入: nums = [5,7,7,8,8,10], target = 6
# 输出: 0
class Solution:
    def search(self, nums: List[int], target: int) -> int:
        # l,r=0,len(nums)-1
        # while l<r:
        #     mid=(l+r)//2
        #     if nums[mid]>target:
        #         r=mid
        #     elif nums[mid]<target:
        #         l=mid+1
        # res1=l

        # l,r=0,len(nums)-1
        # while l<r:
        #     mid=(l+r)//2
        #     if nums[mid]>target:
        #         r=mid
        #     elif nums[mid]<target:
        #         l=mid+1
        # res2=l
        # return res2-res1+1
        import bisect
        left=bisect.bisect_left(nums,target)
        right=bisect.bisect(nums,target)
        return right-left

#53_1.py

# 一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。

#  

# 示例 1:

# 输入: [0,1,3]
# 输出: 2
# 示例 2:

# 输入: [0,1,2,3,4,5,6,7,9]
# 输出: 8
class Solution:
    def missingNumber(self, nums: List[int]) -> int:
        left=0
        right=len(nums)-1
        
        while left<=right:
            mid=(left+right)//2
            
            if nums[mid]==mid:
                left=mid+1
            else:
                right=mid-1
        
        return left

#54.py

#给定一棵二叉搜索树,请找出其中第k大的节点。
class Solution:
    def kthLargest(self, root: TreeNode, k: int) -> int:
        if not root:return 0
        res=[]
        def dfs(root):
                if root.left:
                    dfs(root.left)
                res.append(root.val)
                if root.right:
                    dfs(root.right)
        if root:        
            dfs(root)
        return res[len(res)-k]

#55.py

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

# 例如:

# 给定二叉树 [3,9,20,null,null,15,7],

#     3
#    / \
#   9  20
#     /  \
#    15   7
# 返回它的最大深度 3 。
class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        
        if not root:return 0
        if not root.left and not root.right:return 1
        if root.left and not root.right:
            return 1+self.maxDepth(root.left)
        if root.right and not root.left:
            return 1+self.maxDepth(root.right)
        if root.left and root.right:
            return 1+max(self.maxDepth(root.left),self.maxDepth(root.right))

#55_2.py

# 输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。

# 示例 1:

# 给定二叉树 [3,9,20,null,null,15,7]

#     3
#    / \
#   9  20
#     /  \
#    15   7
# 返回 true 。

# 示例 2:

# 给定二叉树 [1,2,2,3,3,null,null,4,4]

#        1
#       / \
#      2   2
#     / \
#    3   3
#   / \
#  4   4
# 返回 false 。
class Solution:
    def isBalanced(self, root: TreeNode) -> bool:
        if not root:return True
        return abs(self.depth(root.left)-self.depth(root.right))<=1 and self.isBalanced(root.left) and self.isBalanced(root.right)

    def depth(self,root):
        if not root:return 0
        return 1+max(self.depth(root.left),self.depth(root.right))

#56.py

# 一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
# 示例 1:
# 输入:nums = [4,1,4,6]
# 输出:[1,6] 或 [6,1]
# 示例 2:
# 输入:nums = [1,2,10,4,1,4,3,3]
# 输出:[2,10] 或 [10,2]
class Solution:
    def singleNumbers(self, nums: List[int]) -> List[int]:
        c=Counter(nums)
        res=[]
        for k,v in c.items():
            if v==1:
                res.append(k)
        return res

#56_2.py

# 一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
# 示例 1:
# 输入:nums = [4,1,4,6]
# 输出:[1,6] 或 [6,1]
# 示例 2:
# 输入:nums = [1,2,10,4,1,4,3,3]
# 输出:[2,10] 或 [10,2]
class Solution:
    def singleNumbers(self, nums: List[int]) -> List[int]:
        c=Counter(nums)
        res=[]
        for k,v in c.items():
            if v==1:
                res.append(k)
        return res

#57.py

# 输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
# 序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
# 示例 1:
# 输入:target = 9
# 输出:[[2,3,4],[4,5]]
# 示例 2:
# 输入:target = 15
# 输出:[[1,2,3,4,5],[4,5,6],[7,8]]
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        i=0
        j=len(nums)-1
        while i<j:
            if nums[i]+nums[j]>target:
                j-=1
            elif nums[i]+nums[j]<target:
                i+=1
            else:
                return [nums[i],nums[j]]

#57_2.py

# 输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
# 序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
# 示例 1:
# 输入:target = 9
# 输出:[[2,3,4],[4,5]]
# 示例 2:
# 输入:target = 15
# 输出:[[1,2,3,4,5],[4,5,6],[7,8]]

class Solution:
    def findContinuousSequence(self, target: int) -> List[List[int]]:
        nums=[i for i in range(1,target+1)]
        res=[]
        i=target//2
        start=2
        while i>=0 and start<=target//2+1:
            if sum(nums[i:i+start])==target:
                res.append(nums[i:i+start])
                i=i-1
                start+=1
            if sum(nums[i:i+start])>target:
                i=i-1
            if sum(nums[i:i+start])<target:
                start+=1
        return sorted(res)

#58.py

#输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. ",则输出"student. a am I"。
class Solution:
    def reverseWords(self, s: str) -> str:
        s=s.strip()
        s=s[::-1]
        res=""
        j=0
        for i in range(len(s)):
            if s[i]==' ' and s[i+1]!=' ':
                res+=s[j:i][::-1].strip()+' '
                j=i
        res+=s[j:][::-1].strip()
        return res

#58_2.py

# 字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。

# 示例 1:

# 输入: s = "abcdefg", k = 2
# 输出: "cdefgab"
# 示例 2:

# 输入: s = "lrloseumgh", k = 6
# 输出: "umghlrlose"
class Solution:
    def reverseLeftWords(self, s: str, n: int) -> str:
        return s[n:]+s[:n]

#59.py

# 给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。

# 示例:

# 输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
# 输出: [3,3,5,5,6,7] 
# 解释: 

#   滑动窗口的位置                最大值
# ---------------               -----
# [1  3  -1] -3  5  3  6  7       3
#  1 [3  -1  -3] 5  3  6  7       3
#  1  3 [-1  -3  5] 3  6  7       5
#  1  3  -1 [-3  5  3] 6  7       5
#  1  3  -1  -3 [5  3  6] 7       6
#  1  3  -1  -3  5 [3  6  7]      7
class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        q=[]
        res=[]
        for i in range(len(nums)):
            if i-k>=0 and nums[i-k]==q[0]:
                q.pop(0)

            while q and nums[i]>q[-1]:
                q.pop()
            q.append(nums[i])    

            print(q)
            if i>=k-1:
                res.append(q[0])
        return res

#59_2.py

# 请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。

# 若队列为空,pop_front 和 max_value 需要返回 -1

# 示例 1:

# 输入: 
# ["MaxQueue","push_back","push_back","max_value","pop_front","max_value"]
# [[],[1],[2],[],[],[]]
# 输出: [null,null,null,2,1,2]
# 示例 2:

# 输入: 
# ["MaxQueue","pop_front","max_value"]
# [[],[],[]]
# 输出: [null,-1,-1]
class MaxQueue:

    def __init__(self):
        self.q=[]
        self.sort_q=[]


    def max_value(self) -> int:
        if self.q:
            return self.sort_q[0]
        else:
            return -1


    def push_back(self, value: int) -> None:
        self.q.append(value)
        
        while self.sort_q and self.sort_q[-1]<value:
            self.sort_q.pop(-1)
        self.sort_q.append(value)

    def pop_front(self) -> int:
        print(self.q,self.sort_q)
        if not self.q:
            return -1
        else:
            x=self.q.pop(0)
            if x==self.sort_q[0]:
                self.sort_q.pop(0)
        return x    

#6.py

# 输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
# 示例 1:
# 输入:head = [1,3,2]
# 输出:[2,3,1]
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def reversePrint(self, head: ListNode) -> List[int]:
        # res=[]
        # while head:
        #     res.append(head.val)
        #     head=head.next
        # return res[::-1]
        #辅助栈
        res=[]
        stack=[]
        while head:
            stack.insert(0,head)
            head=head.next
        
        while stack:
            res.append(stack.pop(0).val)
        return res

#60.py

# 把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。
# 你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n 个骰子所能掷出的点数集合中第 i 小的那个的概率。
class Solution:
    def twoSum(self, n: int) -> List[float]:
        res=[]
        l1=[1/6]*6
        for i in range(1,n):
            tmp=[0]*(5*i+6)
            #l2=[1/6]*6
            for j in range(len(l1)):
                for k in range(6):
                    #print(len(tmp),j,k)
                    tmp[j+k]+=l1[j]*1/6
            l1=tmp
        return l1

#61.py

# 从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。
# 示例 1:

# 输入: [1,2,3,4,5]
# 输出: True
#  

# 示例 2:

# 输入: [0,0,1,2,5]
# 输出: True
class Solution:
    def isStraight(self, nums: List[int]) -> bool:
        nums.sort()
        count=0
        # nums for i in nums
        for i in range(len(nums)-1):
            if nums[i]==0:
                count+=1
                continue
            elif nums[i]==nums[i+1]:
                return False
        if nums[-1]-nums[count]<5:
            return True
        else:    
            return False

#62.py

# 0,1,,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。

# 例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。
# 示例 1:

# 输入: n = 5, m = 3
# 输出: 3
# 示例 2:

# 输入: n = 10, m = 17
# 输出: 2
class Solution:
    def lastRemaining(self, n: int, m: int) -> int:
        q=[i for i in range(n)] 
        last=0
        while len(q)>1:
            index=(last+m-1)%len(q)
            q.pop(index)
            last=index
            
        return q[-1]

#63.py

# 假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少?
# 示例 1:

# 输入: [7,1,5,3,6,4]
# 输出: 5
# 解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
#      注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。
# 示例 2:

# 输入: [7,6,4,3,1]
# 输出: 0
# 解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        profit,temp=0,0

        for i in range(len(prices)-1):
            temp=max(0,temp+prices[i+1]-prices[i])
            profit=max(profit,temp)
        return profit

#64.py

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

# 示例 1:

# 输入: n = 3
# 输出: 6
# 示例 2:

# 输入: n = 9
# 输出: 45
class Solution:
    def sumNums(self, n: int) -> int:
        
        return n and n+self.sumNums(n-1)

#65.py

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

# 输入: a = 1, b = 1
# 输出: 2
class Solution:
    def add(self, a: int, b: int) -> int:
        trans=0xffffffff
        a,b=a&trans,b&trans
        while b!=0:
            carry=(a&b)<<1
            a^=b
            b=carry&trans
        if a<=0x7FFFFFFF:return a
        else:
            return ~(a^trans)

#66.py

# 给定一个数组 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]。不能使用除法。

#  

# 示例:

# 输入: [1,2,3,4,5]
# 输出: [120,60,40,30,24]
class Solution:
    def constructArr(self, a: List[int]) -> List[int]:
        if not a:return []
        left=[1]
        right=[1]
        for i in range(1,len(a)):
            left.append(left[-1]*a[i-1])
            right.insert(0,right[0]*a[len(a)-i])
        #print(right)
        res=[]
        for i in range(len(left)):
            res.append(left[i]*right[i])
        return res

#67.py

# 写一个函数 StrToInt,实现把字符串转换成整数这个功能。不能使用 atoi 或者其他类似的库函数。

# 首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。

# 当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。

# 该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。

# 注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。

# 在任何情况下,若函数不能进行有效的转换时,请返回 0。

# 说明:

# 假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231,  231 − 1]。如果数值超过这个范围,请返回  INT_MAX (231 − 1) 或 INT_MIN (−231) 。

# 示例 1:

# 输入: "42"
# 输出: 42
# 示例 2:

# 输入: "   -42"
# 输出: -42
# 解释: 第一个非空白字符为 '-', 它是一个负号。
#      我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。
# 示例 3:

# 输入: "4193 with words"
# 输出: 4193
# 解释: 转换截止于数字 '3' ,因为它的下一个字符不为数字。
# 示例 4:

# 输入: "words and 987"
# 输出: 0
# 解释: 第一个非空字符是 'w', 但它不是数字或正、负号。
#      因此无法执行有效的转换。
# 示例 5:

# 输入: "-91283472332"
# 输出: -2147483648
# 解释: 数字 "-91283472332" 超过 32 位有符号整数范围。 
#      因此返回 INT_MIN (−231) 。
class Solution:
    def strToInt(self, str: str) -> int:
        
        s=str.strip()
        if len(s)==0:return 0
        print(s)
        nums=0
        flag=True
        if s[0]=="-" and len(s[1:])>0:
            flag=False
            s=s[1:]
            print(s)
        elif s[0]=="+" and len(s[1:])>0:
            s=s[1:]
        print(s)
        for i in range(len(s)):
            if 0<=ord(s[i])-ord('0')<=9:
                nums=10*nums+ord(s[i])-ord('0')
            else:
                break
        if not flag:
            if nums<2**31:
                return -nums
            else:
                return -2**31
        else:
            if nums<2**31:
                return nums           
            else:
                return 2**31-1

#68.py

# 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

# 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

# 例如,给定如下二叉搜索树:  root = [6,2,8,0,4,7,9,null,null,3,5]

# 示例 1:

# 输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
# 输出: 6 
# 解释: 节点 2 和节点 8 的最近公共祖先是 6。
# 示例 2:

# 输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
# 输出: 2
# 解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。
class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        while root:
            if root.val-p.val <0 and root.val-q.val<0:
                root=root.right
            if root.val-p.val>0 and root.val-q.val>0:
                root=root.left
            else:break
        return root

#68_2.py

# 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

# 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

# 例如,给定如下二叉树:  root = [3,5,1,6,2,0,8,null,null,7,4]

# 示例 1:

# 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
# 输出: 3
# 解释: 节点 5 和节点 1 的最近公共祖先是节点 3。
# 示例 2:

# 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
# 输出: 5
# 解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。

class Solution:
    def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
        if not root or root==p or root==q:return root
        l=self.lowestCommonAncestor(root.left,p,q)
        r=self.lowestCommonAncestor(root.right,p,q)
        #if not l and not r:return
        if not l:return r
        if not r: return l
        if l and r:
            return root
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值