剑指offer(第二版) |第二章

03-数组中重复的数字

# -*- coding: utf-8 -*-

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

# 方法一:对输入数组排序,从投到尾扫描,即可得到重复的元素,时间复杂度O(nlogn)
# 方法二:利用集合,检测元素是否重复
# 方法三:以将对应元素放到对应位置的方式重排数组,然后发现重复元素


# 以牛客网写法为主
class Solution:
    # 这里要特别注意~找到任意重复的一个值并赋值到duplication[0]
    # 函数返回True/False

    # 方法一
    def duplicate1(self, numbers, duplication):
        # write code here
        if numbers == None or len(numbers) <= 1:
            return False
        for i in range(len(numbers)):
            if numbers[i] < 0 or numbers[i] > len(numbers) - 1:
                return False

        numbers.sort()
        for i in range(len(numbers) - 1):
            if numbers[i] == numbers[i + 1]:
                duplication[0] = numbers[i]  #
                print(duplication[0])
                return True
        return False

    # 方法二
    def duplicate2(self, numbers, duplication):
        if numbers == None or len(numbers) <= 1:
            return False
        usedDic = set()
        for i in range(len(numbers)):
            if numbers[i] < 0 or numbers[i] > len(numbers) - 1:
                return False
            if numbers[i] not in usedDic:
                usedDic.add(numbers[i])
            else:
                duplication[0] = numbers[i]
                print(duplication[0])
                return True
        return False

    # 方法三
    def duplicate3(self, numbers, duplication):
        if numbers == None or len(numbers) <= 1:
            return False
        for i in range(len(numbers)):
            if numbers[i] < 0 or numbers[i] > len(numbers) - 1:
                return False

        for i in range(len(numbers)):
            while (numbers[i] != i):
                if numbers[i] == numbers[numbers[i]]:  # 如果第i个数所对应的数等于i
                    duplication[0] = numbers[i]
                    print(duplication[0])
                    return True
                else:
                    temp = numbers[i]
                    numbers[i] = numbers[temp]  # numbers[temp]这里对应的是书中的第m个数字
                    numbers[temp] = temp
        return False


if __name__ == "__main__":
    print("03_01")
    Array = [2, 3, 1, 0, 2, 5, 3]
    Dup = [0]  # Dup先定义为一个长度为1的数组,用来存储第一个重复的数字
    print("方法1--------------------")
    print(Solution().duplicate1(Array, Dup))

    print("方法2--------------------")
    print(Solution().duplicate2(Array, Dup))

    print("方法3--------------------")
    print(Solution().duplicate3(Array, Dup))

04-二维数组中的查找

# -*- coding: utf-8 -*-

"""
面试题4:二维数组中的查找
题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。
请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
"""

class Solution:
    def Find(self, target, array):
        '简单粗暴,二层遍历,时间不是最优'
        found = False
        rows, columns = len(array),len(array[0])
        if array and rows > 0 and columns > 0:
            for row in range(rows):
                for column in range(columns):
                    if array[row][column] == target:
                        found = True
        return found
    
    def Find2(self, target, array):
        '从右上角开始判断'
        found = False
        rows = len(array)
        columns = len(array[0])
        if array and rows > 0 and columns > 0:
            row = 0
            column = columns - 1
            while row < rows and column >= 0:
                if array[row][column] == target:
                    found = True
                    break
                elif array[row][column] > target:
                    column -= 1
                else:
                    row += 1
        return found
    
    def Find3(self, target, array):
        '从左下角开始判断'
        found = False
        rows = len(array)
        columns = len(array[0])
        if array and rows > 0 and columns > 0:
            row = rows -1
            column = 0
            while row >= 0 and column < columns:
                if array[row][column] == target:
                    found = True
                    break
                elif array[row][column] > target:
                    row -= 1
                else:
                    column += 1
        return found

if __name__ == "__main__":
    Array = [[1, 2, 8, 9],
             [2, 4, 9, 12],
             [4, 7, 10, 13],
             [6, 8, 11, 15]]
    Target = 7
    print(Solution().Find(Target, Array))
    print(Solution().Find2(Target, Array))
    print(Solution().Find3(Target, Array))
    

05-替换空格

# -*- coding: utf-8 -*-

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


