> 文章列表 > leetcode 1~10 学习经历

leetcode 1~10 学习经历

leetcode 1~10 学习经历

LeetCode 习题 1 - 10

  • 1. 两数之和
  • 2. 两数相加
  • 3. 无重复字符的最长子串
  • 4. 寻找两个正序数组的中位数
  • 5. 最长回文子串
  • 6. N 字形变换
  • 7. 整数反转
  • 8. 字符串转换整数 (atoi)
  • 9. 回文数
  • 10. 正则表达式匹配

1. 两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。

示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]

提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案

进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?
通过次数4,194,521提交次数7,931,754

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/two-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一遍,暴力计算,复杂度 O(n^2)

class Solution:def twoSum(self, nums: List[int], target: int) -> List[int]:n = len(nums)for i in range(n-1):for j in range(i+1,n):if nums[i] + nums[j] == target:return [i,j]

leetcode 1~10 学习经历
竟然还能击败这么多人吗?难道这不是最土的办法吗?
然后想办法优化下,利用一下 python 本身的方法

第二遍,排序后计算,嗯,其实我也不知道复杂度是多少,但他就是运行时间减少了那么多

class Solution:def twoSum(self, nums: List[int], target: int) -> List[int]:arr = [_ for _ in nums]arr.sort(reverse=True)n = len(arr)for i in range(n-1):for j in range(1,n):if arr[i] + arr[j] == target:pos = nums.index(arr[i])if arr[i] != arr[j]:return [pos,nums.index(arr[j])]else:return [pos,nums[pos+1:].index(arr[j])+pos+1]

leetcode 1~10 学习经历
leetcode 1~10 学习经历
第三遍,利用集合set来看看

class Solution:def twoSum(self, nums: List[int], target: int) -> List[int]:n = {}for i in range(len(nums)):if nums[i] in n.keys():n[nums[i]] = (n[nums[i]] + [i])[:2]else:n[nums[i]] = [i]for i in n.keys():if target == i * 2:if len(n[i])>1:return n[i]continueif target - i in n.keys():return [n[i][0],n[target - i][0]]

https://leetcode.cn/submissions/detail/403539238/
leetcode 1~10 学习经历
内存消耗越来越大了。。。到底怎么能把内存消耗也减掉一些呢
第四遍,实在搞不懂,抄一下官方题解吧

class Solution:def twoSum(self, nums: List[int], target: int) -> List[int]:hashtable = dict()for i, num in enumerate(nums):if target - num in hashtable:return [hashtable[target - num], i]hashtable[nums[i]] = ireturn []

leetcode 1~10 学习经历
leetcode 1~10 学习经历
????诧异了,执行时间居然比我第三遍的还多一点。。。吓得我多执行了几次第三遍代码,哦,赶巧了啊,平均用时还是40多一点,嗯这个题目就确定了,用hashtable、dict之类的方法就是最好的办法了

2. 两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

leetcode 1~10 学习经历

示例 1:
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
示例 2:
输入:l1 = [0], l2 = [0]
输出:[0]
示例 3:
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]

提示:
每个链表中的节点数在范围 [1, 100] 内
0 <= Node.val <= 9
题目数据保证列表表示的数字不含前导零
通过次数1,641,150提交次数3,875,235

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/add-two-numbers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

老顾是个野路子,链表是个啥东西也都是最近才开始接触,平时工作里真就没用上过这东西。。。
还好题目中代码给了个 ListNode 的构造,不用一头雾水的琢磨了,然后大概也明白 Node 是个什么东西了,就琢磨了第一个版本的代码

class Solution:def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:u = l1d = l2r = ListNode()z = rf = 0n = 0while u or d or n>0:if f:r.next = ListNode()r = r.nexts = (u.val if u else 0) + (d.val if d else 0) + nr.val = s % 10n = s // 10u = u.next if u else Noned = d.next if d else Nonef = 1return z

leetcode 1~10 学习经历

其实这个题,就是逆序的10进制加法,不过所有数都是倒着的,第一个是各位数,第二位是十位数,第三位是千位数这样的。。。最后返回的链表要求也是逆序的,这就ok

