码迷,mamicode.com
首页 > 其他好文 > 详细

LeetCode每周记录-7

时间:2020-05-02 22:32:56      阅读:71      评论:0      收藏:0      [点我收藏+]

标签:可能性   row   dfs   依次   target   清空   规律   完成后   info   

技术图片

判断一个9*9数组是否满足数独游戏规则:每行、每列、每3*3小格不能有相同的数。我的方法是按行进行遍历,同时用9个数组存储每列的数字,再用3个数组存储3个小格的数字(这3个数组每遍历完三行进行一次清空);遍历的同时判断新发现的数字在对应的行、列、3*3小格里是否已经存在,存在的话直接返回False。遍历完成后返回True。代码:

class Solution(object):
    def isValidSudoku(self, board):
        """
        :type board: List[List[str]]
        :rtype: bool
        """
        columns = [[] for _i in xrange(9)]
        boxes = [[] for _i in xrange(3)]
        for i in xrange(9):
            _tempRow = []
            if i % 3 == 0:
                boxes = [[] for _i in xrange(3)]
            for j in xrange(9):
                _c = board[i][j]
                currBox = boxes[j / 3]
                if _c != .:
                    if _c in currBox or _c in columns[j] or _c in _tempRow:
                        return False
                    else:
                        currBox.append(_c)
                        _tempRow.append(_c)
                        columns[j].append(_c)
        return True

 

 

 

技术图片

 

数独填空,上一题的进一步扩展。给出一个9*9数组,里面有空格和数字,用1-9填满空格,并使数组满足数独规则。思路是首先找出所有的空格位置并用一个数组存储下来,并且把9*9数组拆分为9行、9列、9小格来分别进行合法性判定。然后利用递归依次对空格位置尝试进行填补,用来填补的数由当前的行、列、小格的情况获得,填补成功,则把所有的状态传入下一个递归循环,所有可能性失败则退回上一层递归。代码:

class Solution:
    def getPosNums(self, board, position, rows, columns, sub_boxes):
        nums = []
        row, column = position
        box_idx = (row // 3) * 3 + column // 3
        for s in map(str, range(1, 10)):
            if (not s in rows[row]) and (not s in columns[column]) and (not s in sub_boxes[box_idx]):
                nums.append(s)
        return nums

    def init(self, board, emptyPos, rows, columns, sub_boxes):
        for i in range(9):
            for j in range(9):
                tmp = board[i][j]
                if tmp != .:
                    rows[i].add(tmp)
                    columns[j].add(tmp)
                    box_idx = (i // 3) * 3 + (j // 3)
                    sub_boxes[box_idx].add(tmp)
                else:
                    emptyPos.append((i, j))
        return

    def solveSudoku(self, board):

        emptyPos = []
        rows = [set() for i in range(9)]
        columns = [set() for i in range(9)]
        sub_boxes = [set() for i in range(9)]

        self.init(board, emptyPos, rows, columns, sub_boxes)

        def solve(board, positions):
            if not positions:
                return True

            posNums = self.getPosNums(board, positions[0], rows, columns, sub_boxes)

            if not posNums:
                return False

            row, column = positions[0]
            box_idx = (row // 3) * 3 + (column // 3)
            for s in posNums:
                board[row][column] = s
                rows[row].add(s)
                columns[column].add(s)
                sub_boxes[box_idx].add(s)

                if solve(board, positions[1:]):
                    return True

                rows[row].remove(s)
                columns[column].remove(s)
                sub_boxes[box_idx].remove(s)

            board[row][column] = .
            return False

        solve(board, emptyPos)
        return

 

 

 

技术图片

按照题目中给出的这个规律(后一项是对前一项的描述,比如第三项是21,那么对其描述为:一个2和一个1,即1211),结合题目给出的整数n,返回这个规律下第n下的字符串。给出的n不会超过30,所以按照规则一项一项地求出第n项即可,用一个front记录上一项的结果,代码:

class Solution(object):
    def countAndSay(self, n):
        """
        :type n: int
        :rtype: str
        """
        if n == 1:
            return 1
        front = None
        output = ‘‘
        for idx, i in enumerate(self.countAndSay(n-1)):
            if i != front:
                if front != None:
                    output = output + str(count) + front
                elif idx == 0 and n == 2:
                        output = output + str(1) + i        
                front = i
                count = 1
            else:
                count += 1
        
        if n > 2:
            output = output + str(count) + i
        return output

 

 

 

技术图片

给出一个数组合一个目标数target,找出这个数组中相加和为target的所有组合。思路是利用递归的方法,先对数组进行排序,然后递归查找组合可能性,当前和满足要求则记录。代码:

class Solution(object):
    def combinationSum(self, candidates, target):
        res = []
        candidates.sort()
        self.dfs(candidates, target, 0, [], res)
        return res
    
    def dfs(self, nums, target, index, path, res):
        if target < 0:
            return
        if target == 0:
            res.append(path)
            return 
        for i in xrange(index, len(nums)):
            self.dfs(nums, target-nums[i], i, path+[nums[i]], res)

 

 

 

技术图片

上一题的扩展,新增的要求是原有数组中的数不能在一个可能性组合里重复使用。思路和上一题一样,只需要注意进行递归时,传入下一层递归循环的剩余可使用的数需要剔除当前这一层使用到的数。代码:

class Solution(object):
    def combinationSum2(self, candidates, target):
        """
        :type candidates: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        if not candidates:
            return []
        
        ret = []
        
        def fn(nums, tmp):
            if sum(tmp) > target:
                return False
            elif sum(tmp) == target:
                if tmp not in ret:
                    ret.append(tmp)
                return True
            else:
                for i in range(len(nums)):
                    if i>0 and nums[i] == nums[i-1]: continue
                    fn(nums[i+1:],tmp+[nums[i]])
        
        candidates.sort()
        fn(candidates,[])
        return ret

 

LeetCode每周记录-7

标签:可能性   row   dfs   依次   target   清空   规律   完成后   info   

原文地址:https://www.cnblogs.com/HorribleMe/p/12819884.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!