双指针法在数组和字符串的应用:LeetCode 27. 移除元素 LeetCode 344.反转字符串 LeetCode 54. 替换数字 LeetCode 151. 反转字符串中的单词

LeetCode 27. 移除元素(需要重点掌握)

class Solution(object):
    def removeElement(self, nums, val):
        """
        :type nums: List[int]
        :type val: int
        :rtype: int
        """
        ### 采用快慢指针,slow和fast同步移动,当找到等于val值的位置后,fast后移,slow不变。随后slow指向更新新数组下标的位置,fast指向那些不等同于val的元素
        ### fast 用于判断元素是否相同; slow 用于指向前移元素的存放下标

        slow, fast = 0, 0
        equal_k = 0
        while fast < len(nums):         ### 去除等于val的元素
            if nums[fast] != val:
                nums[slow] = nums[fast]
                slow += 1 
                fast += 1
            elif nums[fast] == val:
                fast += 1 
                equal_k += 1
                    
        k = len(nums) - equal_k
        nums_k = nums[:k]
        return k           
 ### 可以只return slow指针,因为slow指针指的是下一个不同于val元素需要存放的下标位置,刚好等同于数组中不同于val元素的个数

思路:

  • slow 用于存放 后面不等于val的元素存放到数组前的下标(不等同于val的元素需要存放在数组的位置下标)
  • fast 用于判断 数组中的值是否等于val  (寻找数组中等同于val的元素位置)

LeetCode 344.反转字符串

class Solution(object):
    def reverseString(self, s):
        """
        :type s: List[str]
        :rtype: None Do not return anything, modify s in-place instead.
        """
        ### 首尾颠倒,采用双指针,一个从头开始,一个从尾开始

        left, right = 0, len(s) - 1
        while left < right :
            s[left], s[right] = s[right], s[left]
            left += 1
            right -= 1
        return s    

思路:

  • 首尾颠倒,采用双指针,一个从头开始,一个从尾开始

LeetCode 54. 替换数字

class Solution(object):
    def change_math2number(self, s):
        ### 与移除元素类似,这里可以只用一个指针来查找需要修改/删除的元素位置,由于修改后的内容是一致的,因此可以直接赋予。

        fast = 0
        s = list(s)
        while fast < len(s):
            fast_ord = ord(s[fast])
            a_ord = ord('a')
            if fast_ord - a_ord >= 0:       ### 元素是字母
                fast += 1
            else:                           ### 元素是数字
                s[fast] = "number"
                fast += 1
        return "".join(s)


if __name__ == "__main__":
    solution = Solution()
    s = input()
    change_str = solution.change_math2number(s)
    print(change_str)

思路:

  • 这里可以只用一个指针来查找需要修改/删除的元素位置,由于修改后的内容是一致的,因此可以直接赋予。

LeetCode 151. 反转字符串中的单词(需要重点掌握)

class Solution(object):
    def reverseWords(self, s):
        """
        :type s: str
        :rtype: str
        """
        ### 难点在于删除多余的空格

        ### 与 翻转字符串类似 可以使用一个left指针和一个right指针来对局部每个单词进行反转
        ### 整体翻转 再局部单词翻转


        ### 删除多余空格, 采用类似移除元素的思路,不过区别在于每个单词之间要留一个空格(难点也是重点)
        s = list(s)
        result = ""
        fast = 0
        while fast < len(s):
            if s[fast] != ' ':
                if len(result) != 0:
                    result += ' '       ### 前导空格除外,在每个单词之间加一个空格  

                while fast < len(s) and s[fast] != ' ':        ### 使用while添加每个单词,注意不能用if
                ### while 的判断条件虽跟上面if的判断条件一样,但思路是不一样的。if判断条件是为了找到不为空格的位置,while判断条件是为了将非空格元素进行添加。注意区分
                    result += s[fast]         
                    fast += 1
            else:
                fast += 1

        result = list(result)
        result_list = result[::-1]            ###全局翻转
        left, right =0, 0
        while right <= len(result_list):
            if right < len(result_list) and result_list[right] != ' ':              ### 注意 逻辑操作的前后顺序,如何利用来避免index out of range的情况
                right += 1
            elif right == len(result_list) or result_list[right] == ' ' :           ### 中间的单词 or 最后的一个单词
                self.single_reverse(result_list, left, right - 1)       ### 左右都是闭区间
                left = right + 1 
                right = left 

        result = ''.join(result_list)
        return result
    
    def single_reverse(self, s, left, right):
        while left < right:
            s[left], s[right] = s[right], s[left]
            left += 1
            right -= 1

思路:

  • 类似于移除元素的形式,使用快慢指针来去除多余的空格。这里需要注意的是除头个单词前无空格外,其余每个slow指针赋值前都需要将slow当前的位置赋予一个空格,并在slow+1的位置进行添加操作。在这道题,使用slow和fast来移除相对来说不是很方便,因为数组长度的问题(移除多余空格的数组长度一定是变小的,但这里的话数组长度是不变的,数组最后还存有元素)。因此这里,可以直接使用一个空字符串,通过fast和空字符串长度控制并去除多余的空格。
  • 字符串中的单词翻转,采用全局翻转+局部单词翻转即可完成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值