• 2020/8/17:Pow(x, n)、最大子序和 、最多元素
    • 第一题:pow(x,n):
    • 第二题:最大子序和
    • 第三题:最多元素
  • 2020/8/18:最长回文子串 / 编辑距离
    • 最长回文子串
    • 编辑距离
  • 2020/8/19:打家劫舍I/II、最长回文子序列
    • 打家劫舍
    • 最长回文子序列
  • 2020/8/20:最长连续递增序列 / 搜索插入位置
    • 最长连续递增序列
    • 搜索插入位置
  • 2020/8/25:快乐数、字符出现频率排序、同构字符串

2020/8/17:Pow(x, n)、最大子序和 、最多元素

三道题目都属于分治,分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解,具体将在下面的题目中体现。

第一题:pow(x,n):

实现 pow(x, n) ,即计算 x 的 n 次幂函数:

示例 1:
输入: 2.00000, 10
输出: 1024.00000

示例 2:
输入: 2.10000, 3
输出: 9.26100

示例 3:
输入: 2.00000, -2
输出: 0.25000
解释: 2-2 = 1/22 = 1/4 = 0.25

说明:
-100.0 < x < 100.0
n 是 32 位有符号整数,其数值范围是 [−231, 231 − 1] 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/powx-n

首先不管什么方法,都要用最快最有效的方式得到答案,其中一个答案对于各种语言都适用,就是直接将题目抄下来加return,因为pow本身就属于math包下的内置函数,含义是计算 x 的 y 次方,在python中,它的使用方式与底层为:

return pow(x, y[, z])    # 写法1,pow(x,y) %z
return x ** y % Z       # 写法2
"""
Equivalent to x**y (with two arguments) or x**y % z (with three arguments)Some types, such as ints, are able to use a more efficient algorithm when
invoked using the three argument form.
"""

但我纠结的是小数点后5位,因为python有比较严重的精度丢失,如果有decimal模块创建数据还好,float很大程度会四舍五入,除非以"%.5f" % L1 用str形式打印内容,但那就不是整数了,但看了下解答发现自己想多了。而想想用第二种思路:分治

x10=x(1010)2=x1∗23+0∗22+1∗21+0∗20=x1∗23∗x0∗22x1∗21∗x0∗20x^{10}=x^{(1010)_{2}}=x^{1 * 2^{3}+0 * 2^{2}+1 * 2^{1}+0 * 2^{0}}=x^{1 * 2^{3}} * x^{0 * 2^{2}} x^{1 * 2^{1}} * x^{0 * 2^{0}}x10=x(1010)2​=x1∗23+0∗22+1∗21+0∗20=x1∗23∗x0∗22x1∗21∗x0∗20

上面式子是通过十进制与二进制数转换来表示幂的乘积,如果上式成立,那么会得到:

