Leetcode刷题记录

Problem 30 字符查找题
一开始的想法是将words进行全排列,再找s里面的匹配,但是由于全排列n!运算,耗时过长。
于是改由在s里面找到words里面的词,接下来就继续配对,配对一个words的词就remove,知道words为空。耗时1400ms, 勉强通过,但是内存占用较大。

class Solution:
    def findSubstring(self, s: 'str', words: 'List[str]') -> 'List[int]':
        count=len(words)
        if len(s)==0 or count==0: 
            return []
        lens=len(words[0])
        if len(s)<count*lens:
            return []
        index=[]
        for i in range(len(s)-count*lens+1):
            j=i
            temp=words.copy()
            while s[j:j+lens] in temp:
                temp.remove(s[j:j+lens])
                j+=lens
                if temp==[]:
                    index.append(i)
        return index   

Problem 31 字典排序题
看了solution的启示写的,升序的空间来源于非降序的排列,也就是97521没有空间升序了,因此只要找到a[i]>a[i-1],便可进行升序,最邻近的升序排列需要一次交换以及逆序。设立哨兵对应321的情况。

class Solution:
    def swap(self,num,i,j):
        temp=num[i]
        num[i]=num[j]
        num[j]=temp
        return num
    def reverse(self,num,i):
        num[i:len(num)]=num[i:len(num)][::-1]
        return num
    def nextPermutation(self, num: 'List[int]') -> 'None':
        """
        Do not return anything, modify nums in-place instead.
        """
        army=0
        for i in range(len(num)-1,0,-1):
            if num[i]>num[i-1]:
                army=1
                dis=num[i]-num[i-1]
                k=i
                for j in range(i,len(num),1):
                    if num[j]-num[i-1]<=dis and num[j]-num[i-1]>0:
                        dis=num[j]-num[i-1]
                        k=j
                self.swap(num,i-1,k)                
                self.reverse(num,i)
                break
        if len(num)==1 or army==0:
            self.reverse(num,0)