嗯。。。。用了很多没啥意义的变量,纯粹是懒得改了,提交的时候就是这样,算法好像也没啥算法,老顾对链表真的不懂,不知道这种单向链表(也不知道对不对)怎么就能方便的返回每个节点的值,就这么用本办法弄出来了,然后开始学习,去看官方题解。。。好吧,竟然没有 python 版本的题解,而 java 的和 c# 的,居然方法内的内容一毛一样。。。除了变量更容易让人读懂,和老顾的写法也没啥本质区别了。。。瞎猫碰到死耗子了

3. 无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

提示:
0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成
通过次数2,182,219提交次数5,580,531

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/longest-substring-without-repeating-characters
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

还好,这个题目看着就很简单,嗯,从第一个字符遍历,然后记录遍历的起始位置,碰到重复的字符,记录长度,并和最大长度比较,然后遍历的起始位置从重复的字符后一个开始。。。嗯,思路很清晰,来,写代码了

class Solution:def lengthOfLongestSubstring(self, s: str) -> int:n = len(s)if n<2:return nmx = 1# 576ms,15.1mbpos = 0while pos < n:nxt = 1if pos + nxt == n:breakfinal = 0while s[pos + nxt] not in s[pos:pos + nxt]:if mx < nxt + 1:mx = nxt + 1nxt += 1if pos + nxt == n:final = 1breakif final == 1:breakpos += s[pos:pos + nxt].index(s[pos + nxt]) + 1return mx

leetcode 1~10 学习经历
额。。。。这个成绩有点惨不忍睹啊。。。。倒数的前8%。。。。。琢磨琢磨怎么给优化一下,思路应该没什么大问题吧?
嗯,pos 和 nxt 意义不大,不如取消这两个变量,直接用字符串代替,也不再用 s[pos:pos+nxt] 方式计算,直接用一个字符串代替这一堆

class Solution:def lengthOfLongestSubstring(self, s: str) -> int:n = len(s)if n<2:return nmx = 1# 100ms,15.1mbl = ''for i in range(n):while s[i] in l:l = l[1:]l += s[i]mx = max(mx,len(l))return mx

嗯。。。。看着舒服很多,这次不至于那么惨的成绩了吧,看看先
https://leetcode.cn/submissions/detail/403660974/
leetcode 1~10 学习经历
嗯,碰到一次赶巧的成绩,那估计我的这个代码也没啥问题了,翻了翻官方题解。。。。好吧,不能说没啥区别,只能说完全一个路子

4. 寻找两个正序数组的中位数

给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
算法的时间复杂度应该为 O(log (m+n)) 。

示例 1:
输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
示例 2:
输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5

提示:
nums1.length == m
nums2.length == n
0 <= m <= 1000
0 <= n <= 1000
1 <= m + n <= 2000
-106 <= nums1[i], nums2[i] <= 106
通过次数889,905提交次数2,135,574

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/median-of-two-sorted-arrays
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

其实,题目到是真不难,问题在于要理解题意。。。开始没弄明白,什么叫中位数,看了看两个示例,还以为是平均数,一提交,人家不认。。。
leetcode 1~10 学习经历
额。。。。那中位数是啥?难道是两个数组中合并后,最中间的那一个或两个数的平均数?那就再试试吧

一通操作猛如虎,还好成绩不是250

class Solution:def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:arr = nums1 + nums2arr.sort()n = (len(arr) + 1) // 2 - 1if len(arr) % 2 == 1:return arr[n]else:return (arr[n] + arr[n+1]) / 2

leetcode 1~10 学习经历
当然,这里的运算取巧了,毕竟不管 js 也好,python 也好,排序已经不是主要目标了,通常都会直接用系统提供的办法完成,这次只是确定了中位数的概念。。。。嗯,试着不用自身的 sort ,自己来按顺序插入数字。。。反而慢了一半,算了,不折腾了。。。估计这个题考的目的就是排序插入新数组,70ms完成应该也可以了,就当我过了,嘿嘿
说句题外话,这个题目的评价难度居然是困难,没看出困难在哪里。。。。

5. 最长回文子串

给你一个字符串 s,找到 s 中最长的回文子串。
如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

示例 1:
输入:s = “babad”
输出:“bab”
解释:“aba” 同样是符合题意的答案。
示例 2:
输入:s = “cbbd”
输出:“bb”

