美文网首页算法刷题
Leetcode题解 - Easy - 2

Leetcode题解 - Easy - 2

作者: aaanthony | 来源:发表于2019-02-25 16:06 被阅读0次

    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

        本文链接:https://www.haomeiwen.com/subject/ovegyqtx.html