xn={(x2)n//2,n为偶数 x(x2)n//2,n为奇数 x^{n}=\left\{\begin{array}{ll}\left(x^{2}\right)^{n / / 2} & , n \text { 为偶数 } \\ x\left(x^{2}\right)^{n / / 2} & , n \text { 为奇数 }\end{array}\right.xn={(x2)n//2x(x2)n//2​,n 为偶数 ,n 为奇数 ​

那用 Pow(x, n) (快速幂,清晰图解) 这个题解中的二进制计算中的位运算就能很快得出答案:

class Solution:def myPow(self, x: float, n: int) -> float:if x == 0.0: return 0.0res = 1if n < 0: x, n = 1 / x, -nwhile n:if n & 1: res *= xx *= xn >>= 1return res

第二题:最大子序和

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:

输入: [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-subarray

本题思考的是用动态规划去求解,因为出现了最大和连续与数组等字样,那基本不用想也能用DP求解,那排除掉特殊情况,动态规划的思路为:

  • 从第二个数开始循环,取其与前一个数为sum
  • 如果 sum > 0,则说明 sum 对结果有增益效果,则 sum 保留并加上当前遍历数字
  • 如果 sum <= 0,则说明 sum 对结果无增益效果,需要舍弃,则 sum 直接更新为当前遍历数字
  • 遍历结束返回max
class Solution:def maxSubArray(self, nums: List[int]) -> int:if not nums:return 0elif len(nums) == 1:return nums[0]for i in range(1, len(nums)):# 当前索引i永远存储0~i的最大和nums[i] = max(nums[i], nums[i] + nums[i - 1])# 返回每个索引最大和的最大值return max(nums)"""
第二种写法
"""
class Solution:def maxSubArray(self, nums: List[int]) -> int:if not nums:return 0elif len(nums) == 1:return nums[0]else:for i in range(1, len(nums)):nums[i] = nums[i] + max(nums[i - 1],0)return max(nums)

另外,看到了有个大佬用了分治,我这里没想到怎么用,也没考虑用,所以这里标记一下:

class Solution:def maxSubArray(self, nums: List[int]) -> int:n = len(nums)#递归终止条件if n == 1:return nums[0]else:#递归计算左半边最大子序和max_left = self.maxSubArray(nums[0:len(nums) // 2])#递归计算右半边最大子序和max_right = self.maxSubArray(nums[len(nums) // 2:len(nums)])#计算中间的最大子序和,从右到左计算左边的最大子序和,从左到右计算右边的最大子序和,再相加max_l = nums[len(nums) // 2 - 1]tmp = 0for i in range(len(nums) // 2 - 1, -1, -1):tmp += nums[i]max_l = max(tmp, max_l)max_r = nums[len(nums) // 2]tmp = 0for i in range(len(nums) // 2, len(nums)):tmp += nums[i]max_r = max(tmp, max_r)#返回三个中的最大值return max(max_right,max_left,max_l+max_r)

链接:https://leetcode-cn.com/problems/maximum-subarray/solution/bao-li-qiu-jie-by-pandawakaka/

第三题:最多元素

这题在python里也比较容易,题目太长就直接饮用链接:
https://leetcode-cn.com/problems/majority-element/

这里有很多种解法,可以用hash表做记录然后求最大值,这也是我最直观的一种解法:

class Solution:def majorityElement(self, nums: List[int]) -> int:dicts = {}for i in nums:dicts[i] = dicts.get(i,0) + 1return (max(dicts, key=dicts.get))

第二种可以用python工具类中的counter:

from collections import Counterclass Solution:def majorityElement(self, nums: List[int]) -> int:count = Counter(nums)return count.most_common(1)[0][0]

LeetCode中内置了collections类,因为这是刷题必备的一个工具类,如果在python解释器下,这个包还是需要import。但这个题目最优秀的做法还是从题目意思中体现了:出现次数大于 ⌊ n/2 ⌋ 的元素。也就是说结果要的数,一定是在数组中数量超过1/2,那么就能排序后用中数:

return sorted(nums)[len(nums)//2]

2020/8/18:最长回文子串 / 编辑距离

最长回文子串

最长回文子串我记得很早之前我刷过,知道是用动态规划,然而还是先用暴力来写了,状态方程没有想到,去翻了下很早的博客,思路整理如下:

暴力求解,用队尾元素的删除,让原串来和取反后的进行比较,一旦出现相等的情况,那么就是最大子串:

class Solution:def longestPalindrome(self, s: str) -> str:for length in range(len(s), -1, -1):for index in range(0, len(s) - length + 1):sub_string = s[index:length + index]if sub_string == sub_string[::-1]:return sub_string

另一种解法是对上述的优化,确实强,其主要是把每个字母当成回文串的结束,进行缩放:

class Solution:def longestPalindrome(self, s: str) -> str:if not s: return ""length = len(s)if length == 1 or s == s[::-1]: return smax_len,start = 1,0for i in range(1, length):even = s[i-max_len:i+1]odd = s[i-max_len-1:i+1]if i - max_len - 1 >= 0 and odd == odd[::-1]:start = i - max_len - 1max_len += 2continueif i - max_len >= 0 and even == even[::-1]:start = i - max_lenmax_len += 1continuereturn s[start:start + max_len]

关于动态规划的解法,首先可以看看求两个字符串的最长公共字串:

可能有点小丑,但无伤大雅。通过上图所示,max为最长公共子串的长度,以及maxIndex为最长子串结尾字符在字符数组中的位置,由这两个值就可以确定最长公共子串为"cad",实现代码参考python算法面试宝典,如下:

"""
方法功能:获取两个字符串的最长公共字串
输入参数:str1和str2为指向字符的引用(指针)
"""
def getMaxSubStr(str1,str2):len1 = len(str1)len2 = len(str2)SJ = ''maxs = 0 # 用来记录最长公共子串的长度maxI = 0 # 用来记录最长公共字串最后一个字符的位置"""申请新的空间来记录公共字符长度信息"""M = [[0 for i in range(len1 + 1)] for j in range(len2 + 1)]"""利用递归公式构建二维数组"""i,j = 0, 0 """动态规划推导"""while i < len1 + 1:j = 1while j < len2 + 1:if list(str1)[i-1] == list(str2)[j-1]:M[i][j] = M[i-1][j-1] + 1if M[i][j] > maxs:maxs = M[i][j]maxI = ielse:M[i][j] = 0j += 1i += 1"""找出公共子串"""i = maxI - maxswhile i < maxI:SJ = SJ + list(str1)[i]i += 1return SJ

而若是求自身的最大子串,参照上面的理解,那么我可以将JJJ变为SSS的逆序,图解为:

dp[i][j]={true, str [i]==str⁡[j]and dp[i+1][j−1]==tr⁡ue∣1false d p[i][j]=\left\{\begin{array}{c}\text { true, str }[i]==\operatorname{str}[j] \text { and } d p[i+1][j-1]==\operatorname{tr} u e \mid 1 \\ \text { false }\end{array}\right.dp[i][j]={ true, str [i]==str[j] and dp[i+1][j−1]==true∣1 false ​

那么代码为:

class Solution:def longestPalindrome(self, s: str) -> str:length = len(s)dp = [[0] * length for _ in range(length)]left, right = 0, 0 #长度为1时for i in range(1, length):for j in range(length-i):if s[j] == s[j+i] and (j+1 >= j+i-1 or dp[j+1][j+i-1]):dp[j][j+i] = 1 left, right = j, j+ireturn s[left: right+1]

编辑距离

这题并没看懂,然后手边还有其它任务没做完,就先看了下讲解视频,结合官方的文字说明,发现还是对动态规划不熟,如果将删除、编辑和插入都看成是一种状态,确实就简单了。mark一下:

dp[i - 1][j - 1] # 替换,同时前移 i,j
dp[i - 1][j]        # 删除,前移i
dp[i][j-1]          # 插入,前移j
class Solution:def minDistance(self, word1: str, word2: str) -> int:m = len(word1)n = len(word2)dp = [[float('inf') for _ in range(n + 1)] for _ in range(m + 1)]# 初始化for i in range(m + 1):dp[i][0] = ifor i in range(n + 1):dp[0][i] = i# 状态转移# i , j 代表 word1, word2 对应位置的 indexfor i in range(1, m + 1):for j in range(1, n + 1):# 如果word1[:i][-1]==word2[:j][-1],即表示两个的操作最小距离相等,继续向上判断if word1[i - 1] == word2[j - 1]:dp[i][j] = dp[i - 1][j - 1]# 否则从三种状态中选一个最小的然后 +1else:dp[i][j] = min(dp[i - 1][j - 1], min(dp[i - 1][j], dp[i][j - 1])) + 1return dp[m][n]

2020/8/19:打家劫舍I/II、最长回文子序列

打家劫舍

打家劫舍I是一个很明显的dp问题,当然也能看做是求奇偶和最大的一方,这两种看起来都没有什么问题,所以代码如下:

class Solution:def rob(self, nums: List[int]) -> int:if not nums: return 0if len(nums)<=2:return max(nums)# 初始状态dp = [0] * len(nums)dp[0] = nums[0]dp[1] = max(nums[0],nums[1])# dp状态转移方程for i in range(2,len(nums)):dp[i] = max(dp[i-1],dp[i-2]+ nums[i]) return dp[-1]

然后打家劫舍II,这题充分暴露了我的短板,我确实想用将打家劫舍I中的两种方法结合起来,判奇偶和动态规划,感觉可以一步到胃,然而确实阵阵胃疼。。。奇数的判断是没问题的,主要是偶数的两个列表,[1,2,3,1][2,1,1,2]。被卡死了。。。最后发现还是得两遍循环:

class Solution:def rob(self, nums: List[int]) -> int:if not nums : return 0if len(nums) == 1: return nums[0]def helper(nums):if not nums : return 0if len(nums) == 1: return nums[0]n = len(nums)dp = [0] * (n + 1)dp[1] = nums[0]for i in range(2, n + 1):dp[i] = max(dp[i - 1], dp[i - 2] + nums[i - 1])return dp[-1]return max(helper(nums[1:]), helper(nums[:-1]))

最长回文子序列

被一个bug搞得有点崩,等今晚有时间再完善思路和解法。

现在是第二天晚上,发现今天并不想回看,算了。。

class Solution:def longestPalindromeSubseq(self, s: str) -> int:n = len(s)maxL = -1dp = [[0]*n for _ in range(n)]for i in range(n):dp[i][i] = 1for i in range(n-1, -1, -1):for j in range(i+1, n):if s[i] == s[j]:dp[i][j] = dp[i+1][j-1] + 2else:dp[i][j] = max(dp[i][j-1], dp[i+1][j])return dp[0][n-1]

2020/8/20:最长连续递增序列 / 搜索插入位置

最长连续递增序列

最简单的一种思路就是对于后一个大于前一个值的序列进行加一,从上面的题刷下来,确实这题一下就写出来了:

class Solution:def findLengthOfLCIS(self, nums: List[int]) -> int:n=len(nums)if not nums or n<0:return 0dp=[1]*nfor i in range(1,n):if nums[i]>nums[i-1]:dp[i]=dp[i-1]+1return max(dp)

第二种思路是用单指针的方式,让当前指针永远都指向最大的子序列长度:

class Solution:def findLengthOfLCIS(self, nums: List[int]) -> int:if not nums:return 0legth = 1maxleght = 1for i in range(1,len(nums)):if nums[i] > nums[i-1]:legth+= 1if legth > maxleght:maxleght = legthelse:legth = 1return maxleght

搜索插入位置

// An highlighted block
var foo = 'bar';

2020/8/25:快乐数、字符出现频率排序、同构字符串

可惜今天七夕,这还快乐数?那我快乐就够了,规定找寻50次,如果超过50次还没有变成1,那就是陷入了死循环,返回False

class Solution:def isHappy(self, n: int) -> bool:times = 0while times <= 50:n = sum([int(i)**2 for i in str(n)])print(n)times += 1if n == 1:breakreturn n == 1

同构字符串

class Solution:def isIsomorphic(self, s: str, t: str) -> bool:hashmap={}for i,j in zip(s,t):if i in hashmap and hashmap[i]!=j:return Falseelif i not in hashmap and j in hashmap.values():return Falsehashmap[i]=jreturn True

根据字符出现频率排序

class Solution:def frequencySort(self, s: str) -> str:# Counterreturn ''.join([i * j for i, j in collections.Counter(s).most_common()])

LeetCode刷题笔记——(8/17 - 8/27)相关推荐

  1. LeetCode刷题笔记:17.电话号码的字母组合

    1. 问题描述 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合.答案可以按 任意顺序 返回. 给出数字到字母的映射如下(与电话按键相同).注意 1 不对应任何字母. 2: " ...

  2. LeetCode刷题笔记(算法思想 四)

    LeetCode刷题笔记(算法思想 四) 七.动态规划 斐波那契数列 70. 爬楼梯 198. 打家劫舍 213. 打家劫舍 II 信件错排 母牛生产 矩阵路径 64. 最小路径和 62. 不同路径 ...

  3. 卷进大厂系列之LeetCode刷题笔记:二分查找(简单)

    LeetCode刷题笔记:二分查找(简单) 学算法,刷力扣,加油卷,进大厂! 题目描述 涉及算法 题目解答 学算法,刷力扣,加油卷,进大厂! 题目描述 力扣题目链接 给定一个 n 个元素有序的(升序) ...

  4. LeetCode刷题笔记2——数组2

    LeetCode刷题笔记2--数组2 重塑数组 题目 在 MATLAB 中,有一个非常有用的函数 reshape ,它可以将一个 m x n 矩阵重塑为另一个大小不同(r x c)的新矩阵,但保留其原 ...

  5. 小何同学的leetcode刷题笔记 基础篇(01)整数反转

    小何同学的leetcode刷题笔记 基础篇(01)整数反转[07] *** [01]数学取余法*** 对数字进行数位操作时,常见的方法便是用取余的方法提取出各位数字,再进行操作 操作(1):对10取余 ...

  6. LeetCode刷题笔记汇总

    LeetCode刷题笔记汇总 第一次刷LeetCode写的一些笔记. 1.两数之和 3.无重复字符的最长子串 15.三数之和 18.四数之和 19.删除链表的倒数第 N 个结点 20.有效的括号 21 ...

  7. 【leetcode刷题笔记】动态规划

    #[leetcode刷题笔记]动态规划 石子游戏 public boolean stoneGame(int[] piles) {int N = piles.length;// dp[i][j] is ...

  8. LeetCode刷题笔记-动态规划-day4

    文章目录 LeetCode刷题笔记-动态规划-day4 55. 跳跃游戏 1.题目 2.解题思路 3.代码 45. 跳跃游戏 II 1.题目 2.解题思路 3.代码 LeetCode刷题笔记-动态规划 ...

  9. LeetCode刷题笔记- 15.三数之和

    LeetCode刷题笔记- 15.三数之和 C语言 题目 注意点 C语言 /*** Return an array of arrays of size *returnSize.* The sizes ...

  10. LeetCode刷题笔记第6题:Z字形变换

    LeetCode刷题笔记第6题:Z字形变换 想法: 要完成字符串根据给定的行数从上往下,从左到右完成Z字形排列.当只有一行时直接返回原字符串,当行数大于1时,先以行数构建一个行数数值个空字符串的列表, ...

最新文章

  1. 孔兵 库卡机器人_库卡机器人中华区CEO孔兵:机器人是制造业升级的关键
  2. Leetcode 47. 全排列 II (每日一题 20211015)
  3. 《漫画算法2》源码整理-6 两数之和 三数之和
  4. C++ 中的引用 和指针的区别
  5. python下采样_python + opencv 如何在上采样下采样之后导出图片?
  6. 网速慢?不!可能是DNS出了问题! 公共DNS优选之 BAT 百度、腾讯、阿里、谷歌DNS哪个更快?
  7. superviseddescent (SDM C++11实现)环境配置
  8. form提交后台注解拿不到数据_浏览器是如何将用户数据发送到服务器的?
  9. 2014年二级c语言,2014年计算机二级考试C语言选择题
  10. 分享:MySQL 学习笔记(三)
  11. webdriver.chrome()禁止加载图片
  12. 在 Web 浏览器中运行(PowerApps)应用
  13. 你见过花140年拼出来的现存“古代最高积木”吗?
  14. java 判断pc还是手机_Java判断验证访问是手机端还是PC电脑端
  15. 安卓没有删除谷歌服务框架
  16. 数据通信最新技术复习
  17. 苹果设邮箱的126服务器,Mac系统中的邮箱创建126邮箱帐户的方法
  18. 【Orientation】详解Android中的屏幕方向
  19. Jquery遍历对象
  20. HTTPS安全通信:HTTPS与SSL

热门文章

  1. android水波纹教程,Android实现简单水波纹效果
  2. 09年高考零分作文:兔子,你就是一个牛B
  3. Prove the EXACT 4SAT is NP-complete.
  4. EndNoteX9保姆级基础功能使用教程(够用!!)
  5. 【EndNote】使用教程
  6. 二值化神经网络——BNN
  7. zipException error in opening zip file
  8. java ico_Java 读写 ICO 图像
  9. 裸机linux分区,裸机装linux系统怎么操作?
  10. CF1442D Sum 分治 背包dp