LeetCode整理笔记

本文整理了LeetCode中的核心算法,包括双指针、分治策略、动态规划、堆、栈等,并通过具体题目详细阐述解题思路,如滑动窗口、分治查找、动态规划求解最长回文子串、最小覆盖子串等,适合程序员提升算法能力。

整理进度:1-201,518-581,1017-1024

待归档:

记忆化广搜:
#576 Out of Boundary Paths

排序问题:
#581 Shortest Unsorted Continuous Subarray

凸包:
#587 Erect the Fence

哈希,重复模式:
#594 Longest Harmonious Subsequence

滑动窗口:
#611 Valid Triangle Number

找规律:
#621 Task Scheduler

动规/记忆化搜索/贪心:
#630 Course Schedule III

双指针滑动窗口

  • #3 Longest Substring Without Repeating Characters

    • 思路1:
      后指针向后滑动以添加新的元素,前指针向后滑动保证滑动窗口内无重复字符
    • 思路2:
      维护每个字符最后一次出现的位置,后指针发现一个前面出现过的字符时,前指针可以直接跳到该字符最后出现的位置后面,i = max(i, lastpos[s[j]]),效率更高一些
  • #11 Container With Most Water
    前指针、后指针中间的区域为一个桶,桶的面积为高乘以宽,当i、j为两端时,桶宽最大,当i、j向中间滑动时,只有桶高增加,桶面积才有可能增大。若移动长板,桶高不可能增大,因此只能移动短板对应的指针。

  • #1 2Sum
    当前后指针和大于k,前移后指针(和变小),否则后移前指针(和变大)

  • #15 3Sum
    遍历并固定第一个数,从而把问题转换为2Sum
    同理 #16 3Sum Closest、#18 4Sum

  • #76 Minimum Window Substring
    滑动窗口前后指针都从起始位置开始,先移动后指针使得窗口内数组符合要求,然后移动前指针直到窗口内数组不再符合要求,随后再次移动后指针,依此类推。

分治策略

  • #4 Median of Two Sorted Arrays

    • 思路1:双约束二分
      寻找A数组中的指针i、B数组中的指针j,使得两指针之前的元素的并集构成两数组的前半部分,这样就会产生两个约束条件,也即:
      ①前后两部分元素个数相等:i + j = m - i + n - j
      ②前半部分的最大值小于后半部分最小值:A[i - 1] <= B[j] && B[j - 1] <= A[i]
      由于i、j满足约束条件①,因此只要确定了i,就可以确定j,如此一来,只需要寻找i的合适位置
      如此一来可以利用二分搜索维护 i 的区间 [i_min, i_max],下次搜索区间可以利用约束条件②来确定
    • 思路2:归并
      简单把两个数组归并后找中位数,但需要用到额外的空间
  • #33 Search in Rotated Sorted Array
    首先用二分搜索找到数组中的最小元素,之后就可以构造出旋转前的数组元素对应在旋转后的数组中的位置索引,根据这一索引进行全局的二分搜索即可。#153 Find Minimum in Rotated Sorted Array 和这道题是一样的
    若考虑数组中存在重复元素,则需要在查找数组最小元素的二分搜索步骤中添加一个预处理步骤,保证二分区间的左右端点值不同,见 #81 Search in Rotated Sorted Array II#154 Find Minimum in Rotated Sorted Array II

  • #50 Pow(x, n)
    二分求快速幂,注意考虑幂的正负

  • #69 Sqrt(x)
    二分确定x的范围,比较x^2与a的大小

  • #74 Search a 2D Matrix
    其实不能算是分治策略,但形式有点像二维的二分搜索,所以干脆放在这里
    从右上角开始进行搜索,若小于目标值,则向下搜索,若大于目标值,则向左搜索,时间复杂度O(m + n)

  • #162 Find Peak Element
    很像之前遇到过的一个面试题目
    这道题如果用O(n)的算法是非常简单的,我们需要找到一个O(logn)的算法
    二分策略的一般流程是,先找到区间的中点元素,将这个元素与某一个标准进行对比,从而决定接下来的区间选择哪一侧
    对比标准常见的有:1、与某个目标值作对比,比如二分查找;2、与左右端点值作对比,比如上面的 #33 Search in Rotated Sorted Array;3、与中点元素两侧的元素作对比,相当于判断中点元素处的单调性,比如这道题就是。
    我们判断nums[mid]与左右两侧元素的大小,如果这一点正好是peak,就直接输出,如果某一侧单调递增,则在这一侧必存在一个peak元素(若递增后开始递减,则存在peak,若一直递增到数组末尾,因为设定nums[nums.size()] = -∞,所以此时末尾元素是一个peak),进而可以将搜索区间决定到这一侧

