「这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战」
合并两个有序数组
分析
这道题的意思说,将截取nums1的前m位和nums2的前n位合并到num1里,并且要注意的是,nums1的长度刚好等于m+n,那么我们可以对nums1舍弃掉后面n位,并替换成nums的前n位,然后再进行排序。
解法一
由刚才的分析,我们可以很轻松得到解法一
var merge = function(nums1, m, nums2, n) {
for(let i = m ; i < m + n; i++){
nums1[i] = nums2[i-m]
}
nums1.sort((a,b)=>a-b)
};
上述代码中用到了sort排序,进行了两次循环,下面我们用双指针来改写一下吧
解法二
var merge = function(nums1, m, nums2, n) {
let l = 0
let r = 0
let res = []
while(l < m || r < n){
if(l === m){
res.push(nums2[r])
r++
}else if(r === n){
res.push(nums1[l])
l++
}else if(nums1[l] < nums2[r]){
res.push(nums1[l])
l++
}else{
res.push(nums2[r])
r++
}
}
for (let i = 0; i < res.length; i++) {
nums1[i] = res[i]
}
};
这里时间复杂度就比解法一的时间复杂度小多了,这个思路主要是利用双指针,一直做循环,只要l指针还没到m,r指针还没到n,循环就会继续,循环中当l到m时,只能加nums2的数,当r===n时只能加nums1的数,否则就比较大小,小的先进。要注意的是,在有一个进数组后,指针就要后移。
无重复最长子串
解法一
暴力法:
根据题意可得,我们可以计算每个字符的最长子串,最后得出字符串最长子串。
var lengthOfLongestSubstring = function(s) {
let maxLen = 0
for (let i = 0; i < s.length; i++) {
let arr = []
arr.push(s[i])
for (let j = i+1; j < s.length; j++) {
if(arr.includes(s[j])){
break
}
arr.push(s[j])
}
maxLen = Math.max(maxLen,arr.length)
}
return maxLen
};
但是暴力的话,你们懂的。。。两层循环,性能差到没法看
解法二
滑动窗口:
我们可以利用两个指针之间来表示一个子串,也就是一个窗口,这个窗口如果符合我们的需求(也就是不重复子串,判断满不满足需求可以用一个set或者一个数组来判断)那么我们就利用右移右指针来进行扩张,否则我们就对左指针左移来进行收缩,然后记录下最后满足需求的长度,与之前记录的长度进行对比,得出最长长度即可。
var lengthOfLongestSubstring = function(s) {
let left = 0
let right = 0
let set = new Set()
let len = s.length
let res = 0
while(left < len){
while(right < len && !set.has(s[right])){
set.add(s[right])
right++
}
res = Math.max(res,set.size)
set.delete(s[left])
left++
}
return res
};