提示:
1 <= s.length <= 1000
s 仅由数字和英文字母组成
通过次数1,322,154提交次数3,534,763

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/longest-palindromic-substring
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一遍,还是暴力思路,这人呐,脑子闲置的久了,就用不上了。。。

class Solution:def longestPalindrome(self, s: str) -> str:n = len(s)if n < 2:return sr = s[0]for i in range(n):for j in range(i+1,n+1):if s[i:j] == s[i:j][::-1]:if j-i>len(r):r = s[i:j]return r

然后,不出所料的没有能通过
leetcode 1~10 学习经历
这个是真没想法啊。。。。只好去看题解,嗯嗯嗯嗯,学了很多写法,印象最深刻的,并且自己能理解透的,也就是那个Manacher算法。。。设计真精巧啊

class Solution:def longestPalindrome(self, s: str) -> str:r = ''t = '^#' + '#'.join(s) + '#$'n = len(t)p = [0 for _ in range(n)]for i in range(1,n-1):while t[i - p[i] - 1] == t[i + p[i] + 1]:p[i] += 1mx = max(p)idx = p.index(mx)b = (idx - mx) // 2r = s[b:b+mx]return r

leetcode 1~10 学习经历

这。。。。跑了好几遍,基本都在1000ms左右?点开提交结果一看。。。排不上号啊。。。

leetcode 1~10 学习经历
看来,还得继续学习,而且看官方题解已经不够了,得学别人的写法了,好在,可以点执行用时分布里的时间点看别人的代码,真棒

先找了个900ms左右的答案。。。嗯中心扩散法,学习学习

# 以下内容抄自leetcode第5题908ms答案,实际运行能达到600ms左右
class Solution:def longestPalindrome(self, s: str) -> str:#暴力解法# cur_str = max_str = ''# for i in range(len(s)):#     for j in s[i:]:#         cur_str += j#         if cur_str == cur_str[::-1] and len(cur_str) > len(max_str):#             max_str = cur_str#     cur_str = ''# return max_str#中心扩散法left = right = start = 0cur_len = max_len = 1 for i in range(len(s)):left = i - 1right = i +1while left >= 0 and s[i] == s[left]:left -= 1cur_len += 1while right < len(s) and s[i] == s[right]:right += 1cur_len += 1while left >= 0 and right < len(s) and s[left] == s[right]:left -= 1right += 1cur_len += 2print(s[left], cur_len,end ='QWQ ')while cur_len > max_len:max_len = cur_lenstart = left + 1cur_len = 1                                   #少了这句找了一小时bugprint(start, end='')print(max_len)return s[start: start + max_len]
# 以下内容抄自leetcode第5题800ms答案,实际运行能达到600ms左右
class Solution:def longestPalindrome(self, s: str) -> str:palindrome = ''for i in range(len(s)):len1 = len(self.getLongestPalindrome(s,i,i))if len1> len(palindrome):palindrome = self.getLongestPalindrome(s,i,i)len2 = len(self.getLongestPalindrome(s,i,i+1))if len2> len(palindrome):palindrome = self.getLongestPalindrome(s,i,i+1)return palindromedef getLongestPalindrome(self,s,l,r):while l>=0 and r<len(s) and s[l]==s[r]:l-=1r+=1return s[l+1:r]

可惜只能看到答案,不知道是哪位同学提交的,嗯,都是提交的源代码,我一个字符都没改动过的。
这两个答案都是中心扩散法,老顾就不说题解了,自己写一遍试试看,其他同学关于中心扩散法的说明很多,官方题解里也有

# 老顾自己搞一版
class Solution:def longestPalindrome(self, s: str) -> str:n = len(s)if n < 2 or s == s[::-1]:return st = s[0]for i in range(n):mx = 1while i - mx >= 0 and i + mx < n and s[i - mx] == s[i + mx]:r = s[i - mx:i + mx + 1]mx += 1if len(r) > len(t):t = rmx = 1while i - mx + 1 >= 0 and i + mx < n and s[i - mx + 1] == s[i + mx]:r = s[i - mx + 1:i + mx + 1]mx += 1if len(r) > len(t):t = rreturn t

leetcode 1~10 学习经历
额。。。。。。这执行用时超出我的预料啊,我还以为也就600ms左右呢。。。。

