给你一个字符串 s
,找到 s
中最长的回文子串。
示例 1:
输入:s = "babad" 输出:"bab" 解释:"aba" 同样是符合题意的答案。
class Solution:
def longestPalindrome(self, s: str) -> str:
def isHuiWenStr(subStr:str):#判断当前子串是不是回文字符
start = 0
end = len(subStr) - 1
while(start < end):
if(subStr[start] != subStr[end]):
return False
start = start + 1
end = end - 1
return True
if(len(s) < 2):
return s
maxLen = 1#记录最大回文字符长度
begin = 0#记录最大回文字符的起点
for i in range(len(s)-1):
for j in range(i + 1, len(s)):
if((j - i + 1) > maxLen and isHuiWenStr(s[i:j+1])):
maxLen = j - i + 1
begin = i
return s[begin:begin + maxLen]
class Solution(object):
def longestCommonSubsequence(self, text1, text2):
M, N = len(text1), len(text2)
dp = [[0] * (N + 1) for _ in range(M + 1)]
for i in range(1, M + 1):
for j in range(1, N + 1):
if text1[i - 1] == text2[j - 1]:
dp[i][j] = dp[i - 1][j - 1] + 1
else:
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
return dp[M][N]
# Dynamic programming.
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
if not nums: return 0
dp = [1] * len(nums)
for i in range(len(nums)):
for j in range(i):
if nums[j] < nums[i]: # 如果要求非严格递增,将此行 '<' 改为 '<=' 即可。
dp[i] = max(dp[i], dp[j] + 1)
return max(dp)
最长递增子序列II:
class Solution:
def lengthOfLIS(self, nums: List[int], k: int) -> int:
n=len(nums)
e=max(nums)
lst=[0]*(4*e)
def query(l,r,s,t,p):
if l<=s and r>=t:
return lst[p]
mid=(s+t)//2
cmax=0
if l<=mid:
cmax=max(cmax,query(l,r,s,mid,2*p))
if r>mid:
cmax=max(cmax,query(l,r,mid+1,t,2*p+1))
return cmax
def update(key,val,l,r,p):
if l==r and l==key:
lst[p]=max(lst[p],val)
return
if l<=key and r>=key:
lst[p]=max(lst[p],val)
mid=(l+r)//2
if key<=mid:
update(key,val,l,mid,2*p)
else:
update(key,val,mid+1,r,2*p+1)
ans=1
update(nums[0],1,0,e,1)
for i in range(1,n):
cur=nums[i]
t=query(cur-k,cur-1,0,e,1)
ans=max(ans,t+1)
update(cur,t+1,0,e,1)
return ans
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
n = len(nums)
dic = {}
for i in range(n):
if nums[i] not in dic:
dic[nums[i]] = 1
else:
dic[nums[i]] += 1
res = []
while k > 0:
tmp = 0
for num in dic:
if dic[num] > tmp:
tmp = dic[num]
cur = num
dic[cur] = -1
res.append(cur)
k -= 1
return res
给你两个按 非递减顺序 排列的整数数组 nums1
和 nums2
,另有两个整数 m
和 n
,分别表示 nums1
和 nums2
中的元素数目。请你 合并 nums2
到 nums1
中,使合并后的数组同样按 非递减顺序 排列。
算法思路:
采用归并排序的思想,将每次num1和num2较大的值归并入num1末端(递增排序),如果num1里的元素先归并完了,就直接将num2剩余元素直接放入num1(num1和num2都递增)
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
while(m > 0 and n >0):
if(nums1[m-1] > nums2[n-1]):
nums1[m+n-1] = nums1[m-1]
m -= 1
else:
nums1[m+n-1] = nums2[n-1]
n -= 1
if(n > 0):#num1先归并完了,将num2剩余元素直接放入num1
nums1[:n] = nums2[:n]
6. 买卖股票最佳时机III
class Solution:
def maxProfit(self, prices: List[int]) -> int:
n = len(prices)
buy1 = buy2 = -prices[0]
sell1 = sell2 = 0
for i in range(1, n):
buy1 = max(buy1, -prices[i])
sell1 = max(sell1, buy1 + prices[i])
buy2 = max(buy2, sell1 - prices[i])
sell2 = max(sell2, buy2 + prices[i])
return sell2
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeNthFromEnd(self, head, n):
left = right = head
count = 0
while count < n:
right = right.next
count += 1
if not right:
return head.next
while right.next:
left = left.next
right = right.next
left.next = left.next.next
return head
class Solution:
def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
for row in matrix:
for element in row:
if element == target:
return True
return False
class Solution:
def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
i, j = len(matrix) - 1, 0
while i >= 0 and j < len(matrix[0]):
if matrix[i][j] > target: i -= 1
elif matrix[i][j] < target: j += 1
else: return True
return False
9. 括号匹配
class Solution:
def isValid(self, s: str) -> bool:
dic = {')':'(',']':'[','}':'{'}
stack = []
for i in s:
if stack and i in dic:
if stack[-1] == dic[i]: stack.pop()
else: return False
else: stack.append(i)
return not stack
class Solution:
def checkValidString(self, s: str) -> bool:
def help(a):
cnt = 0
for c in s if a == 1 else reversed(s):
if c == '(': cnt += a
if c == ')': cnt += -a
if c == '*': cnt += 1
if cnt < 0:
return False
return True
return help(1) and help(-1)
class Solution:
def majorityElement(self, nums: List[int]) -> int:
votes = 0
for num in nums:
if votes == 0: x = num
votes += 1 if num == x else -1
return x
(1)饿汉式单例:(立即加载)
// 饿汉式单例
public class Singleton1 {
// 指向自己实例的私有静态引用,主动创建
private static Singleton1 singleton1 = new Singleton1();
// 私有的构造方法
private Singleton1(){}
// 以自己实例为返回值的静态的公有方法,静态工厂方法
public static Singleton1 getSingleton1(){
return singleton1;
}
}
(2)懒汉式单例:(延迟加载)
// 懒汉式单例
public class Singleton2 {
// 指向自己实例的私有静态引用
private static Singleton2 singleton2;
// 私有的构造方法
private Singleton2(){}
// 以自己实例为返回值的静态的公有方法,静态工厂方法
public static Singleton2 getSingleton2(){
// 被动创建,在真正需要使用时才去创建
if (singleton2 == null) {
singleton2 = new Singleton2();
}
return singleton2;
}
}
class Solution:
def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
if not root: return []
res, queue = [], collections.deque()
queue.append(root)
while queue:
tmp = []
for _ in range(len(queue)):
node = queue.popleft()
tmp.append(node.val)
if node.left: queue.append(node.left)
if node.right: queue.append(node.right)
res.append(tmp)
return res
class Solution:
def isStraight(self, nums: List[int]) -> bool:
repeat = set()
ma, mi = 0, 14
for num in nums:
if num == 0: continue # 跳过大小王
ma = max(ma, num) # 最大牌
mi = min(mi, num) # 最小牌
if num in repeat: return False # 若有重复,提前返回 false
repeat.add(num) # 添加牌至 Set
return ma - mi < 5 # 最大牌 - 最小牌 < 5 则可构成顺子
def find_kth_largest_index(nums, k):
sorted_nums = sorted(range(len(nums)), key=lambda x: nums[x], reverse=True)
return sorted_nums[k-1]
关于测试用例的设计,你可以考虑以下几种情况:
关于代码的问题,上述代码的问题在于使用了sorted
函数对数组进行排序,它的时间复杂度为O(nlogn)。如果数组很大,可能会影响性能。可以使用快速选择算法来优化时间复杂度。
快速选择算法的时间复杂度为O(n),它的实现方式类似于快速排序。你可以通过将数组分成两部分来确定第k个大的数所在的位置,从而减少排序的时间复杂度。
SELECT name FROM abc ORDER BY score DESC LIMIT 1 OFFSET 1;
(1)SpringApplication: 是启动Spring Boot应用的起始点。当运行 SpringApplication.run 方法时,它会执行以下操作:
推断应用类型(是否是Web应用)。
设置默认属性。
加载所有的 Spring 配置属性。
配置日志。
创建并返回一个 Spring 的 ApplicationContext 实例。
(2)SpringFactoriesLoader: 这个类用于从 classpath 下的 META-INF/spring.factories 文件中加载配置。这是 Spring Boot 扩展自动配置、提供其他 Spring Boot 初始器的主要机制。
(3)@SpringBootApplication: 这个注解实际上是一个组合注解,它组合了以下三个注解:
@SpringBootConfiguration: 表明该类是配置类。
@EnableAutoConfiguration: 启用 Spring Boot 的自动配置。
@ComponentScan: 启用组件扫描。
(4)AutoConfigurationImportSelector: 这个类读取 META-INF/spring.factories 中配置的所有自动配置类,并基于条件评估决定哪些自动配置需要被激活。
(5)ApplicationContext:Spring的上下文对象,所有的Bean都是在这里被管理。
Spring Boot在启动过程中创建了特定类型的ApplicationContext(基于应用类型,例如Web应用会创建AnnotationConfigServletWebServerApplicationContext)。
(6)内嵌 Servlet 容器:如 Tomcat、Jetty 或 Undertow。
Spring Boot 的一个特点是它可以打包为一个独立的JAR,这个JAR包含了一个内嵌的Servlet容器。所以,当应用启动时,这个内嵌的容器也会被启动。
执行顺序简述:
主类(通常带有 public static void main 方法)调用 SpringApplication.run。
创建 SpringApplication 对象。
应用 SpringFactoriesLoader 加载 META-INF/spring.factories 中的配置。
初始化 ApplicationContext。
调用 @EnableAutoConfiguration 加载自动配置。
初始化内嵌的 Servlet 容器。
启动容器并开始监听请求。
(1)白盒测试(White Box Testing)
定义:白盒测试,又称为结构测试、逻辑驱动测试或代码级测试,它是基于程序代码的结构或算法来设计测试用例的。
测试内容:
工具:可能会使用代码覆盖工具来检查代码的哪些部分被测试,哪些部分没有。
优点:
缺点:
(2) 黑盒测试(Black Box Testing)
定义:黑盒测试,又称功能测试,主要关注程序功能,而不考虑其内部结构或工作原理。测试是基于输入和预期输出。
测试内容:
工具:可能会使用自动测试工具,如 Selenium 或 QTP,来模拟用户操作并检查结果。
优点:
缺点:
(1)HTTP与HTTPS的区别
安全性:
端口:
性能:
证书:
(2) HTTP请求结构
一个HTTP请求主要包含以下部分:
(3) 请求头的作用
请求头在HTTP请求中扮演了重要的角色,它为服务器提供了关于客户端请求的一些信息。以下是请求头的一些常见用途:
Content-Type
头部,客户端可以告诉服务器发送的数据是什么格式,如application/json
或text/html
。Content-Length
头部,指示请求或响应体的大小。Authorization
头部用于包含凭据,通常用于API认证。Cache-Control
和其他相关的头部可以控制如何缓存响应内容。User-Agent
头部描述了发出请求的客户端类型,如浏览器或其他客户端应用。Accept
头部,客户端可以告诉服务器它希望收到哪种类型的响应。Cookie
头部可以包含服务器设置的任何cookie,它们在每个请求中发送回服务器。Origin
头部表示请求来自哪个源,与CORS(跨来源资源共享)策略相关。(1) TCP与UDP的区别
连接的性质:
可靠性:
数据的边界性:
速度:
用途:
(2)TCP三次握手为什么是三次握手而不是两次?
三次握手是TCP协议建立连接的过程,具体步骤如下:
三次握手原因:
防止已失效的连接请求报文段突然传到了服务端:考虑一个场景,客户端发送了第一个连接请求,但是由于网络原因这个请求被延迟了,于是TCP又发送了一个连接请求。当网络好转时,两个连接请求几乎同时到达服务端,如果此时是两次握手,服务端就会建立两个连接,但客户端只建立了一个连接,这就造成了服务端资源的浪费。
更为可靠地确认双方的接收与发送能力:三次握手可以确保双方都有接收和发送消息的能力。两次握手无法保证这一点。
设定序列号:三次握手还可以使得双方都能为TCP连接初始的序列号达成一致
地址解析:
建立TCP连接:
发送HTTP请求:
服务器处理请求并返回HTTP响应:
浏览器解析并渲染页面:
加载嵌套的资源:
执行JavaScript:
关闭连接:
AVG、COUNT、MAX、MIN、SUM
锁定:
原子操作:
compare-and-swap
。隔离级别:
序列化访问:
分布式锁:
冲突检测与回滚:
事务:
锁定策略:
死锁检测与预防:
优化查询:
乐观并发控制:
减少事务持续时间:
隔离级别:
READ COMMITTED
和SERIALIZABLE
在锁定策略上有很大的不同。分区:
(1)JVM内存模型
JVM内存大致可以划分为以下几个部分:
(2) 垃圾回收机制
主要回收对象存放的主内存区域:堆和方法区。主要算法:
(3) 进入老年代的阈值
对象从新生代进入老年代通常是基于它们的年龄。如果对象在新生代中经过了特定次数的GC后仍然存活,它就会被移至老年代。这个“特定次数”就是阈值,通常可通过参数-XX:MaxTenuringThreshold
来设置。
(4) JVM可调整的参数
JVM有许多可调整的参数。以下是一些常用的参数:
-Xms
:设置初始堆大小。-Xmx
:设置最大堆大小。-XX:NewRatio
:设置新生代与老年代的大小比例。-XX:SurvivorRatio
-XX:MaxTenuringThreshold
:设置对象进入老年代的年龄阈值。-XX:+UseSerialGC
:选择串行回收器。-XX:+UseParallelGC
:选择并行回收器。-XX:+UseConcMarkSweepGC
:选择CMS回收器。-XX:+UseG1GC
:选择G1回收器。Java的垃圾收集器有多种,每种都有其特定的应用场景和优势。以下是常见的垃圾收集器及其工作方式:
-XX:+UseSerialGC
-XX:+UseParallelGC
-XX:+UseConcMarkSweepGC
(1)数据完整性测试:
确保原始大表中的所有数据都出现在某个小表中。确保数据没有重复,也就是说,
一个数据行不应该出现在多个小表中。确保所有的约束和关系(如外键)都仍然成立。
(2)查询测试:
如果你对原始大表有预定义的查询,确保它们在小表上也能正确运行。
为了验证性能提升,对相同的查询进行基准测试,比较分片前后的执行时间。
(3)写入测试:
确保新数据可以正确地写入适当的小表。测试批量写入的性能,确保它符合或超过你的性能要求。
(4)故障恢复测试:
尝试模拟小表的故障并恢复,确保没有数据丢失。确保备份和恢复策略仍然有效。
(5)并发性测试:
用多个并发用户或进程测试小表,确保系统仍然稳定和响应。检查是否有任何的锁定或并发性问题。
(6) 应用集成测试:
如果你有依赖原始大表的应用程序,确保它们能够正确地与小表集成,并且所有的功能都正常工作。
(7)负载测试:
根据预期的工作负荷进行负载测试,确保系统的性能满足要求。监控系统资源使用情况,如CPU、内存和磁盘。
(8) 迁移测试:
如果你计划在生产环境中迁移到这些小表,考虑执行迁移测试,模拟真实的迁移过程。
(9) 验证工具:
使用数据库验证工具,检查数据的一致性和完整性。
(10) 安全性测试:
确保所有的小表都与原始大表具有相同的安全性标准和策略。
执行安全性测试以确保数据在分片后仍然安全。
(1)基本功能测试:
添加商品到购物车:单个商品、多个商品、不同种类的商品。
从购物车中删除商品。
更改购物车中商品的数量。
选择/取消选择购物车中的商品。
(2) UI/UX测试:
购物车界面在不同设备和浏览器中的显示。
响应性测试,确保在移动设备上也有良好的体验。
购物车的加载速度。
(3) 数据一致性测试:
购物车显示的价格与商品页面显示的价格是否一致。
库存检查:当库存不足时,购物车应该有相应的提示。
(4) 购物车更新测试:
当商品价格或属性(如颜色、尺寸等)发生变化时,购物车中的商品信息是否会更新。
(5) 并发性测试:
多个用户同时操作购物车时的表现,如同时添加、删除商品。
(6) 持久性测试:
退出并重新登录后,购物车的商品是否仍然存在。
在不同设备和浏览器上登录,购物车的内容是否一致。
(7) 集成测试:
购物车与其他模块(如支付、优惠券、积分系统等)的集成。
购物车到结账流程的完整性测试。
(8) 安全性和隐私测试:
确保未登录或其他用户无法访问用户的购物车。
确保所有数据传输,特别是结账时,都是加密的。
(9) 异常和边界测试:
尝试添加库存超出的商品数量到购物车。
尝试在购物车中加入已下架的商品。
当购物车为空时的界面和提示。
(10) 性能测试:
加载含有大量商品的购物车时的性能。
(11)通知和提示测试
当商品缺货或价格变化时,用户是否会收到相应的通知。
购物车中的操作(如删除商品)是否有相应的确认提示。
(1) UI/UX测试:
检查所有元素(如文本框、标签、按钮、链接)是否正确显示。
确保错误提示清晰、友好并易于理解。
确保所有文本框、按钮、链接等都可点击且反应正常。
检查页面是否在各种屏幕尺寸和分辨率下响应正常。
(2) 功能测试:
使用有效的用户名和密码登录。
使用无效的用户名和密码登录。
使用有效的用户名和无效的密码登录。
使用无效的用户名和有效的密码登录。
使用空用户名和密码尝试登录。
确保“忘记密码”功能或链接可用。
(3) 输入验证测试:
在用户名/密码字段中输入特殊字符、空格等,检查应用的响应。
输入超长或超短的用户名和密码。
输入SQL注入、脚本注入等攻击向量,检查应用的响应。
(4)错误处理测试:
检查当提供错误的凭据时是否显示了合适的错误消息。
在多次尝试错误的登录凭据后,检查是否有锁定策略或验证码要求。
(5) 会话和安全性测试:
登录后,直接访问登录页面,确保应用将用户重定向到主页面或显示已登录状态。
登录后关闭浏览器或标签,再次打开,确保用户仍然登录。
登录后,修改URL地址到其他页面,然后再返回,确保用户仍然登录。
使用HTTP(非HTTPS)登录,确保密码不是明文传输。
检查cookies和session的安全设置,如httpOnly、secure等。
(6) 多用户类型登录测试(如果适用):
尝试使用不同类型的用户(如管理员、普通用户、访客)登录,并确保他们被正确地重定向到他们的主页面。
(7) 浏览器兼容性测试:
在不同的浏览器和版本中测试登录页面。
(8) 性能测试:
模拟多用户同时登录,检查页面加载速度和服务器响应时间。
(9) 重置密码和验证码功能测试(如果适用):
尝试使用“忘记密码”功能重置密码。
在被要求时正确和错误地输入验证码。
(10) 多语言和多地区测试(如果适用):
切换不同的语言或地区,确保登录页面的内容和错误消息正确地翻译
(1) 功能性测试:
从相册选择图片并成功发送。
使用相机拍摄新照片并成功发送。
选择并发送多张图片。
图片发送进度条显示并在发送完毕后消失。
在发送图片的过程中,能够成功取消发送。
(2) 文件大小和格式测试:
尝试发送大于微信允许的最大文件大小的图片。
尝试发送不同格式的图片文件(如JPG、PNG、GIF、BMP等)。
尝试发送损坏或不完整的图片文件。
(3) UI/UX测试:
在不同屏幕尺寸的设备上检查图片的显示效果。
长按已发送的图片,确保弹出菜单(如转发、保存、删除等)正常工作。
检查点击图片后的放大、缩小、左右滑动等查看功能。
(4) 网络和性能测试:
在不同的网络环境(如4G、5G、WiFi、慢速网络)下发送图片,确保发送速度和稳定性。
在网络信号不稳定或断开的情况下尝试发送图片。
(5) 安全性和隐私测试:
确保未授权的应用或用户无法访问发送的图片。
检查图片存储和传输是否有加密。
(6) 错误处理测试:
当发送大量或超大文件时,检查是否有合适的错误消息。
当磁盘空间不足时,尝试发送图片并检查是否有相应的提示。
(7) 集成测试:
发送图片后,尝试使用其他功能,如语音、视频、红包等,确保它们不受影响。
在聊天界面外,如朋友圈、微信群等,尝试发送图片。
(8) 其他测试:
旋转设备并在横屏模式下发送图片。
在应用后台运行时发送图片。
修改设备的系统日期和时间,然后尝试发送图片。
(9) 互通性测试:
从不同版本的微信发送图片,并确保接收方可以正确显示。
(10) 多语言和地区测试(如果适用):
在不同的语言设置下尝试发送图片,确保所有的提示、错误消息等都被正确翻译。
(1) 前端性能监控工具:
使用前端性能监控工具,例如Google Chrome的内置开发者工具,可以提供详细的页面加载时间报告。
如何操作:
打开Chrome开发者工具(F12或右键页面选择“检查”)。
转到“网络”或“Performance”选项卡。
清空缓存并刷新页面或模拟点击操作。
你可以看到页面的详细加载时间线,并准确知道何时页面开始加载、何时DOM完成、何时所有资源(如图片、JS、CSS等)都被下载和执行完毕。
(2) 使用第三方性能监控服务:
有许多第三方服务,如New Relic, LogRocket, FullStory等,提供页面性能监控功能。
这些工具可以为你提供页面的加载和渲染时间,同时还提供其他有关页面性能的详细信息
(3)服务器日志:
尽管大部分的页面渲染时间发生在客户端,但你还可以检查服务器日志以确定服务器响应的时间。
这有助于分析页面加载时间中哪一部分是由服务器引起的
总时间为:7+1+1=9分钟。
答:相同。设盐和a糖最初为x 取走一勺y 而后盐中有x+y 最后盐中含糖y-y*y/(x+y) 糖中含盐y*x/(x+y) 两式相等