Leetcode题解 - Easy - 2

20- 有效的括号

问题

给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。

思路

显然应该用栈来解决。

不过留意一点,题目中规定了字符串中只包括括号,所以只需一个mapping存右括号,如果不在右括号中就一定是左括号,直接append进栈即可,无需判断当前字符是不是非括号字符。

代码

class Solution:
    def isValid(self, s):
        """
        :type s: str
        :rtype: bool
        """
        stack = []
        mapping = {
            ')': '(',
            ']': '[',
            '}': '{',
        }
        for c in s:
            if c in mapping:
                if stack and stack[-1] == mapping[c]:
                    stack.pop(-1)
                else:
                    return False
            else:
                stack.append(c)
        return not stack

21- 合并两个有序链表

问题

将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例:

输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4

思路

特别要留意指针操作

代码

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def mergeTwoLists(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        head = ListNode(-1)
        current = head
        while l1 and l2:
            if l1.val <= l2.val:
                current.next = l1
                current = l1
                l1 = l1.next
            else:
                current.next = l2
                current = l2
                l2 = l2.next
        if l1:
            current.next = l1
        if l2:
            current.next = l2
        return head.next

26- 删除排序数组中的重复项

问题

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

示例 :

给定数组 nums = [1,1,2],

函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。

你不需要考虑数组中超出新长度后面的元素。

思路

一快一慢两个指针,慢指针代表当前去重后的结果的进度,快指针代表当前检查的进度,遇到重复元素,快指针跳过,遇到不重复,则值复制到慢指针处,两者都往前移动,直到快指针扫完全部。

代码

class Solution:
    def removeDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if len(nums) <= 1:
            return len(nums)
        
        left = 0
        right = 1
        while right < len(nums):
            if nums[right] != nums[left]:
                left += 1
                nums[left] = nums[right]
            right += 1
        return left + 1
        

27- 移除元素

问题

给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

思路

与26相同的思路,双指针。

由于本题中条件【元素的顺序可以改变】,可以进一步优化。双指针法在某些特殊情况下效率比较低,例如 41235 要删4,需要把1235都挪一次,产生了很多挪动。

改进方法:当前要删,则将当前与最后一个元素交换位置,并删除最后一个元素,然后继续检查当前是否要删,直到不要删,再往后接着判断。

代码

# 双指针
class Solution:
    def removeElement(self, nums, val):
        """
        :type nums: List[int]
        :type val: int
        :rtype: int
        """
        if len(nums) < 1:
            return 0
        left = -1
        right = 0
        while right < len(nums):
            if nums[right] != val:
                left += 1
                nums[left] = nums[right]
            right += 1
        return left + 1
        
        
# 优化方法:交换
class Solution:
    def removeElement(self, nums, val):
        """
        :type nums: List[int]
        :type val: int
        :rtype: int
        """
        if len(nums) < 1:
            return 0
        left = 0
        right = len(nums) - 1
        while left <= right:
            if nums[left] == val:
                nums[left] = nums[right]
                right -= 1
            else:
                left += 1
        return left

特别注意:
26、27两题要注意一些特殊情况能否正确处理,例如

[]
[3] val=4
[3] val=3
[3,3,3] val=3

28- 实现 strStr()

问题

实现 strStr() 函数。

给定一个 haystack(草堆) 字符串和一个 needle (针)字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。

示例 :

输入: haystack = "hello", needle = "ll"
输出: 2

思路

基本思路就是从头第一个字符开始依次往后找。

更高效的KMP算法:
如何更好的理解和掌握 KMP 算法? - 逍遥行的回答 - 知乎
https://www.zhihu.com/question/21923021/answer/37475572

【【【TODO:添加KMP算法的写法】】】

代码

# 基础写法
class Solution:
    def strStr(self, haystack, needle):
        """
        :type haystack: str
        :type needle: str
        :rtype: int
        """
        if not needle:
            return 0
        if not haystack:
            return -1
        j = 0
        for i in range(0, len(haystack)):
            if i + len(needle) <= len(haystack):
                if haystack[i: i+len(needle)] == needle:
                    return i
        return -1

35- 搜索插入位置

问题

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

你可以假设数组中无重复元素。

示例 :
输入: [1,3,5,6], 5
输出: 2

输入: [1,3,5,6], 2
输出: 1

输入: [1,3,5,6], 7
输出: 4

输入: [1,3,5,6], 0
输出: 0

思路

由于排序数组,最基本的就是按顺序从前往后找。
可通过二分查找提高效率。

代码

# 二分查找。需注意最后的判断,因为如果找不到,要返回能插入的位置。
class Solution:
    def searchInsert(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        start = 0
        end = len(nums) - 1
        while start <= end:
            mid = (start + end) // 2
            if nums[mid] == target:
                return mid
            elif nums[mid] < target:
                start = mid +  1
            else:
                end = mid - 1
        if nums[mid] < target:
            return mid + 1
        else:
            return mid
        

38- 报数

问题

报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。
比如说,
n=1时, 1
n=2时,读前面一项,是 一个一,所以此时是 11
n=3时,读前面一项,是 二个一,所以此时是 21
n=4时,读前面一项,是 一个二 一个一,所以此时是 1211
n=5时,读前面一项,是 一个一 一个二 二个一,所以此时是 111221
以此类推。
给定一个正整数 n(1 ≤ n ≤ 30),输出报数序列的第 n 项。

思路

模拟人怎么来读取就可以,不过感觉代码写的比较笨2333

代码

class Solution:
    def countAndSay(self, n):
        """
        :type n: int
        :rtype: str
        """
        if n <= 0:
            return ''
        if n == 1:
            return '1'
        last_str = '1'
        for i in range(1, n):
            cur_char = ''
            cur_count = 0
            cur_str = ''
            for c in last_str:
                if c == cur_char:
                    cur_count += 1
                elif cur_count != 0:
                    cur_str += str(cur_count) + cur_char
                    cur_count = 1
                    cur_char = c
                else:
                    cur_char = c
                    cur_count = 1
            if cur_count != 0:
                cur_str += str(cur_count) + cur_char
            last_str = cur_str
        return last_str

53- 最大子序和

问题

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

进阶:
如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。

思路

参考这里:连续子数组的最大和

代码

import sys
class Solution:
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        sum_ = sys.maxsize * -1
        max_ = sum_
        for i in nums:
            if sum_ < 0:
                sum_ = i
            else:
                sum_ += i
            if max_ < sum_:
                max_ = sum_
        return max_

58- 最后一个单词的长度

问题

给定一个仅包含大小写字母和空格 的字符串,返回其最后一个单词的长度。
如果不存在最后一个单词,请返回 0 。

说明:一个单词是指由字母组成,但不包含任何空格的字符串。

示例:
输入: "Hello World"
输出: 5

思路

思路很简单,注意特殊比如 abc_ 这种空格在最后的情况,所以要先trim掉空格

代码

class Solution:
    def lengthOfLastWord(self, s):
        """
        :type s: str
        :rtype: int
        """
        ret = 0
        s = s.strip()
        for i in s:
            if i == ' ':
                ret = 0
            else:
                ret += 1
        return ret

66- 加一

问题

给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。

最高位数字存放在数组的首位, 数组中每个元素只存储一个数字。

你可以假设除了整数 0 之外,这个整数不会以零开头。

示例 1:

输入: [1,2,3]
输出: [1,2,4]
解释: 输入数组表示数字 123。

思路

主要处理进位,所以从后往前处理,特别注意最后仍然需要进位,导致数组长度需要在前面+1的情况。

代码

class Solution:
    def plusOne(self, digits):
        """
        :type digits: List[int]
        :rtype: List[int]
        """
        up = 1
        for i in range(len(digits)-1, -1, -1):
            digits[i] += up
            if digits[i] > 9:
                up = 1
                digits[i] %= 10
            else:
                up = 0
        if up:
            digits = [up, ] + digits
        return digits

你可能感兴趣的:(Leetcode题解 - Easy - 2)