巩固练习移除元素-26/283/844/977
26.删除有序数组中的重复项
解题思路
完全和27类似,只是条件略微变动。
重点就是前后两项不重复。
出现的问题
var removeDuplicates = function(nums) {
let fast=0,slow=0
while(fast < nums.length){
if(nums[fast] != nums[fast-1]){ //如果后项==前项,则意味着重复
nums[slow] = nums[fast]
slow++
}
fast++
}
return slow
};
上面我自己写的。虽然尝试了下,可以通过所有的解,但我还是对fast-1
有点介意,所以去看了答案。
果然,答案是改成另一个加一的。
主要是两个指针,一左一右,一个不动用来当flag与之对比,另一个去找新的的数去和flag比。
最后输出的时候因为数组的index和长度会相差1,所以要flag所对应的index+1输出。
JavaScript解法代码
用while写法的
var removeDuplicates = function(nums) {
let left=0,right=1
while(right < nums.length){
if(nums[right] != nums[left]){ //如果后项==前项,则意味着重复
nums[++left] = nums[right]
}
right++
}
return left+1
};
用for循环的
var removeDuplicates = function(nums) {
let left=0,right=1
for(let right = 1; right < nums.length; slow++){
if(nums[right] != nums[left]){ //如果后项==前项,则意味着重复
nums[++left] = nums[right]
}
}
return left+1
};
Python解法代码
class Solution(object):
def removeDuplicates(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
left = 0
right = 1
while(right < len(nums)):
if(nums[left]!= nums[right]):
left += 1
nums[left] = nums[right]
right += 1
return left+1
283.移动零
解题思路
就是交换,把非零的放到前面,零的放到后面。
(全部我自己做出来的!)(开心!😄)
JavaScript解法代码
var moveZeroes = function(nums) {
let left = 0
for(let right = 1; right<nums.length;right++){
if(nums[left]==0 && left == 0){
nums[left] = nums[right]
nums[right] = 0
}
if(nums[right] != 0){
temp = nums[++left]
nums[left]=nums[right]
nums[right] = temp
}
}
return nums
};
Python解法代码
class Solution(object):
def moveZeroes(self, nums):
"""
:type nums: List[int]
:rtype: None Do not return anything, modify nums in-place instead.
"""
left = 0
right = 1
while(right<len(nums)):
if(nums[left]==0 and left == 0):
nums[left] = nums[right]
nums[right] = 0
if(nums[right] != 0):
left += 1
temp = nums[left]
nums[left]=nums[right]
nums[right] = temp
right += 1
return nums
844.比较含退格的字符串
解题思路
如果可以开新数组的话很简单。
var backspaceCompare = function(s, t) {
let snew = [],tnew = []
for(let i=0;i<s.length;i++){
if(s[i]!='#'){
snew.push(s[i])
}
else{
snew.pop()
}
}
for(let i=0;i<t.length;i++){
if(t[i]!="#"){
tnew.push(t[i])
}
else{
tnew.pop()
}
}
if(snew.toString() == tnew.toString()){
return true
}
else{
return false
}
};
但如果不开辟新数组空间,用 O(n) 的时间复杂度和 O(1) 的空间复杂度解决该问题,那就是双指针。
出现的问题
按之前的双指针是不行的,因为退格。
采取快慢指针初始值差1,还是不行。
想过倒着来比较,不太行,删掉的只是#。
看了视频 b站844题讲解恍然大悟!
我之前一直在想原地处理完数组再去比较,但这个视频的解法是从后往前一边处理一边比较!牛蛙!
JavaScript解法代码
var backspaceCompare = function(s, t) {
let sflag = s.length - 1
let tflag = t.length - 1
let sind = 0, tind = 0
while(sflag >= 0 || tflag >= 0 ){
while(sflag >= 0){
if(s[sflag] == '#'){
sflag--
sind++
}
else if(sind != 0){
sflag--
sind--
}
else{
break
}
}
while(tflag >= 0){
if(t[tflag] == '#'){
tflag--
tind++
}
else if(tind != 0){
tflag--
tind--
}
else{
break
}
}
if(s[sflag] != t[tflag]){
return false
}
if((sflag<0 && tflag>=0) || (sflag>=0 && tflag<0)){
return false
}
sflag--
tflag--
}
return true
};
Python解法代码
python用上面的写法会超时,先放一下
class Solution(object):
def backspaceCompare(self, s, t):
"""
:type s: str
:type t: str
:rtype: bool
"""
sflag = 0
tflag = 0
si = len(s) - 1
tj = len(t) - 1
while(si >= 0 or tj >= 0):
#在s时,si指针有三种情况
while(si >= 0):
if(s[si] == '#'): #指到#
si-=1
sflag+=1
elif(sflag != 0): #指到#的下一个,即要删掉的字符
si-=1
sflag-=1
else: #指到正常须保留的字符, break去和t的须保留的字符进行比较
break
#t同理
while(tj >= 0):
if(t[tj] == '#'): #指到#
tj-=1
tflag+=1
elif(tflag != 0): #指到#的下一个,即要删掉的字符
tj-=1
tflag-=1
else: #指到正常须保留的字符, break去和t的须保留的字符进行比较
break
#判断
if(s[si] != t[tj]):
return False
if((si<0 and tj>=0) or (si>=0 and tj<0)):
return False
si-=1
tj-=1
return True
看了别人的答案,思路完全一样。但是他重复的代码包装了一下,就不会超时了。(俺也不知道为啥)
class Solution(object):
def backspaceCompare(self, s, t):
"""
:type s: str
:type t: str
:rtype: bool
"""
# match s, t one char by one from right to left
i, j = len(s) - 1, len(t) - 1
while i >= 0 or j >= 0:
i = self.getLastNonDeletedChar(s, i)
j = self.getLastNonDeletedChar(t, j)
if i >= 0 and j >= 0:
if s[i] != t[j]:
return False
elif i >= 0 or j >= 0:
return False
i -= 1
j -= 1
return True
def getLastNonDeletedChar(self, s, i):
num_back_s = 0
while (i >= 0): # get the last non-deleted char in s
if s[i] == '#':
num_back_s += 1
i -= 1
elif num_back_s > 0:
num_back_s -= 1
i -= 1
else:
break
return i
977.有序数组的平方
解题思路
简而言之就是对一个递增数组的每一个元素进行平方,然后再进行递增排序。
很容易马上就想到用JS的forEach(还是有其他的函数可以直接)平方,然后用一下sort。也成功了。
如下所示
function compare(a, b){
return a-b
}
var sortedSquares = function(nums) {
numsSquare = []
nums.forEach((value,index)=>{
s = value * value
numsSquare.push(s)
})
numsSquare = numsSquare.sort(compare)
return numsSquare
};
但接下来考虑时间复杂度为 O(n) 的解法,即只有一遍for循环。
那么就是正负数平方后变化的问题。如果全是正数,那么其实不用考虑第二步的排序;如果是负数,则需要考虑平方后的排序问题。
(它的意思是用双指针咯)
出现的问题
如果数组里有正有负或者全为正,我这么写是可以的。但如果是全负就不行。
var sortedSquares = function(nums) {
let l = 0, r = nums.length-1
while(l <= r){
if(nums[l] * nums[l] <= nums[r] * nums[r]){
nums[r] = nums[r] * nums[r]
}
else{
temp = nums[r]
nums[r] = nums[l] * nums[l]
nums[l] = temp
if(r == 0){
nums[l] = nums[l] * nums[l]
}
}
r--
}
return nums
};
好吧,看了答案发现人家是开辟了一个新的数组(我是在原数组上改的)。
答案代码如解法代码所示。
JavaScript解法代码
var sortedSquares = function(nums) {
const n = nums.length;
const ans = new Array(n).fill(0);
let l = 0, r = n - 1;
let i = n - 1;
while(l <= r){
if(nums[l] * nums[l] > nums[r] * nums[r]){
ans[i--] = nums[l] * nums[l++];
}else{
ans[i--] = nums[r] * nums[r--];
}
}
return ans;
};
Python解法代码
class Solution(object):
def sortedSquares(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
newArr = [0] * len(nums)
l = 0
r = len(nums) - 1
ind = len(nums) - 1
while(l <= r):
if(nums[l] * nums[l] < nums[r] * nums[r]):
newArr[ind] = nums[r] * nums[r]
ind -= 1
r -= 1
else:
newArr[ind] = nums[l] * nums[l]
ind -= 1
l += 1
return newArr
总结:
- 双指针问题一定要脑子清楚:一个动,一个不动。
- 反思自己的脑子不清楚,可能需要多训练吧
- 回顾一下JS的字符串处理方法:
substr(n,m):从索引n开始,截取m个字符
substring(n,m):从索引n开始,截取到索引m,不包括m.将截取的字符返回
slice(n,m) :从索引n开始,截取到索引m,不包括m
str.replace(reg,'替换者')