LeetCode每周记录-7

Posted HorribleMe

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode每周记录-7相关的知识,希望对你有一定的参考价值。

判断一个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的主要内容,如果未能解决你的问题,请参考以下文章

leetcode每周记录

资料 | 从 0 开始刷 LeetCode 的心得记录

sqlserver 获取到日期范围内每天,每周,每月,每年记录

团队交流记录 - 2020-04

Leetcode 763 划分字母区间

OI每周刷题记录