然后,我们来抄个最厉害的答案吧,40ms执行时间的。。。

# 以下内容抄自leetcode第5题40ms答案
class Solution:def longestPalindrome(self, s: str) -> str:        if len(s) < 2 or s == s[::-1]:            return s        res = s[0]        maxlen = 1        for i in range(1, len(s)):            odd = s[i - maxlen - 1: i + 1]even = s[i - maxlen: i + 1]if even == even[::-1] and i - maxlen >= 0:res = evenmaxlen += 1continueif odd == odd[::-1] and i - maxlen - 1 >= 0:res = oddmaxlen += 2continuereturn res

https://leetcode.cn/submissions/detail/403938742/
leetcode 1~10 学习经历
肯定是我的电脑和网络问题,竟然跑了几次都没挨到40,人家的最高成绩是36ms。。。。
这位的办法更直接,直接判断当前位置按最大长度中心扩散,得到单双两个字符串,如果其中一个是回文。。。省略了前边的判定,估计在python中好用,其他语言环境就难言了

另一个更暴力的

# 以下内容抄自leetcode第5题56ms答案
class Solution:def longestPalindrome(self, s: str) -> str:#res=''for i in range(len(s)):start=max(0,i-len(res)-1)temp=s[start:i+1]if temp==temp[::-1]:res=tempelse:temp=temp[1:]if temp==temp[::-1]:res=tempreturn res

leetcode 1~10 学习经历
效率虽然略有不如前边的,但他的思路更简洁,实现起来更简单啊。。。。

抄个java的40ms看看。。。其实也差不多。。。

// 以下内容抄自leetcode第5题40ms答案
class Solution {public String longestPalindrome(String s) {if(s.length()==0){return s;}if(s.length()==1){return s;}if(s.length()==2){if(s.charAt(0)==s.charAt(1)){return s;}else{return s.substring(0,1);}}String result="";for(int i =1;i<s.length();i++){char a = s.charAt(i);int start = i-1;int end = i+1;while (start>=0&&end<=s.length()-1){if(end-i==1){while (s.charAt(start)==a){start -= 1;if(start<0){break;}}while (s.charAt(end)==a){end +=1;if(end>s.length()-1){break;}}String temp = s.substring(start+1,end);if(temp.length()>result.length()){result=temp;}}if(start<0||end>s.length()-1){break;}if(s.charAt(start)==s.charAt(end)){String temp = s.substring(start,end+1);if(temp.length()>result.length()){result=temp;}start--;end++;continue;}else{break;}}}return result;}
}

也是中心扩散法,嗯确定了,manacher方法很精巧,很容易记,但效率真不如中心扩散

6. N 字形变换

将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下:
P   A  H  N
 A P L S I I G
  Y   I  R
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“PAHNAPLSIIGYIR”。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);

示例 1:
输入:s = “PAYPALISHIRING”, numRows = 3
输出:“PAHNAPLSIIGYIR”
示例 2:
输入:s = “PAYPALISHIRING”, numRows = 4
输出:“PINALSIGYAHRPI”
解释:
P I N
A L S I G
Y A H R
P I
示例 3:
输入:s = “A”, numRows = 1
输出:“A”

提示:
1 <= s.length <= 1000
s 由英文字母(小写和大写)、‘,’ 和 ‘.’ 组成
1 <= numRows <= 1000
通过次数531,132提交次数1,019,546

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/zigzag-conversion
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

呦,这个应该不难吧?结果老顾自己琢磨了半天,才弄出第一个版本

class Solution:def convert(self, s: str, numRows: int) -> str:n = len(s)if n <= numRows:return sif numRows==1:return sr = ['' for _ in range(numRows)]x = numRows*2-2for i in range(numRows):r[i] = [s[_] if _%x==i or (_%x>=numRows and numRows-(_%x-numRows+1)-1==i) else '' for _ in range(n)]#for i in r:#    print(''.join(i))return ''.join([''.join(i) for i in r])

其实就是一个折叠位置的取余与原有高度的差问题。。。嗯,这个效率太感人了
leetcode 1~10 学习经历
惨不忍睹啊。。赶紧简化 代码

