Loading web-font TeX/Math/Italic

alex_bn_lee

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

【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. 盛最多水的容器

  • 可以通过动态规划的思想来解答,但是会超时,动态规划时间复杂度过高
  • 通过设置leftright两个指针,然后根据情况进行左右移动,效率更高

查看代码
 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()
forin range (length - 2 ):
if nums[i] >  0break
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

 

posted on   McDelfino  阅读(28)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
历史上的今天:
2021-05-13 【559】R学习笔记
2021-05-13 【558】LaTeX 写论文
2012-05-13 【042】Madagascar
点击右上角即可分享
微信分享提示