Problem 32 Longest Valid Parentheses 字符匹配题
solution的做法,用栈,初始化为-1.遍历s,若为“(”,则将index压入栈等待配对,否则删除栈最近的元素(即完成配对)。连续距离即为当前位置到未匹配字符的坐标距离。

class Solution:
    def max(self,a,b):
        if a>=b:
            return a
        else:
            return b
    def longestValidParentheses(self, s: str) -> int:
        max_length=0
        stack=[-1]
        for i in range(len(s)):
            if s[i]=='(':
                stack.append(i)
            else:
                stack.pop()
                if len(stack)==0:
                    stack.append(i)
                else:
                    max_length=self.max(max_length,i-stack[-1])
        return max_length
                

Problem33 Search in Rotated Sorted Array
由于nums由排序数列折叠,可根据0位数判断搜索方向,减少搜索长度。

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        if len(nums)==0:
            return -1
        if target<nums[0]:
            for i in range(len(nums)-1,-1,-1):
                if nums[i]==target:
                    return i
                elif nums[i]<nums[i-1]:
                    return -1
        else:
            for i in range(len(nums)):
                if nums[i]==target:
                    return i
                elif nums[i]<nums[0]:
                    return -1

Problem34 Find First and Last Position of Element in Sorted Array
主要用两小段遍历查找first和last,首先由左到右遍历nums,第一个等于target的index返回存为first,跳出循环,否则不存在匹配target,返回[-1,-1]。第二次遍历从first右边开始,第一个不等于target的index-1存为last。

class Solution(object):
    def searchRange(self, nums, target):
        first, last = 0, 0
        i, j = 0, 0
        
        for i in range(len(nums)):
            if nums[i] == target:
                first = i
                break
        else:
            return [-1, -1]
        
        for j in range(i+1, len(nums)):
            if nums[j] != target:
                return [i, j-1]
        return [i, j or i]

Problem 35:Search Insert Position
查找插入数字的位置,目标序列已排序,因此用最直接的做法,就是找到大于等于target的位置,O(n)复杂度

class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
        if len(nums)==0:
            return 0
        for i in range(len(nums)):
            if nums[i]>=target:
                return i
        else:
            return len(nums)

Problem 36: Valid Sudoku
建立99 行、列、九格矩阵,用于遍历board时存储各行、列、九格内的数字分布情况,当有数字发生重复时返回false。
一开始用[None
9]*9初始化,但是发现创建的后面八行实际上是对第一行的复制,所以会跟随前面的赋值行为。

class Solution:
    def isValidSudoku(self, board: List[List[str]]) -> bool:
        rows = [[0 for i in range(9)] for j in range(9)]
        cols = [[0 for i in range(9)] for j in range(9)]
        boxs = [[0 for i in range(9)] for j in range(9)]
        for i in range(9):
            for j in range(9):
                num=board[i][j]
                if num is not '.':
                    num=int(num)-1
                    if (rows[i][num]==1) or (cols[j][num]==1) or (boxs[3*int(i/3)+int(j/3)][num]==1):
                        return False
                    else:
                        rows[i][num]=boxs[3*int(i/3)+int(j/3)][num]=cols[j][num]=1
        return True

Problem 37: Sudoku Solver
求解数独。先用row,cols,boxes三个变量存储各行各列各块已有数字,以及用blank记录空值坐标。
函数fill用于求解。选定含有信息量最大的位置开始填充,可选数字为1-9除去同行同列以及同块已有的数字,循环调用fill,如果blank全为空,即填充满,便结束循环,否则退回上一步的数字选择。

class Solution:
    def solveSudoku(self, board: List[List[str]]) -> None:
        """
        Do not return anything, modify board in-place instead.
        """
        if board == None or len(board) == 0: return
        nums=set('123456789')
        rows = [set() for j in range(9)]
        cols = [set() for j in range(9)]
        boxs = [[set() for j in range(3)] for i in range(3)]
        blank= []
        for i in range(9):
            for j in range(9):
                num=board[i][j]
                if num is not '.':
                    rows[i].add(num)
                    cols[j].add(num)
                    boxs[i//3][j//3].add(num)
                else:
                    blank.append([i,j])
        def fill():
            i,j=max(blank,key=lambda index: len(rows[index[0]])+len(cols[index[1]])+len(boxs[index[0]//3][index[1]//3]))  #firstly try the index where collect most information
            blank.remove([i,j])
            for num in nums-rows[i].union(cols[j]).union(boxs[i//3][j//3]):
                board[i][j] = num; rows[i].add(num); cols[j].add(num); boxs[i//3][j//3].add(num)
                if not blank: return True
                if fill(): return True
                board[i][j] = '.'; rows[i].remove(num); cols[j].remove(num); boxs[i//3][j//3].remove(num)
            blank.append([i, j])
            return False
        if not blank: return
        fill()  

38. Count and Say
递归调用countandsay函数,用read函数读出上一行的输出作为输出。

class Solution:
    def countAndSay(self, n: int) -> str:
        if n==1:
            return '1'
        temp=self.countAndSay(n-1)
        def read(temp):
            ans=''
            count=1
            for k,i in enumerate(temp):
                if k+1<len(temp) and temp[k]!=temp[k+1]:
                    ans=ans+str(count)+i
                    count=1
                elif k+1<len(temp):
                    count+=1
            return ans+str(count)+i
        temp=read(temp)
        return temp

39. Combination Sum
给定target和不重复正整数数列,数列元素可重复使用,找出所有求和为target的不重复组合。
看的是LeetCode社区分享的答案,这个递归调用太绕了,理解了一晚上。

class Solution:
    def combinationSum(self, candidates: 'List[int]', target: 'int') -> 'List[List[int]]':
        candidates.sort()
        return self.combinationSum_helper(candidates, 0, target)
    def combinationSum_helper(self, candidates, idx, target):
        if target==0:
            return [[]]
        com=[]
        for i in range(idx,len(candidates)):
            if candidates[i]>target:
                break
            else:
                new=self.combinationSum_helper(candidates, i, target-candidates[i])
                if new!=[]:
                    for s in new:
                        com.append(s+[candidates[i]])
        return com

40. Combination Sum II
和前面一题差不多,区别在于数列元素会重复,且不能重复使用元素。因此修改了combination_helper里面的起始检索位置,改成从当前坐标+1即可,但是会有重复数列组合,因此对com里面的元素做了重复检查。

class Solution:
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        candidates=[i for i in candidates if i<=target]
        candidates.sort()
        return self.combinationSum_helper(candidates, 0, target)
    def combinationSum_helper(self, candidates, idx, target):
        if target==0:
            return [[]]
        com=[]
        for i in range(idx,len(candidates)):
            if candidates[i]>target:
                break
            else:
                new=self.combinationSum_helper(candidates, i+1, target-candidates[i])
                if new!=[]:
                    for s in new:
                        if s+[candidates[i]] not in com:
                            com.append(s+[candidates[i]])
        return com
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值