class Solution:def convert(self, s: str, numRows: int) -> str:n = len(s)if n <= numRows:return sif numRows==1:return sx = numRows*2-2r = ['' for _ in range(numRows)]for i in range(n):r[min(i % x,x-i%x)] += s[i]return ''.join(r)

好像也诶怎么动,就是把按行循环改成按字符循环。。。第一版是按行从字符串里提取应该在该行的字符,第二版是按字符分配到应该去的行。。。。结果效率。。。
leetcode 1~10 学习经历
效率还是不错的。。。问题是才53%??
leetcode 1~10 学习经历
这得抄作业?来个36ms的答案看看!

# 以下内容抄自leetcode第6题36ms答案
class Solution:def convert(self, s: str, numRows: int) -> str:ans = ['']*numRowsflag = -1cnt = 0if numRows<2:return s for ch in s:ans[cnt] +=ch if cnt ==0 or cnt ==numRows-1:flag = flag * -1 cnt += flagreturn ''.join(ans)

额。。。。感觉差不多啊,为什么比不过呢?算了,这个答案分布,基本就差那么几ms,老顾是不懂的了,不跟你们这帮牲口拼了,继续做下一题去了

7. 整数反转

给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [−2^31, 2^31 − 1] ,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。

示例 1:
输入:x = 123
输出:321
示例 2:
输入:x = -123
输出:-321
示例 3:
输入:x = 120
输出:21
示例 4:
输入:x = 0
输出:0

提示:
-231 <= x <= 231 - 1
通过次数1,150,381提交次数3,247,643

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/reverse-integer
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

Hmmmmmmm,我的电脑难道是32位的?

class Solution:def reverse(self, x: int) -> int:s= str(x)f = 1 if s[0] == '-':f = -1s = s[1:]e = int(s[::-1]) * freturn e if e>=-2**31 and e<=2**31-1 else 0

leetcode 1~10 学习经历
额。。。。。。我都作弊了,居然还不是头部10%?
算了,这个题还是按照不作弊的方式自己尝试下吧。

class Solution:def reverse(self, x: int) -> int:y = 0z = 1 if x < 0:z = -1x *= zwhile x > 0:y = y * 10 + x % 10x //= 10y *= zif y > (2**31 - 1) or y < (2**31 * -1):return 0return y        

https://leetcode.cn/submissions/detail/403955924/leetcode 1~10 学习经历
嗯。。。。老顾真的不知道怎么装作不支持64位。。。所以最后的那个比大小估计是有问题的,然后答案估计也很集中在几个时间点上,就不抄答案了这次

8. 字符串转换整数 (atoi)

