Python小白 Leetcode刷题历程 No.36-No.40 有效的数独、解数独、外观数列、组合总和、组合总和Ⅱ (有题干 有代码 有思路心得)

Python小白 Leetcode刷题历程 No.36-No.40 有效的数独、解数独、外观数列、组合总和、组合总和Ⅱ

写在前面:

作为一个计算机院的大学生,总觉得仅仅在学校粗略的学习计算机专业课是不够的,尤其是假期大量的空档期,作为一个小白,实习也莫得路子,又不想白白耗费时间。于是选择了Leetcode这个平台来刷题库。编程我只学过基础的C语言,现在在自学Python,所以用Python3.8刷题库。现在我Python掌握的还不是很熟练,算法什么的也还没学,就先不考虑算法上的优化了,单纯以解题为目的,复杂程度什么的以后有时间再优化。计划顺序五个题写一篇日志,希望其他初学编程的人起到一些帮助,写算是对自己学习历程的一个见证了吧。

有一起刷LeetCode的可以关注我一下,我会一直发LeetCode题库Python3解法的,也可以一起探讨。

觉得有用的话可以点赞关注下哦,谢谢大家!
········································································································································································

No.36.有效的数独

难度:中等
题目描述:


在这里插入图片描述

在这里插入图片描述

题解代码(Python3.8)