动态规划

  • #5 Longest Palindromic Substring

    • 思路1:与反向字符串计算最长公共子串
      回文串的问题,一般都可以试试对比原string与反向string的方法
    • 思路2:区间动规
      dp[i][j]表示子串 [i, j] 是否为回文子串
    • 思路3:中心扩展判断回文串
      遍历所有的回文串中心(考虑奇数、偶数长度),从中心向外扩展可以用O(n)的时间找到该中心位置对应的最长回文串,这个思路其实相当直接,但时空复杂度相对于上面两个动规反而更好
  • #10 Regular Expression Matching
    算是经典题目,.表示任意匹配单字符,*表示前一字符可以出现任意次数
    dp[i][j]表示模式串前 i 位是否能与字符串前 j 位匹配

  • #32 Longest Valid Parentheses
    dp[i]表示以i为结尾的最长合法括号子串长度
    s[i] == '('时,dp[i] = 0
    s[i] == ')'时,
    ①若s[i - 1] == '(',则dp[i] = dp[i - 2] + 2
    ②若s[i - 1] == ')' && s[i - dp[i - 1] - 1] == '(',则dp[i] = dp[i - 1] + 2 + dp[i - dp[i - 1] - 2]

  • #44 Wildcard Matching
    和#10类似的字符串匹配问题,这里*不再代表前一字符出现任意次数,而是代表任意序列(可为空)

    • 思路1:动规,可以考虑用滚动数组优化空间
      dp[i][j]表示字符串前前 i 位与模式串前 j 位匹配
      dp[i][j] = dp[i - 1][j - 1] && (s[i - 1] == p[j - 1] || p[j - 1] == '?'), if p[j - 1] != '*'
      dp[i][j] = dp[i][j - 1] || dp[i - 1][j], if p[j - 1] == '*'
    • 思路2:贪心
      若发现模式串出现*,则记录当前模式串/字符串遍历位置pi与si,继续往下匹配,若匹配失败,则返回记录的位置,字符串每次匹配失败后重新开始匹配的位置需要前移一位
  • #53 Maximum Subarray
    dp[i]表示以i为结尾的子数组最大值,则dp[i] = max(dp[i - 1] + arr[i], arr[i]),由于dp[i]仅与dp[i - 1]相关,所以可以降维到0维。
    同理**#121 Best Time to Buy and Sell Stock**

  • #188 Best Time to Buy and Sell Stock IV
    同系列的还有 #121 Best Time to Buy and Sell Stock#122 Best Time to Buy and Sell Stock II#123 Best Time to Buy and Sell Stock III
    第k次购入仅和第k-1次卖出时的收益相关,第k次卖出仅和第k次购入时的收益相关
    rele[i][j]表示 i 时刻进行第 j 次卖出的最大收益,以hold[i][j]表示 i 时刻进行第 j 次买入的最大收益

    for(int i=0; i<prices.size(); i++){
         
         
        for(int j=k; j>=1; j--){
         
         
            rele[j] = max(rele[j], prices[i]-hold[j]);
            hold[j] = min(hold[j], prices[i]-rele[j-1]);
            maxProfit=max(maxProfit, rele[j]);
        }
    }
    
  • #198 House Robber
    同系列的还有 #213 House Robber II#337 House Robber III
    个人感觉和前面的Best Time to Buy and Sell Stock是同一类型的题目,都是在每个时间步有两种不同的状态,区别在于Stock题目两种状态之间必须相互转移,而Robber这道题状态转移不一定发生在两种状态之间。
    这类题目可以推广到多个不同状态。

  • #72 Edit Distance
    类似正则匹配的方程,dp[i][j]表示a串0…i - 1位与b串0…j - 1位的编辑距离

    for (int i = 1; i <= m; i++) {
         
         
        for (int j = 1; j <= n; j++) {
         
         
            if (word1[i - 1] == word2[j - 1]) 
                dp[i][j] = dp[i - 1][j - 1];
            else dp[i][j] = min(dp[i - 1][j - 1] + 1, min(dp[i][j - 1] + 1, dp[i - 1][j] + 1));
        }
    }
    
  • #518 Coin Change 2
    dp[i]表示 i 有多少种组合方法,这里需要注意,因为找零是一个组合问题,要忽略顺序,所以选用类似带数量限制的背包问题的方法求解,amount放在内层循环,并倒序遍历从而防止重复选用同一种面额。

    for (int j = 0; j 
概要:   DevCon 实用工具是一种命令行实用工具,可以替代设备管理器。使用 DevCon,您可以启用禁用、重新启动、更新、删除查询单个设备或一组设备。DevCon 提供与开发人员有关但无法在设备管理器中看到的信息。   您可以将 DevCon 用于 Windows 2000 、Windows XPWindows vista。不能将 Devcon 用于 Microsoft Windows 95、Windows 98、或 Windows Millennium Edition。   下载:http://download.microsoft.com/download/1/1/f/11f7dd10-272d-4cd2-896f-9ce67f3e0240/devcon.exe 用法及参数说明:   devcon.exe [-r] [-m:\\] [...]   -r 如果指定它,在命令完成后若需要则重新启动计算机。    是目标计算机的名称。    是将要执行的命令(如下所示)。   ... 是命令需要的一个或多个参数。   要获取关于某一特定命令的帮助,请键入:devcon.exe help   classfilter 允许修改类别筛选程序。   classes 列出所有设备安装类别。   disable 禁用与指定的硬件或实例 ID 匹配的设备。   driverfiles 列出针对设备安装的驱动程序文件。   drivernodes 列出设备的所有驱动程序节点。   enable 启用与指定的硬件或 实例 ID 匹配的设备。   find 查找与指定的硬件或 实例 ID 匹配的设备。   findall 查找设备,包括那些未显示的设备。   help 显示此信息。   hwids 列出设备的硬件 ID。   install 手动安装设备。   listclass 列出某一安装类别的所有设备。   reboot 重新启动本地计算机。   remove 删除与特定的硬件或 实例 ID 匹配的设备。   rescan 扫描以发现新的硬件。   resources 列出设备的硬件资源。   restart 重新启动与特定的硬件或 实例 ID 匹配的设备。   stack 列出预期的设备驱动程序堆栈。   status 列出设备的运行状态。   update 手动更新设备。   UpdateNI 手动更新设备,无用户提示   SetHwID 添加、删除更改根枚举设备的硬件 ID 的顺序。 示例:   devcon -m:\\test find pci\* 列出计算机 test 上的所有已知 PCI 设备。(通过使用 -m,您可以指定一个目标计算机。您必须使用“进程间通信”(IPC) 访问此计算机。)   devcon -r install Windows directory\Inf\Netloop.inf *MSLOOP 安装一个新的 Microsoft 环回适配器实例。这将创建一个新的根枚举设备节点,使用此节点您可以安装“虚拟设备”,如环回适配器。如果需要重新启动计算机,此命令还将以安静模式重启计算机。   devcon classes 列出所有已知的安装类别。输出结果包含短的未本地化的名称(例如,“USB”)描述性名称(例如,“通用串行总线控制器”)。 禁用启用网卡的步骤:   1.用devcon hwids PCI*命令得到所有以PCI开头的设备。这时会列出很多设备,那么哪个才是网卡对应的呢?   2.打开设备管理器,展开网络适配器,找到网卡的名称,然后记住到刚才得到的列表中找对应的Name,然后你会在下面看到好几个ID,随便挑一个就行   3.用devcon disable "PCI\VEN_11AB&DEV_4380&SUBSYS_301B17AA&REV_10"禁用网卡(启用的话讲disable换成enable就行了)   4.其实用PCI开头得到的几组设备中一般第一个就是网卡设备 sysdzw 16:01 2010-11-16
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值