leetcode marathon [复习] 8.24 - 9道

组合,排列,子集

给出一个集合[1,2,3,4],输出其:
组合:k=2,[1,2],[1,3],[1,4]…
排列:1234,1243,1324,1342…
子集:[1],[1,2],[1,2,3]…
编写代码时,主要分为两类

排列顺序需要考虑:排列

road 代表已有轨迹,choice代表选择
每次需要复制,并添加新的选择,choice去除选择

为什么要复制,不用全局数组?
主要在于其中的for循环
road 和 choice 都要参与到下一次循环,而我们希望这轮执行完,和初始一致(有的不需要,比如visited数组,就直接用全局很舒服)
所以 要不就是对road和choice复制后 操作
或者 操作完,把它恢复原状

def permute(self, nums):
    """
    :type nums: List[int]
    :rtype: List[List[int]]
    """

    k = len(nums)
    result = []

    def dfs(road, choice_n):
        if len(road) == k:
            result.append(road)
            return
        else:
            for num_n in choice_n:
                road_new = road[:]
                road_new.append(num_n)
                choice_new = choice_n[:]
                choice_new.remove(num_n)
                dfs(road_new, choice_new)

    dfs([], nums)
    return result

排列顺序不需要考虑:组合,子集

很巧妙的方法,通过for循环开始的位置
保证只能遍历后面的

组合

截至位置为 有k个数

def combine(n, k):
    """
    :type n: int
    :type k: int
    :rtype: List[List[int]]
    """
    res=[]

    def dfs(track,start,choice):
        print(f"当前track:{track}")
        print(f"当前start:{start}")
        if len(track)==k:
            res.append(track)
            return
        else:
            # 关键是理解 其中的start,每个节点的选择只能是当前节点后面的
            for i in range(start,len(choice)):
                num=choice[i]
                track_new=track[:]
                track_new.append(num)
                dfs(track_new,i+1,choice)

    dfs([],0,[i+1 for i in range(n)])
    return res

子集

每个遍历点都加上

def subsets(nums):
    res=[]
    def dfs(track,start,choice):
        res.append(track)
        for i in range(start,len(choice)):
            new_track=track[:]
            new_track.append(choice[i])
            dfs(new_track,i+1,choice)
    dfs([],0,nums)
    res.remove([])
    return res

没有重复数字的子集,组合,排列

首先把初始数组排序一下,然后记录last_num,一样则不添加…第一个赋值成" ",字符串还巧滴.
47. 全排列 II

def permuteUnique(nums):
    """
    :type nums: List[int]
    :rtype: List[List[int]]
    """
    nums=sorted(nums)
    print(f"排序后:{nums}")
    n=len(nums)
    res=[]
    def dfs(track,choice):
        print(f"track:{track}")
        print(f"choice:{choice}")
        if len(track)==n:
            res.append(track)
            return
        else:
            last_num=" "
            for num in choice:

                if num == last_num:
                    continue
                last_num=num
                new_choice=choice[:]
                new_choice.remove(num)
                new_track=track[:]
                new_track.append(num)
                dfs(new_track,new_choice)
    dfs([],nums)
    return res

if __name__ == '__main__':
    nums=[1,1,2]
    print(permuteUnique(nums))

41. 缺失的第一个正数 -两个思路

本地存储

它要求常数空间复杂度, 立马想到本地存储,本地存储指的是直接在本数组中存储信息,比如全是正数,那么某一位是负数的时候,就代表这一位被标记了.