class Solution:
    def isValidSudoku(self, board: List[List[str]]) -> bool:
        set_box=set()
        for i in range(9):
            for j in range(9):
                if board[i][j].isdigit():
                    row = 'row_'+str(i)+' ' + board[i][j]
                    col = 'col_'+str(j)+' ' + board[i][j]
                    small_square = 'row-col_'+str(i//3)+'-'+str(j//3)+' ' + board[i][j]
                    if  row in set_box or col in set_box or small_square in set_box:
                        return False
                    set_box.update([row,col,small_square])
        return True

或许有用的知识点:
set.add(key)可以在set中添加一个元素,set.remove(key)可以在set中删除一个元素。
如果想在set中一次性假如多个元素,可使用set.update([key1,key2,key3])。

解题思路:
在数独9宫格中,每个数字必定带有三个特性:行数、列数、小方块位置。对于一个i行j列的元素n,我们不妨定义它的特性为,row=row_i n , col=col_j n , small_square=row-col_(i//3)-(j)//3 n。对于每个数,我们将他的三个特性储存到一个set中。当新一个数字的三个特性都不在set中,我们便将其写入set;如果新一个数字有特性已经在set中了,不满足条件,返回False。

No.37.解数独

难度:困难
题目描述:


在这里插入图片描述

在这里插入图片描述

题解代码(Python3.8)

class Solution:
    def solveSudoku(self, board: List[List[str]]) -> None:
        row = [set(range(1,10)) for _ in range(9)]      #行剩余可用数字
        col = [set(range(1,10)) for _ in range(9)]      #列剩余可用数字
        block = [set(range(1,10)) for _ in range(9)]    #块剩余可用数字
        empty = []                                      #收集空白位置 
        for i in range(9):
            for j in range(9):
                if board[i][j] != '.':
                    val = int(board[i][j])
                    row[i].remove(val)
                    col[j].remove(val)
                    block[(i//3)*3+(j//3)].remove(val)
                else:
                    empty.append((i,j))
        
        def backtrack(iter_=0):
            if iter_ == len(empty):
                return True
            i,j = empty[iter_]
            block_index = (i//3)*3+(j//3)
            for val in row[i] & col [j] & block[block_index]:
                row[i].remove(val)
                col[j].remove(val)
                block[block_index].remove(val)
                board[i][j] = str(val)
                if backtrack(iter_+1):
                    return True
                row[i].add(val)
                col[j].add(val)
                block[block_index].add(val)
            return False

        backtrack()

或许有用的知识点:
这道题需要使用回溯算法。
set( range(j) ) for _ in range(i),可以制作一个i行j列的set型二维数组,例如set( range(3)) for _ in range(4) = [ {0,1,2} , {0,1,2} , {0,1,2} , {0,1,2} ]。
要求列表A,B,C的公共元素,应使用 A & B & C ,(逻辑运算 and or not 只会返回运算的布尔值)。

解题思路:
先确定回溯函数,对比回溯函数模板,回溯出口为iter_长度与empty相等,回溯主体中在当发现子状态的有效解后进入下一状态,否则回溯到原来状态。
之后初始化状态,要有行剩余可用数字、列剩余可用数字、块剩余可用数字、空白方格位置。最后调用回溯函数即可。

No.38.外观数列

难度:简单
题目描述:


在这里插入图片描述

题解代码(Python3.8)

class Solution:
    def countAndSay(self, n: int) -> str:
        prev_person = '1'
        for i in range(1,n):
            next_person,num,count = '',prev_person[0],1
            for j in range(1,len(prev_person)):
                if prev_person[j] == num:
                    count +=1
                else:
                    next_person += str(count)+num
                    num = prev_person[j]
                    count =1
            next_person += str(count)+num
            prev_person = next_person
        return prev_person

解题思路:
这个题就是题比较难读懂,我翻译了一下,其实就是:
1.1
2.描述的是1,是一个1,也就是11
3.描述的是11,是两个1,也就是21

  1. 描述的是21,是一个2一个1,也就是12-11
  2. 描述的是1211, 是一个1,一个2,两个1,也就是11-12-21
  3. 描述的是111221,是三个1,两个2,一个1,也就是31-22-11
  4. 描述的是312211,是一个3一个1两个2两个1,也即是13-11-22-21
    以此类推
    所以对字符串进行一次遍历就好,将已生成的最后一个数称为‘上一个数’,再通过‘上一个数’推出‘下一个数’,然后把‘下一个数’的值赋给上一个数,继续遍历即可。

No.39.组合总和

难度:中等
题目描述:


在这里插入图片描述

题解代码(Python3.8)

class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        l=len(candidates)
        if l==0:
            return []
        candidates.sort()
        path=[]
        res=[]
        
        def backtrack(begin,path,target):
            if target==0:
                res.append(path[:])
            for i in range(begin,l):
                target_next=target-candidates[i]        #剪枝操作
                if target_next<0:
                    break
                path.append(candidates[i])
                backtrack(i,path,target_next)
                path.pop()
        
        backtrack(0,path,target)
        return res

或许有用的知识点:
这道题要用到回溯算法。
a=p与a=p[:]的区别:a=p是把p的地址给a,p和a指向同一对象;而a=p[:]是创建一个内容与p全等的对象,命名为a,a指向p的副本,p和a指向不同对象。再回溯算法中,对可能被回溯的待保存元素,有时需要以a=p[:] 的方式储存。

解题思路:
定义回溯函数,在减的过程中,得到 0或者负数,就没有必要再走下去,所以这两种情况就分别表示成为叶子结点。此时递归结束,然后要发生回溯。注意,这道题中组合里的数字可以无限制重复被选取。而要想完成剪枝,前提是数组是有序的,因此我们需要对数组进行排序。注意,Python 中可变对象是引用传递,因此需要将当前 path 里的值拷贝出来,即a=p[:]。

No.40.组合总和Ⅱ

难度:中等
题目描述:


在这里插入图片描述

题解代码(Python3.8)

class Solution:
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        l=len(candidates)
        if l==0:
            return []
        candidates.sort()                                           #初始化
        path=[]
        res=[]
        
        def backtrack(begin,path,target):
            if target==0:                                           #回溯出口
                res.append(path[:])
            for i in range(begin,l):                                #回溯主体
                target_next=target-candidates[i]    #剪枝操作
                if target_next<0:
                    break
                if i>begin and candidates[i-1]==candidates[i]:
                    continue
                path.append(candidates[i])
                backtrack(i+1,path,target_next)
                path.pop()                                          #状态返回
        
        backtrack(0,path,target)
        return res

或许有用的知识点:
这道题要用到回溯算法。
a=p与a=p[:]的区别:a=p是把p的地址给a,p和a指向同一对象;而a=p[:]是创建一个内容与p全等的对象,命名为a,a指向p的副本,p和a指向不同对象。再回溯算法中,对可能被回溯的待保存元素,有时需要以a=p[:] 的方式储存。

解题思路:
这道题跟‘39.组合总和’的思路类似,都是定义回溯函数,与其差别就是这道题组合中每个数只能用使用一次。在减的过程中,得到 0或者负数,就没有必要再走下去,所以这两种情况就分别表示成为叶子结点。此时递归结束,然后要发生回溯。要想完成剪枝,前提是数组是有序的,因此我们需要对数组进行排序。注意,Python 中可变对象是引用传递,因此需要将当前 path 里的值拷贝出来,即a=p[:]。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,743评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,296评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,285评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,485评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,581评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,821评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,960评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,719评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,186评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,516评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,650评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,936评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,757评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,991评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,370评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,527评论 2 349