巩固练习移除元素-26/283/844/977

文章介绍了使用双指针解决数组操作问题的几种方法,包括删除有序数组中的重复项、移动零以及比较含退格的字符串。对于每个问题,都提供了JavaScript和Python的解题代码,强调了在不同情况下如何有效地运用双指针策略。此外,还讨论了时间复杂度和空间复杂度的优化,如在有序数组的平方问题中,如何实现O(n)的时间复杂度解决方案。
摘要由CSDN通过智能技术生成

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

总结:

  1. 双指针问题一定要脑子清楚:一个动,一个不动。
  2. 反思自己的脑子不清楚,可能需要多训练吧
  3. 回顾一下JS的字符串处理方法:

substr(n,m):从索引n开始,截取m个字符
substring(n,m):从索引n开始,截取到索引m,不包括m.将截取的字符返回
slice(n,m) :从索引n开始,截取到索引m,不包括m
str.replace(reg,‘替换者’)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值