```python
def firstMissingPositive(nums):
    """
    :type nums: List[int]
    :rtype: int
    """
    n=len(nums)
    # 第一次循环将所有负数全变成n+1
    for i in range(len(nums)):
        if nums[i] <= 0:
            nums[i] = n+1
    print(nums)
    # 第二次循环将所有>0且<=n的数 对应的索引上的数全变成负数
    # 注意索引与该数之间差1哦
    # 防止[1,1,1]这种情况,变成负数的时候,要先检查它是否是正数
    for i in range(len(nums)):
        if abs(nums[i]) <= n and nums[abs(nums[i])-1] >0:
            nums[abs(nums[i])-1] = -nums[abs(nums[i])-1]

    print(nums)
    for i in range(len(nums)):
        if nums[i] > 0:
            return i+1
    return n+1

跳转遍历

指的是o(n)时间复杂度的遍历

需要 能够区分本位置的数对不对
然后立足于本位置,不断交换

在这里插入图片描述

rom typing import List


class Solution:

    # 3 应该放在索引为 2 的地方
    # 4 应该放在索引为 3 的地方

    def firstMissingPositive(self, nums: List[int]) -> int:
        size = len(nums)
        for i in range(size):
            # 先判断这个数字是不是索引,然后判断这个数字是不是放在了正确的地方
            while 1 <= nums[i] <= size and nums[i] != nums[nums[i] - 1]:
                self.__swap(nums, i, nums[i] - 1)

        for i in range(size):
            if i + 1 != nums[i]:
                return i + 1

        return size + 1

    def __swap(self, nums, index1, index2):
        nums[index1], nums[index2] = nums[index2], nums[index1]

50. Pow(x, n)

记忆化递归

快速幂算法

比如 2 10 = 2 5 ∗ 2 5 2^{10}=2^5 * 2^5 210=2525 只需要算pow(2,5) 即可
利用递归(二分的思路),加上记忆化策略(当函数遇到相同参数时,直接用cache) 语法糖@cache

class Solution:
    def myPow(self, x: float, n: int) -> float:
        """
        :type x: float
        :type n: int
        :rtype: float
        """
        return dfs(x,n)
@cache
def dfs(x,n):

    # 如果是1的话
    if n==0:
        return 1
    if n == 1:
        return x
    # 如果是2的话
    if n==2:
        return x*x
    if n==-1:
        return 1/x
    # 如果n是偶数的话
    if n%2==0:

        return dfs(x,n//2)*dfs(x,n//2)
    else: # 如果是奇数的话
        return dfs(x,n//2)*dfs(x,n//2)*dfs(x,n%2)

58. 最后一个单词的长度

正则表达式 字符串处理

很多字符串题目可以直接用正则表达式做
这题是最基础那种,连正则表达式都不需要

def lengthOfLastWord(s):
    """
    :type s: str
    :rtype: int
    """
    # api 战士
    return len(s.strip().split(" ")[-1])

71. 简化路径

正则表达式+栈

用re.split 轻松分割
用栈,类似括号匹配的思路
遇到… 则弹出一个

import re
class Solution:
    def simplifyPath(self, path: str) -> str:
        stack1=[]
        names=re.split(r'/+',path)
        print(names)
        for name in names:
            if name=='..':
                if len(stack1)!=0:
                    stack1.pop()
            elif name=='.' or name=='':
                continue
            else:
                stack1.append(name)
        return "/"+"/".join(stack1)

125. 验证回文串

正则表达式

import re
class Solution:
    def ispalindrome(self, s: str) -> bool:
        a="".join(re.split(r"[^a-zA-Z0-9]+",s)).lower()
        if len(a)%2==0:
            if a[:len(a)//2]==a[len(a)//2:][::-1]:
                return True
        if len(a)%2==1:
            if a[:len(a)//2]==a[len(a)//2+1:][::-1]:
                return True
        return False

26. 删除有序数组中的重复项

本地修改-快慢指针

需要在数组原地存储,则用慢指针来存储,快指针用来访问

# 快慢指针
# 慢指针负责存储
# 快指针负责查找
# 当快指针找到一个符合要求的则传给慢指针
def removeDuplicates(nums):
    """
    :type nums: List[int]
    :rtype: int
    """
    slow=0
    for fast in range(len(nums)):
        if nums[fast] != nums[slow]:
            slow+=1
            nums[slow]=nums[fast]
    return nums[:slow+1]

相关文章

显卡天梯图2024最新版,显卡是电脑进行图形处理的重要设备,...
初始化电脑时出现问题怎么办,可以使用win系统的安装介质,连...
todesk远程开机怎么设置,两台电脑要在同一局域网内,然后需...
油猴谷歌插件怎么安装,可以通过谷歌应用商店进行安装,需要...
虚拟内存这个名词想必很多人都听说过,我们在使用电脑的时候...