【700】Leecode solution
001. 两数之和
2022年7月12日
【分析】最简单的想法就是两层遍历,时间复杂度为 O(n2)。为了提高效率因此不能进行两层遍历,第一层的遍历是必须的,针对每一个元素,考虑 target-nums[i] 是否在数组里面。因为最终的结果需要索引值,因此考虑到将 nums 的元素作为 key,索引作为 value 来构建 哈希表(字典),从而可以根据数值获取对应的索引值!
【总结】哈希表的灵活使用很重要,特别是涉及到索引的问题,重要函数 hashmap.get(key),如果找到,则返回对应的值,如果找不到,则返回 None。
002. 两数相加
2022年7月13日
【分析】主要是考察链表,根据已经定义好的链表class来直接用。注意不同链表的不同处理情况!
【总结】链表就是逻辑性很强,但是不难
Python实现链表操作
(1)定义 ListNode
查看代码
class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next
(2)将list转为链表
查看代码
def create_list_node(list1): """ 把list转为链表 """ head = ListNode() # 头结点,设置为空 loop_node = head # 循环结点 for e in list1: # 通过循环构建新的结点,并连接起来 tmp_node = ListNode(e) loop_node.next = tmp_node loop_node = tmp_node return head.next # 最终返回头结点的下一个结点即可
(3)将链表转为list
查看代码
def print_list_node(l1): """ 把链表转为list """ arr = [] while l1: arr.append(l1.val) l1 = l1.next return arr
最终代码:
查看代码
# Definition for singly-linked list. # class ListNode: # def __init__(self, val=0, next=None): # self.val = val # self.next = next class Solution: def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]: # 定义一个头结点 l3 = ListNode() # 定义一个指针 p = l3 # 定义进位值 flag = 0 # 针对不同的情况分别考虑 while l1 != None or l2 != None: if l1 == None: s = l2.val + flag flag = 0 if s > 9: s = s % 10 flag = 1 l2 = l2.next elif l2 == None: s = l1.val + flag flag = 0 if s > 9: s = s % 10 flag = 1 l1 = l1.next else: s = l1.val + l2.val + flag flag = 0 if s > 9: s = s % 10 flag = 1 l1 = l1.next l2 = l2.next tmp_node = ListNode(s) p.next = tmp_node p = p.next if flag == 1: tmp_node = ListNode(1) p.next = tmp_node return l3.next
003. 无重复字符的最长子串
查看代码
class Solution: def lengthOfLongestSubstring(self, s: str) -> int: tmp = "" max_length = 0 for e in s: if e not in tmp: tmp += e else: ind = tmp.find(e) tmp = tmp[(ind+1):] + e if len(tmp) > max_length: max_length = len(tmp) return max_length
004. 寻找两个正序数组的中位数
005. 最长回文子串
-
暴力解法:遍历每一个字符,然后两边扩散
-
动态规划:构建二维数组,参考讲解答案
方法一:暴力解法
查看代码
class Solution: def longestPalindrome(self, s: str) -> str: max_len = 0 max_str = "" for i in range(len(s)): i_r = i for k in range(1, len(s)-i): if s[i+k] != s[i]: i_r = i + k-1 break if k == len(s) - i - 1: i_r = len(s) length = i_r - i + 1 if length > max_len: max_len = length max_str = s[i:i_r+1] for j in range(min(i+1, len(s)-i_r)): if s[i-j] != s[i_r+j]: length = 2*j-2 + i_r - i + 1 if length > max_len: max_len = length max_str = s[i-j+1:i_r+j] break if j == min(i+1, len(s)-i_r) - 1: length = 2*j + i_r - i + 1 if length > max_len: max_len = length max_str = s[i-j:i_r+j+1] return max_str
方法二:动态规划
查看代码
class Solution: def longestPalindrome(self, s: str) -> str: if len(s) == 0: return "" dp = [[False] * len(s) for i in range(len(s))] for i in range(len(s)): dp[i][i] = True max_len = 1 max_str = s[0] for j in range(1, len(s)): for i in range(j): if s[i] == s[j] and (j-i<3 or dp[i+1][j-1]): dp[i][j] = True if j - i + 1 > max_len: max_len = j - i max_str = s[i:j+1] return max_str
006. Z 字形变换
- 分别考虑两种情况,一种是一列上面都是满的,一种情况就是一列只有一个元素
查看代码
class Solution: def convert(self, s: str, numRows: int) -> str: if numRows == 1: return s arr = [[""] * len(s) for i in range(numRows)] ind = 0 # 需要注意的是,二维数组是[row][column]形式的,所以赋值的时候 # 注意是arr[j][i],不要弄反了! for i in range(len(s)): if ind == len(s): break # 能整除的列,全部遍历显示 if i % (numRows - 1) == 0: for j in range(numRows): if ind == len(s): break arr[j][i] = s[ind] ind += 1 if ind == len(s): break # 不能整除的列,只显示一个位置,通过归纳找到对应的索引值 if i % (numRows - 1) != 0: if ind == len(s): break ind_j = numRows - 1 - i % (numRows - 1) arr[ind_j][i] = s[ind] ind += 1 if ind == len(s): break return ''.join([''.join(arr[i]) for i in range(numRows)])
007. 整数反转
-
可以直接通过字符串反转来实现
-
可以通过十进制的规律来获取每一位的数字,再反向组成数字
方法一:
查看代码
class Solution: def reverse(self, x: int) -> int: if x==0: return 0 tmp = (x//abs(x)) * int(str(abs(x))[::-1]) if tmp < -2**31 or tmp > 2**31-1: return 0 return tmp
方法二:
查看代码
class Solution: def reverse(self, x: int) -> int: if x==0: return 0 if x > 0: x_tmp = x if x < 0: x_tmp = -1 * x num_arr = [] while x_tmp > 0: num_arr.append(x_tmp % 10) x_tmp = x_tmp // 10 num = 0 carry = 1 for i in range(len(num_arr)-1, -1, -1): num += num_arr[i] * carry carry *= 10 if x < 0: num = -1 * num if num < -2**31 or num > 2**31-1: return 0 return num
008. 字符串转换整数 (atoi)
-
主要考虑规则
-
首先去掉前面空格
-
连续的可以作为数字才考虑
-
"+-200-+300" 返回 0
-
代码中使用了try...except...
来完成报错情况的结果输出,整体的代码就是一边调试一边修改,因为对具体的规则不了解!
查看代码
class Solution: def myAtoi(self, s: str) -> int: s = s.strip() if s=="": return 0 ref = ["+", "-", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"] if s[0] not in ref: return 0 s_cut = "" for i in range(len(s)): if s[i] not in ref: s_cut = s[:i] break if i == len(s)-1: s_cut = s flag = 0 for i in range(len(s_cut)): if s_cut[i] not in ["+", "-"]: flag = 1 if flag and s_cut[i] in ["+", "-"]: s_cut = s_cut[:i] break try: res = int(s_cut) except: return 0 if int(s_cut) < -1 * 2 ** 31: return -1 * 2 ** 31 if int(s_cut) > 2 ** 31 - 1: return 2 ** 31 - 1 return int(s_cut)
011. 盛最多水的容器
- 可以通过动态规划的思想来解答,但是会超时,动态规划时间复杂度过高
-
通过设置
left
和right
两个指针,然后根据情况进行左右移动,效率更高
查看代码
class Solution: def maxArea(self, height: List[int]) -> int: # 时间复杂度过大,无法通过 #dp = [0] * (len(height) + 1) #dp[2] = min(height) #for i in range(3, len(height) + 1): # dp[i] = max(dp[i-1], max([(i-1-j)*min(height[j], height[i-1]) for j in range(i-1)])) #return dp[-1] # 下面为双指针方法 left = 0 right = len(height) - 1 maxA = 0 while left < right: tmp = (right - left) * min(height[left], height[right]) if maxA < tmp: maxA = tmp if height[left] < height[right]: left += 1 else: right -= 1 return maxA
012. 整数转罗马数字
- 利用穷举的方法来实现!
查看代码
class Solution: def intToRoman(self, num: int) -> str: res = "" if num // 3000 > 0: num %= 3000 res += "MMM" if num // 2000 > 0: num %= 2000 res += "MM" if num // 1000 > 0: num %= 1000 res += "M" if num // 900 > 0: num %= 900 res += "CM" if num // 500 > 0: num %= 500 res += "D" if num // 400 > 0: num %= 400 res += "CD" if num // 300 > 0: num %= 300 res += "CCC" if num // 200 > 0: num %= 200 res += "CC" if num // 100 > 0: num %= 100 res += "C" if num // 90 > 0: num %= 90 res += "XC" if num // 50 > 0: num %= 50 res += "L" if num // 40 > 0: num %= 40 res += "XL" if num // 30 > 0: num %= 30 res += "XXX" if num // 20 > 0: num %= 20 res += "XX" if num // 10 > 0: num %= 10 res += "X" if num // 9 > 0: num %= 9 res += "IX" if num // 5 > 0: num %= 5 res += "V" if num // 4 > 0: num %= 4 res += "IV" if num // 3 > 0: num %= 3 res += "III" if num // 2 > 0: num %= 2 res += "II" if num // 1 > 0: num %= 1 res += "I" return res
【分析】最
【总结】哈
15. 三数之和
可以通过双指针的方式来降低时间复杂度!
查看代码
class Solution: def threeSum( self , nums: List [ int ]) - > List [ List [ int ]]: arr = [] length = len (nums) nums.sort() for i in range (length - 2 ): if nums[i] > 0 : break if i > 0 and nums[i] = = nums[i - 1 ]: continue left = i + 1 right = length - 1 while left < right: s = nums[i] + nums[left] + nums[right] if s = = 0 : arr.append([nums[i], nums[left], nums[right]]) left + = 1 right - = 1 while (left < right and nums[left] = = nums[left - 1 ]): left + = 1 while (left < right and nums[right] = = nums[right + 1 ]): right - = 1 elif s < 0 : left + = 1 while (left < right and nums[left] = = nums[left - 1 ]): left + = 1 else : right - = 1 while (left < right and nums[right] = = nums[right + 1 ]): right - = 1 return arr
016. 最接近的三数之和
可以通过双指针的方式来降低时间复杂度!
查看代码
class Solution: def threeSumClosest( self , nums: List [ int ], target: int ) - > int : nums.sort() res = nums[ 0 ] + nums[ 1 ] + nums[ - 1 ] gap = abs (res - target) for i in range ( len (nums) - 2 ): if nums[i] > 0 and nums[i] > target: break left = i + 1 right = len (nums) - 1 while (left < right): s = nums[i] + nums[left] + nums[right] if s = = target: return target elif s < target: if target - s < gap: gap = target - s res = s left + = 1 else : if s - target < gap: gap = s - target res = s right - = 1 return res
017. 电话号码的字母组合
使用动态规划的方法来解决!
查看代码
class Solution: def letterCombinations( self , digits: str ) - > List [ str ]: if not digits: return [] hashmap = { "2" : "abc" , "3" : "def" , "4" : "ghi" , "5" : "jkl" , "6" : "mno" , "7" : "pqrs" , "8" : "tuv" , "9" : "wxyz" } dp = [[] for i in range ( len (digits) + 1 )] dp[ 1 ] = [e for e in hashmap[digits[ 0 ]]] for i in range ( 2 , len (digits) + 1 ): arr = [] for e1 in dp[i - 1 ]: for e2 in hashmap[digits[i - 1 ]]: arr.append(e1 + e2) dp[i] = arr return dp[ - 1 ]
18. 四数之和
双指针的方法!
367. 有效的完全平方数
解决方案:对于已经排好序的遍历问题,可以优先考虑二分法!
查看代码
class Solution: def isPerfectSquare(self, num: int) -> bool: if num == 1: return True #for i in range(num//2+1): # if i * i == num: # return True # elif i * i > num: # return False #return False left = 1 right = num//2 + 1 while (left <= right): mid = (left + right) // 2 if mid * mid == num: return True if mid * mid < num: left = mid + 1 else: right = mid - 1 return False
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
2021-05-13 【559】R学习笔记
2021-05-13 【558】LaTeX 写论文
2012-05-13 【042】Madagascar