class Solution:
    # s 源字符串
    def replaceSpace1(self, s):
        '使用join'
        if s == "" or len(s) <= 0:
            return ""
        return "%20".join(s.split(" "))

    def replaceSpace2(self, s):
        '使用replace方法'
        if s == "" or len(s) <= 0:
            return ""
        return s.replace(" ", "%20")

    def replaceSpace3(self, s):
        """
        剑指offer解法:
        ①先计算源字符串数组长度,并统计空格数量
        ②新字符串数组长度=源数组长度+2*空格数量
        ③在新字符串数组上,从后向前遍历,通过两个index移动并复制
        :param s: 输入字符串s
        :return: 替换后的字符串
        """
        if s == "" or len(s) <= 0:
            return ""

        # 计算空格数量
        s = list(s)
        count = 0
        for i in s:
            if i == " ":
                count += 1

        p1 = len(s) - 1  # p1初始化为原始字符串数组末尾的index

        s += [None] * (count * 2)  # 将s扩充为新长度
        p2 = len(s) - 1  # p2初始化为新字符串数组末尾的index
        while p1 >= 0:
            if s[p1] == ' ':
                for i in ['0', '2', '%']:
                    s[p2] = i
                    p2 -= 1
            else:
                s[p2] = s[p1]
                p2 -= 1
            p1 -= 1
        return ''.join(s)


if __name__ == "__main__":
    S = "We Are Happy"
    print(Solution().replaceSpace1(S))
    print(Solution().replaceSpace2(S))
    print(Solution().replaceSpace3(S))

06-从尾到头打印链表

不了解Python链表的可以参阅python数据结构-链表

# -*- 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
        l = []
        head = listNode
        while head:
            l.insert(0, head.val)
            head = head.next
        return l
 
 
if __name__ == '__main__':
    # node1 -> node2 -> node3
    # node1,node2,node3的val分别为1,2,3
    node1 = ListNode(1)
    node2 = ListNode(2)
    node3 = ListNode(3)
    node1.next = node2
    node2.next = node3
    result = Solution().printListFromTailToHead(node1)
    print(result)

07-重建二叉树

# -*- coding: utf-8 -*-
 
"""
面试题7:重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},
则重建二叉树并返回。
"""
 
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None
 
 
class Solution:
    # 返回构造的TreeNode根节点
    def reConstructBinaryTree(self, pre, tin):
        """
        :param pre: 前序序列
        :param tin: 中序序列
        :return: 返回树的根root
        """
        # write code here
        if not pre or not tin:  # 如果pre或tin为空则返回None
            return None
 
        root = TreeNode(pre[0])  # 前序序列的第一个为根
        index = tin.index(pre[0])  # index是判断根在tin中的位置
 
        root.left = self.reConstructBinaryTree(pre[1:index + 1], tin[:index])
        root.right = self.reConstructBinaryTree(pre[index + 1:], tin[index + 1:])
        return root
 
 
if __name__ == '__main__':
    # 根据书本上图2.6构建一个二叉树
    n8 = TreeNode(8)
    n7 = TreeNode(7)
    n6 = TreeNode(6)
    n5 = TreeNode(5)
    n4 = TreeNode(4)
    n3 = TreeNode(3)
    n2 = TreeNode(2)
    n1 = TreeNode(1)
    n1.left = n2
    n1.right = n3
    n2.left = n4
    n3.left = n5
    n3.right = n6
    n4.right = n7
    n6.left = n8
 
    pre = [n1, n2, n4, n7, n3, n5, n6, n8]  # 前序序列
    tin = [n4, n7, n2, n1, n5, n3, n8, n6]  # 中序序列
 
    result = Solution().reConstructBinaryTree(pre, tin)
    # result实际上是一个树,result.val则是一个树根,依然是TreeNode对象,
    # result.val.val才是树根的值
    print(result.val.val)

08-二叉树的下一个节点

# -*- coding: utf-8 -*-
 