请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。
函数 myAtoi(string s) 的算法如下:
读入字符串并丢弃无用的前导空格
检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。
读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
将前面步骤读入的这些数字转换为整数(即,“123” -> 123, “0032” -> 32)。如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)。
如果整数数超过 32 位有符号整数范围 [−2^31, 2^31 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −231 的整数应该被固定为 −2^31 ,大于 2^31 − 1 的整数应该被固定为 2^31 − 1 。
返回整数作为最终结果。
注意:
本题中的空白字符只包括空格字符 ’ ’ 。
除前导空格或数字后的其余字符串外,请勿忽略 任何其他字符。

示例 1:
输入:s = “42”
输出:42
解释:加粗的字符串为已经读入的字符,插入符号是当前读取的字符。
第 1 步:“42”(当前没有读入字符,因为没有前导空格)
^
第 2 步:“42”(当前没有读入字符,因为这里不存在 ‘-’ 或者 ‘+’)
^
第 3 步:“42”(读入 “42”)
^
解析得到整数 42 。
由于 “42” 在范围 [-2^31, 2^31 - 1] 内,最终结果为 42 。
示例 2:
输入:s = " -42"
输出:-42
解释:
第 1 步:" -42"(读入前导空格,但忽视掉)
^
第 2 步:" -42"(读入 ‘-’ 字符,所以结果应该是负数)
^
第 3 步:" -42"(读入 “42”)
^
解析得到整数 -42 。
由于 “-42” 在范围 [-2^31, 2^31 - 1] 内,最终结果为 -42 。
示例 3:
输入:s = “4193 with words”
输出:4193
解释:
第 1 步:“4193 with words”(当前没有读入字符,因为没有前导空格)
^
第 2 步:“4193 with words”(当前没有读入字符,因为这里不存在 ‘-’ 或者 ‘+’)
^
第 3 步:“4193 with words”(读入 “4193”;由于下一个字符不是一个数字,所以读入停止)
^
解析得到整数 4193 。
由于 “4193” 在范围 [-2^31, 2^31 - 1] 内,最终结果为 4193 。

提示:
0 <= s.length <= 200
s 由英文字母(大写和小写)、数字(0-9)、’ ‘、’+‘、’-’ 和 ‘.’ 组成
通过次数544,287提交次数2,544,799

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/string-to-integer-atoi
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

嗯,这个题其实非常简单,主要就是,从读入符号看是,后边必须是数字这么一个隐藏条件

class Solution:def myAtoi(self, s: str) -> int:s = s.strip()x = ''f = 1if len(s)==0:return 0if s[0] in '+-':if s[0] == '-':f *= -1s = s[1:]while len(s)>0 and s[0].isnumeric():x += s[0]s = s[1:]e = int(x) if len(x)>0 and x != '-' else 0e *= fif e < 2**31 * -1:e = 2**31 * -1if e >= 2**31:e = 2**31 - 1return e

leetcode 1~10 学习经历
牲口太多了。。。才30%不到的名次
leetcode 1~10 学习经历

竟然还有20ms的答案。。。比不了比不了

9. 回文数

给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
例如,121 是回文,而 123 不是。

示例 1:
输入:x = 121
输出:true
示例 2:
输入:x = -121
输出:false
解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
示例 3:
输入:x = 10
输出:false
解释:从右向左读, 为 01 。因此它不是一个回文数。

提示:
-2^31 <= x <= 2^31 - 1

进阶:你能不将整数转为字符串来解决这个问题吗?
通过次数1,279,736提交次数2,268,913

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/palindrome-number
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution:def isPalindrome(self, x: int) -> bool:return str(x) == str(x)[::-1]

leetcode 1~10 学习经历
你说不转字符串我就不转?

嗯,那就不转吧

class Solution:def isPalindrome(self, x: int) -> bool:if x == 0:return Trueif x < 0 or x % 10 == 0:return Falsey = xz = 0while y > 0:z = z * 10 + y % 10y //= 10if y == z:return Truereturn x == z

leetcode 1~10 学习经历
leetcode 1~10 学习经历
最好成绩52ms,题目评价简单,也就这样了

10. 正则表达式匹配

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘’ 的正则表达式匹配。
‘.’ 匹配任意单个字符
'
’ 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

示例 1:
输入:s = “aa”, p = “a”
输出:false
解释:“a” 无法匹配 “aa” 整个字符串。
示例 2:
输入:s = “aa”, p = “a*”
输出:true
解释:因为 ‘’ 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 ‘a’。因此,字符串 “aa” 可被视为 ‘a’ 重复了一次。
示例 3:
输入:s = “ab”, p = ".
"
输出:true
解释:"." 表示可匹配零个或多个('’)任意字符(‘.’)。

提示:
1 <= s.length <= 20
1 <= p.length <= 30
s 只包含从 a-z 的小写字母。
p 只包含从 a-z 的小写字母,以及字符 . 和 *。
保证每次出现字符 * 时,前面都匹配到有效的字符
通过次数345,735提交次数1,118,182

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/regular-expression-matching
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

老顾自认自己的正则还不错,这个题目就是根据正则来的,不过只要求实现长度*和字符集.
先用正则包来完成下看看情况

import re
class Solution:def isMatch(self, s: str, p: str) -> bool:return True if re.match(p+'$',s) else False

leetcode 1~10 学习经历
我去。。。。这成绩倒数了啊,大佬这么多,都自己实现的正则算法?

嗯,自己写个尝试看看,第一步,整理正则,为什么要整理正则呢?因为很多时候,新手的正则写得很冗余,有效部分其实并不多

# 两个正则片段,完全等价的哦
a*b*.*c* === .*
a*aaa === a{3,}
a*a*a*a*a*a* === a*
a*.*b*.*a*aa*a* === .*a{1,}

这么一整理,需要处理的片段就会少很多了

    def formatRegexPattern(self,p):pattern = []for i in p:if len(pattern) == 0:pattern.append({'c':i,'l':1,'r':1})continueif i == '*':pattern[-1]['r'] = -1pattern[-1]['l'] -= 1while len(pattern) > 1 and pattern[-1]['c'] == '.':isPop = Falseif pattern[-2]['r'] == -1 and pattern[-2]['l'] == 0:pattern.pop(-2)isPop = Trueif not isPop:breakwhile len(pattern) > 1 and pattern[-2]['c'] == '.' and pattern[-2]['r'] == -1:isPop = Falseif pattern[-1]['l'] == 0:# and pattern[-2]['l'] == 0:pattern.pop(-1)isPop = Trueif not isPop:breakwhile len(pattern) > 1 and pattern[-1]['c'] == '.' and pattern[-2]['c'] == '.':pattern[-2]['l'] += pattern[-1]['l']if pattern[-2]['r'] == -1 or pattern[-1]['r'] == -1:pattern[-2]['r'] = -1pattern.pop(-1)continueif i == pattern[-1]['c']:pattern[-1]['l'] += 1pattern[-1]['r'] += 1 if pattern[-1]['r'] > 0 else 0continuepattern.append({'c':i,'l':1,'r':1})return pattern

嗯,弄好了正则合并后,老顾开始琢磨怎么实现正则了,开始写了一大片代码。。。问题是没递归,没调用,纯用循环判断各种情况,最后写不下去了。。。。自己把自己恶心到了

换个思路,正则匹配是按片段进行的,当上一个片段符合,就匹配下一个片段

那么,用递归去匹配当前片段,当前字符串,然后将剩余的片段递归到下一次匹配,传递剩余字符串就好了

再然后,唯一需要注意的就是长度问题了,最后好歹实现出来了,帖个代码先

class Solution:def formatRegexPattern(self,p):pattern = []for i in p:if len(pattern) == 0:pattern.append({'c':i,'l':1,'r':1})continueif i == '*':pattern[-1]['r'] = -1pattern[-1]['l'] -= 1while len(pattern) > 1 and pattern[-1]['c'] == '.':isPop = Falseif pattern[-2]['r'] == -1 and pattern[-2]['l'] == 0:pattern.pop(-2)isPop = Trueif not isPop:breakwhile len(pattern) > 1 and pattern[-2]['c'] == '.' and pattern[-2]['r'] == -1:isPop = Falseif pattern[-1]['l'] == 0:# and pattern[-2]['l'] == 0:pattern.pop(-1)isPop = Trueif not isPop:breakwhile len(pattern) > 1 and pattern[-1]['c'] == '.' and pattern[-2]['c'] == '.':pattern[-2]['l'] += pattern[-1]['l']if pattern[-2]['r'] == -1 or pattern[-1]['r'] == -1:pattern[-2]['r'] = -1pattern.pop(-1)continueif i == pattern[-1]['c']:pattern[-1]['l'] += 1pattern[-1]['r'] += 1 if pattern[-1]['r'] > 0 else 0continuepattern.append({'c':i,'l':1,'r':1})return patterndef IsMatch(self,s,p):if len(s) == 0 and len(p) == 0:return Trueif len(s) == 0 and sum([n['l'] for n in p]) > 0:return Falseif len(s) == 0 and sum([n['l'] for n in p]) == 0:return Trueif len(s) > 0 and len(p) == 0:return Falser = Falsef = p[0]c = f['c']l = f['l']m = f['r']if l > 0:if l > len(s):return Falsev = s[:l]if c != '.' and c * l != v:return Falses = s[l:]if m > l:for i in range(m - l + 1):if c * i == s[:i] or c == '.':r = r or self.IsMatch(s[i:],p[1:])if r:breakelif m == -1:for i in range(len(s) + 1):if c * i == s[:i] or c == '.':r = r or self.IsMatch(s[i:],p[1:])if r:breakelse:r = r or self.IsMatch(s,p[1:])return rdef isMatch(self, s: str, p: str) -> bool:pattern = self.formatRegexPattern(p)return self.IsMatch(s,pattern)

https://leetcode.cn/submissions/detail/404116311/
leetcode 1~10 学习经历
leetcode 1~10 学习经历
呦呵,成绩还不错,差一点就到头部了,一个正则实现琢磨了两天,终于搞定,学习告一段落,下次继续学习