剑指offer解题思路简述:61-68

  • 面试题61:扑克牌中的顺子

剑指offer解题思路简述:61-68_第1张图片

方法:五张牌排序,把大小王先当作零,然后统计零的个数,挨个求相邻两个数的间隔,若果间隔有0,表明有重复牌,则不可能是顺子,如果0的个数大于所有数间隔的和,则是顺子

class Solution:
    def isStraight(self, nums: List[int]) -> bool:
        joker = 0
        nums.sort() # 数组排序
        for i in range(4):
            if nums[i] == 0: joker += 1 # 统计大小王数量
            elif nums[i] == nums[i + 1]: return False # 若有重复,提前返回 false
        return nums[4] - nums[joker] < 5 # 最大牌 - 最小牌 < 5 则可构成顺子
  • 面试题62:圆圈中最后剩下的数字

方法一:约瑟夫环,环形链表模拟圆圈,用list,k = (start + m - 1) % n ,k为每次要删除的数

class Solution:
    def LastRemaining_Solution(self, n, m):
        # write code here
        
        if n==0:
            return -1
        temp = []
        num = 0
        for i in range(n):
            temp.append(i)
        while len(temp)!=1:
            num = (m+num-1) % n
            temp.pop(num)
            n =n-1
        return temp[0]

方法二:找到每次被删除数字的规律直接计算,

  • 面试题63:股票的最大利润

剑指offer解题思路简述:61-68_第2张图片

方法:从前往后遍历,记录当索引之前的数的最小值,然后用当前数减去最小值,每次循环需要更新最小值和差值的最大值

class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        if len(prices)==0:
            return 0
        tempmin = prices[0]
        tempdiff = 0
        for i in range(len(prices)):
            if prices[i]tempdiff:
                tempdiff = prices[i]-tempmin
        return tempdiff
  • 面试题64:求1+2+....+n

方法一:利用条件与的短路特性,即and前面的条件如果不满足,不会执行后面的表达式,利用这点实现递归的if返回判断

class Solution:
    def __init__(self):
        self.res = 0
    def sumNums(self, n: int) -> int:
        n > 1 and self.sumNums(n - 1)
        self.res += n
        return self.res

方法二:利用构造函数、函数指针、虚函数、模板等来实现

  • 面试题65:不用加减乘除做加法

方法:利用位运算,每次把两个数相抑或,得到没有计算进位的结果,然后两个数相与并<<1,得到只计算进位的结果,然后把得到的两个数作为新的加数,重复以上运算,直到表示进位的数为0

class Solution:
    def Add(self, num1, num2):
        # write code here
        while(num2!=0):
            temp = num1^num2;
            num2= (num1&num2)<<1;
            num1 = temp;
        return num1
        '''
        return sum([num1,num2])
        '''

剑指offer解题思路简述:61-68_第3张图片

  • 面试题66:构造乘积数组

方法1:直接暴力连乘,时间复杂度n*2

方法2:通过i来划分左右两个部分,左面的a(n) = a(n-1)*A(n),右边的b(n-1) = b(n)*A(n),然后B(n)=a(n)*b(len(A)-n-1)

class Solution:
    def multiply(self, A):
        zuo=1
        you=1
        left=[]
        right=[]
        result=[]
        for i in range(len(A)):
            left.append(zuo)
            zuo=zuo*A[i]
        for j in range(len(A)-1,-1,-1):
            right.append(you)
            you=you*A[j]
        for n in range(len(A)):
            result.append(left[n]*right[len(A)-1-n])
        return result
  • 面试题67:把字符串转化为整数

方法一:直接用int()函数,可以用try 和except来捕获异常

方法二:按部就班的写,注意开头是‘+’或者‘-’号的情况

class Solution:
    def StrToInt(self, s):
        # write code here
        if(s==''):
            return 0
        flag = 0
        temp = 0
        for i in range(len(s)):
            if i==0:
                if s[i]=='-':
                    flag = 1
                elif s[i]>='0' and s[i]<='9' :
                    temp = temp*10+(ord(s[i])-ord('0'))
            elif s[i]>='0' and s[i]<='9':
                temp = temp*10+(ord(s[i])-ord('0'))
            else:
                return 0
        if flag==1:
            temp =-temp
        return temp
        '''
        try:
            return int(s)
        except Exception as e:
            return 0
        '''
  • 面试题68:树中两个节点的最低公共祖先

情况一:是二叉搜索树,所以跟节点比左节点大比右节点小,中序遍历即为排序的队列,从根节点开始,如果比两个节点都大,则最低公共祖先在左子树,反之在右子树

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        while root:
            if root.val < p.val and root.val < q.val: # p,q 都在 root 的右子树中
                root = root.right # 遍历至右子节点
            elif root.val > p.val and root.val > q.val: # p,q 都在 root 的左子树中
                root = root.left # 遍历至左子节点
            else: break
        return root

情况二:不是搜索树,但有指向父节点的指针,可以把此问题转化成求两个链表相交的第一个节点的题

情况三:不是搜索树,没有指向父节点的指针,需要先分别将两条路径保存,然后从头开始比较两个list,第一个不想等的即为结果

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def lowestCommonAncestor(self, root, p, q):
        """
        :type root: TreeNode
        :type p: TreeNode
        :type q: TreeNode
        :rtype: TreeNode
        """
        stack_1 = []
        stack_2 = []
        def dfs(root, node, stack):
            if not root:
                return False
            stack.append(root)
            if root.val == node.val:
                return True          
            if (dfs(root.left, node, stack) or dfs(root.right, node, stack)):
                return True
            stack.pop()
            
        dfs(root, p, stack_1)
        dfs(root, q, stack_2)
        i = 0
        while i < len(stack_1) and i
class Solution:
    def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
        if not root or root == p or root == q: return root
        left = self.lowestCommonAncestor(root.left, p, q)
        right = self.lowestCommonAncestor(root.right, p, q)
        if not left and not right: return # 1.
        if not left: return right # 3.
        if not right: return left # 4.
        return root # 2. if left and right:

 

你可能感兴趣的:(剑指offer解题思路简述:61-68)