"""
面试题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 here
        if not pNode: # 判断非空
            return None
 
        # 1. 有右子树,下一结点是右子树中的最左结点,例如 B,下一结点是 H
        if pNode.right:
            res = pNode.right
            while res.left:
                res = res.left
            return res
 
        # 2.  无右子树,则向上回溯其父节点
        # 2.1 该节点是其父节点的左子树,则该节点的父节点即为所求,例如 H,下一结点是 E
        # 2.2 该节点不是其父节点的左子树(换句话说就是其父节点的右子树),则持续回溯其
        #     父节点,直到找到一个节点满足其为其父节点的左子树,则其父节点即为所求,比如 I
        #     的下一个节点为 A,如果找不到满足条件的这样一节点,比如 G 节点,那么 G 节点
        #     就是最后一个节点,他没有下一个节点。
        while pNode.next:
            tmp = pNode.next
            if tmp.left == pNode:
                return tmp
            pNode = tmp
        return None
 
if __name__ == '__main__':
    # 根据书本上图2.8构建一个二叉树
    n_a = TreeLinkNode('a')
    n_b = TreeLinkNode('b')
    n_c = TreeLinkNode('c')
    n_d = TreeLinkNode('d')
    n_e = TreeLinkNode('e')
    n_f = TreeLinkNode('f')
    n_g = TreeLinkNode('g')
    n_h = TreeLinkNode('h')
    n_i = TreeLinkNode('i')
    n_a.left = n_b; n_a.right = n_c
    n_b.left = n_d; n_b.right = n_e; n_b.next = n_a
    n_c.left = n_f; n_c.right = n_g; n_c.next = n_a
    n_d.next = n_b
    n_e.left = n_h; n_e.right = n_i; n_e.next = n_b
    n_f.next = n_c
    n_g.next = n_c
    n_h.next = n_e
    n_i.next = n_e
 
    # 中序遍历 [d, b, h, e, i, a, f, c, g]
    testNode = n_g
    result = Solution().GetNext(testNode)
    if result != None:
        print(result.val)
    else:
        # 如果result为空,说明该node是中序遍历最后一个节点,没有下一个节点
        # ,直接输出该节点的val即可
        print(testNode.val)

09-01-用两个栈实现队列

# -*- coding: utf-8 -*-

"""
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
"""
"""
解题思路:
https://www.nowcoder.com/profile/4991846/codeBookDetail?submissionId=9811452
<分析>:
入队:将元素进栈A
出队:判断栈B是否为空,如果为空,则将栈A中所有元素pop,并push进栈B,栈B出栈;
如果不为空,栈B直接出栈。
"""


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[len(self.stack1) - 1])
                self.stack1.pop()
        pop = self.stack2[len(self.stack2) - 1]
        self.stack2.pop()
        return pop


if __name__ == '__main__':
    node1 = 'a'
    node2 = 'b'
    node3 = 'c'
    CQueue = Solution()
    CQueue.push(node1)
    CQueue.push(node2)
    CQueue.push(node3)
    print(CQueue.pop())
    print(CQueue.pop())
    print(CQueue.pop())

09-02-用两个队列实现栈

# -*- coding: utf-8 -*-
"""
09题扩展,两个队列实现栈
"""
'''
<分析>:
入栈:将元素进队列A
出栈:判断队列A中元素的个数是否为0,0说明队列A中最后一个元素已经pop
当队列A的长度不为1时,将队列A中的元素依次输送到队列B中,直到队列A只剩1个元素
此时将队列A与队列B互换,则队列B为只有一个元素的队列,该元素即为要出栈的元素
pop该元素即可。
'''

class Solution:
    def __init__(self):
        self.queue1 = []
        self.queue2 = []

    def push(self, node):
        self.queue1.insert(0, node)

    def pop(self):
        if not self.queue1: # 如果A空,队列A中无元素,此时return None
            return None

        while len(self.queue1) != 1:
            self.queue2.insert(0, self.queue1.pop())
        self.queue1, self.queue2 = self.queue2, self.queue1
        return self.queue2.pop()


if __name__ == '__main__':
    node1 = 'a'
    node2 = 'b'
    node3 = 'c'
    CStack = Solution()
    CStack.push(node1)
    CStack.push(node2)
    CStack.push(node3)
    print(CStack.pop())
    print(CStack.pop())
    print(CStack.pop())

10-斐波那契数列

# -*- coding: utf-8 -*-
# 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。 # n<=39
# 1、1、2、3、5、8、13、21、34

class Solution:
    def Fibonacci(self, n):
        # write code here
        result = [0, 1]
        if n < 2:
            return result[n]
        fibNMinusOne = 0
        fibNMinusTwo = 1
        fibN = 0
        for i in range(2, n + 1):
            fibN = fibNMinusOne + fibNMinusTwo
            fibNMinusOne = fibNMinusTwo
            fibNMinusTwo = fibN
        return fibN


if __name__ == '__main__':
    n = 8
    F = Solution()
    print(F.Fibonacci(n))

10-02-青蛙跳台阶

# -*- coding: utf-8 -*-

# 青蛙跳台阶问题,一只青蛙要跳上n层高的台阶,一次能跳一级,也可以跳两级,请问这只青蛙有多少种跳上这个n层高台阶的方法?
# 1、2、3、5、8、13、21、34

class Solution:
    def Fibonacci(self, n):
        # write code here
        result = [1, 2]
        if n < 2:
            return result[n]
        fibNMinusOne = 1
        fibNMinusTwo = 2
        fibN = 0
        for i in range(2, n):
            fibN = fibNMinusOne + fibNMinusTwo
            fibNMinusOne = fibNMinusTwo
            fibNMinusTwo = fibN
        return fibN


if __name__ == '__main__':
    n = 8
    F = Solution()
    print(F.Fibonacci(n))

11-旋转数组的最小数字

# -*- coding: utf-8 -*-
class Solution:
    def minNumberInRotateArray(self, rotateArray):
        # write code here
        if not rotateArray:
            return 0
        else:
            return min(rotateArray)

    def minNumberInRotateArray2(self, rotateArray):
        if not rotateArray:
            return 0
        else:
            rotateArray.sort()
            return rotateArray[0]

    def minNumberInRotateArray3(self, rotateArray):
        # write code here
        """
        解题思路:> 数组旋转后,分为两部分,前半部分大于等于后半部分(考虑非严格递增的情况)
        > 将index1初始化为第一个数字,index2初始化为最后一个数字,mid初始化为第一个数字(应对旋转0个元素的情况)
        > 如果index1与index2相邻,此时index2即为所求
        > 如果遇到的index1、index2以及indexMid指向的三个数字相等,就无法二分查找,只能遍历数组了
        > 如果mid指向的数字大于等于index1指向的数字,那么mid 在数组一中,下一步,将index1往mid挪,指向mid
        > 如果mid指向的数字小于等于index2指向的数字,那么mid 在数组二中,下一步,将index2往mid挪,指向mid
        :param rotateArray: 
        :return: 
        """
        if not rotateArray:
            return 0
        if len(rotateArray) == 0:
            return 0
        index1 = 0
        index2 = len(rotateArray) - 1
        indexMid = index1
        while (rotateArray[index1] >= rotateArray[index2]):
            if (index2 - index1 == 1):  # 如果index2与index1相邻,则index2对应的即为所求
                indexMid = index2
                break
            indexMid = (index1 + index2) // 2
            # 如果下标index1、index2以及index3的数值相等,就只能遍历了
            if (rotateArray[index1] == rotateArray[index2] and rotateArray[index1] == rotateArray[indexMid]):
                return self.minValue(rotateArray, index1, index2)
            if (rotateArray[indexMid] >= rotateArray[index1]):
                index1 = indexMid
            elif (rotateArray[indexMid] <= rotateArray[index2]):
                index2 = indexMid
        return rotateArray[indexMid]

    def minValue(self, rotateArray, index1, index2):
        result = rotateArray[index1]
        for i in range(index1 + 1, index2 + 1):
            if result > rotateArray[i]:
                result = rotateArray[i]
        return result
if __name__ == '__main__':
    array = [3, 4, 5, 1, 2]
    a = Solution()
    print(a.minNumberInRotateArray(array))
    print(a.minNumberInRotateArray2(array))
    print(a.minNumberInRotateArray3(array))

12-矩阵中的路径

# -*- coding: utf-8 -*-

"""
// 面试题12:矩阵中的路径
// 题目:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有
// 字符的路径。路径可以从矩阵中任意一格开始,每一步可以在矩阵中向左、右、
// 上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入
// 该格子。例如在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字
// 母用下划线标出)。但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个
// 字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。
// A B T G
// C F C S
// J D E H
"""
import unittest


# -*- coding:utf-8 -*-
class Solution:
    def hasPath(self, matrix, rows, cols, path):
        """
        :param matrix: 输入的矩阵
        :param rows: 矩阵的行数
        :param cols: 矩阵的列数
        :param path: 要寻找的path
        :return: 
        """
        # write code here
        if not matrix or rows < 0 or cols < 0 or path == None:
            return False
        markmatrix = [0] * (rows * cols)
        pathIndex = 0

        for row in range(rows):
            for col in range(cols):
                if self.hasPathCore(matrix, rows, cols, row, col, path, pathIndex, markmatrix):
                    return True
        return False

    def hasPathCore(self, matrix, rows, cols, row, col, path, pathIndex, markmatrix):
        """
        
        :param matrix: 输入的矩阵
        :param rows: 矩阵行数
        :param cols: 矩阵列数
        :param row: 当前行
        :param col: 当前列
        :param path: 要寻找的path
        :param pathIndex: 查询到第index个字符
        :param markmatrix: mark为已经走过 
        :return: 
        """
        if pathIndex == len(path):  # 如果pathIndex的长度与path一致,则找到对应的路径
            return True
        hasPath = False
        if row >= 0 and row < rows and col >= 0 and col < cols and matrix[row * cols + col] == path[pathIndex] and not \
                markmatrix[row * cols + col]:  # 当矩阵行数,列数符合条件,且矩阵上该点存在且等于路径上的那一点,且未被走过
            pathIndex += 1  # 路径移到下一个点
            markmatrix[row * cols + col] = True  # 将刚刚走过的这点mark一下
            # 判断该点的上下左右是否满足
            hasPath = self.hasPathCore(matrix, rows, cols, row + 1, col, path, pathIndex, markmatrix) or \
                      self.hasPathCore(matrix, rows, cols, row - 1, col, path, pathIndex, markmatrix) or \
                      self.hasPathCore(matrix, rows, cols, row, col + 1, path, pathIndex, markmatrix) or \
                      self.hasPathCore(matrix, rows, cols, row, col - 1, path, pathIndex, markmatrix)
            if not hasPath:  # 如果上下左右仍未找到对应的点
                pathIndex -= 1  # 回到上一步
                markmatrix[row * cols + col] = False  # 回退之后,走过的路mark为false
        return hasPath


class TestSolution(unittest.TestCase):
    def test1(self):
        matrix = 'ABTGCFCSJDEH'
        string = 'BFCE'
        rows = 3
        cols = 4
        solution = Solution()
        expected = True
        self.assertEqual(expected, solution.hasPath(matrix, rows, cols, string))

    def test2(self):
        matrix = 'ABCESFCSADEE'
        string = 'SEE'
        rows = 3
        cols = 4
        solution = Solution()
        expected = True
        self.assertEqual(expected, solution.hasPath(matrix, rows, cols, string))

    def test3(self):
        matrix = 'ABTGCFCSJDEH'
        string = 'ABFB'
        rows = 3
        cols = 4
        solution = Solution()
        expected = False
        self.assertEqual(expected, solution.hasPath(matrix, rows, cols, string))

    def test4(self):
        matrix = 'ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS'
        string = 'SLHECCEIDEJFGGFIE'
        rows = 5
        cols = 8
        solution = Solution()
        expected = True
        self.assertEqual(expected, solution.hasPath(matrix, rows, cols, string))

    def test5(self):
        matrix = 'ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS'
        string = 'SGGFIECVAASABCEHJIGQEM'
        rows = 5
        cols = 8
        solution = Solution()
        expected = True
        self.assertEqual(expected, solution.hasPath(matrix, rows, cols, string))

    def test6(self):
        matrix = 'ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS'
        string = 'SGGFIECVAASABCEEJIGOEM'
        rows = 5
        cols = 8
        solution = Solution()
        expected = False
        self.assertEqual(expected, solution.hasPath(matrix, rows, cols, string))

    def test7(self):
        matrix = 'ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS'
        string = 'SGGFIECVAASABCEHJIGQEMS'
        rows = 5
        cols = 8
        solution = Solution()
        expected = False
        self.assertEqual(expected, solution.hasPath(matrix, rows, cols, string))

    def test8(self):
        matrix = 'AAAAAAAAAAAA'
        string = 'AAAAAAAAAAAA'
        rows = 3
        cols = 4
        solution = Solution()
        expected = True
        self.assertEqual(expected, solution.hasPath(matrix, rows, cols, string))

    def test9(self):
        matrix = 'AAAAAAAAAAAA'
        string = 'AAAAAAAAAAAAA'
        rows = 3
        cols = 4
        solution = Solution()
        expected = False
        self.assertEqual(expected, solution.hasPath(matrix, rows, cols, string))

    def test10(self):
        matrix = 'A'
        string = 'A'
        rows = 1
        cols = 1
        solution = Solution()
        expected = True
        self.assertEqual(expected, solution.hasPath(matrix, rows, cols, string))

    def test11(self):
        matrix = 'A'
        string = 'B'
        rows = 1
        cols = 1
        solution = Solution()
        expected = False
        self.assertEqual(expected, solution.hasPath(matrix, rows, cols, string))

    def test12(self):
        matrix = ''
        string = ''
        rows = 0
        cols = 0
        solution = Solution()
        expected = False
        self.assertEqual(expected, solution.hasPath(matrix, rows, cols, string))


if __name__ == '__main__':
    unittest.main()

13-机器人的运动范围

# -*- coding: utf-8 -*-

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


# 牛客网题解:https://www.nowcoder.com/questionTerminal/6e5207314b5241fb83f2329e89fdecc8?answerType=1&f=discussion

# 思路:这道题跟前一道题一样,也是回溯法,分析题目,我们需要两个全局变量:标志数组和计数变量;
# 需要一个函数来计算行坐标和列坐标的数位之和;终止条件包括三种情况:越界、重复、行坐标和列坐标的数位之和超过k,
# 然后流程和上一道题相同。

# 根据需求分析需要的函数或变量
# - 标志数组markmatrix和计数变量count
# - 计算行列坐标数位之和的函数
# - 包含计数与处理终止条件的函数

class Solution:
    def movingCount(self, threshold, rows, cols):
        if threshold < 0 or rows <= 0 or cols <= 0:
            return 0
        markmatrix = [False] * (rows * cols)
        count = self.movingCountCore(threshold, rows, cols, 0, 0, markmatrix)
        return count

    def movingCountCore(self, threshold, rows, cols, row, col, markmatrix):
        value = 0
        if self.check(threshold, rows, cols, row, col, markmatrix):
            markmatrix[row * cols + col] = True
            value = 1 + self.movingCountCore(threshold, rows, cols, row + 1, col, markmatrix) + \
                    self.movingCountCore(threshold, rows, cols, row - 1, col, markmatrix) + \
                    self.movingCountCore(threshold, rows, cols, row, col + 1, markmatrix) + \
                    self.movingCountCore(threshold, rows, cols, row, col - 1, markmatrix)
        return value

    def check(self, threhold, rows, cols, row, col, markmatrix):
        if (row >= 0 and row < rows and col >= 0 and col < cols and self.getDigitSum(row) + self.getDigitSum(
                col) <= threhold and not markmatrix[row * cols + col]):
            return True
        return False

    def getDigitSum(self, number):
        sum = 0
        while (number > 0):
            sum += number % 10
            number //= 10
        return sum


if __name__ == '__main__':
    solution = Solution()
    print(solution.movingCount(5, 10, 10))

14-剪绳子

# -*- coding: utf-8 -*-
class Solution:
    def cutRope(self, number):
        # write code here
        # 动态规划
        if (number < 2):
            return 0
        if (number == 2):
            return 1
        if (number == 3):
            return 2

        products = [0] * (number + 1)
        products[0] = 0
        products[1] = 1
        products[2] = 2
        products[3] = 3

        max = 0
        for i in range(4, number + 1):
            max = 0
            for j in range(1, i // 2 + 1):
                product = products[j] * products[i - j]
                if (max < product):
                    max = product
                products[i] = max

        max = products[number]
        return max

    def cutRope2(self, number):
        # 贪心算法
        if number < 2:
            return 0
        if number == 2:
            return 1
        if number == 3:
            return 2

        timesOf3 = number // 3
        if number - timesOf3 * 3 == 1:
            timesOf3 -= 1
        timesOf2 = (number - timesOf3 * 3) // 2
        return int(pow(3, timesOf3)) * int(pow(2, timesOf2))


if __name__ == '__main__':
    length = 8
    so = Solution()
    print(so.cutRope(length))
    print(so.cutRope2(length))

15-位运算

# -*- coding: utf-8 -*-
"""
// 面试题15:二进制中1的个数
// 题目:请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如
// 把9表示成二进制是1001,有2位是1。因此如果输入9,该函数输出2。
"""
class Solution:
    def NumberOf1(self, n):
        # 最佳解法
        count = 0
        if n < 0: # 如果该整数是负数,要把它和0xffffffff相与,消除负数的影响。
            n = n & 0xffffffff
        while n:
            n = (n - 1) & n
            count += 1
        return count
    def NumberOf1_2(self, n):
        # 解法2 使用python特性
        return bin(n & 0xffffffff).count("1")
if __name__ == '__main__':
    so = Solution()
    print(so.NumberOf1(9))
    print(so.NumberOf1_2(9))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值