leetcode刷题之数组(一)

难度:简单

1.删除排序数组中的重复项:给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/
解法:双指针法:1,第一个指针i:由于数组已经完成排序,因此遍历数组,每遇到nums[i] != nums[i-1],就说明遇到了新的不同数字,记录之。
2,第二个指针k:每遇到不同的新数字时,执行k += 1,k指针有两个作用,(1)记录数组中不同数字的数量,(2)作为修改数组元素的索引index。参考链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/solution/remove-duplicates-from-sorted-array-shuang-zhi-zhe/

class Solution:
    def removeDuplicates(self, nums: [int]) -> int:
        if not nums: return 0
        k = 1
        for i in range(1, len(nums)):
            if nums[i] != nums[i - 1]:
                nums[k] = nums[i]
                k += 1
        return k

2.移除元素:给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。题目链接:https://leetcode-cn.com/problems/remove-element/
解法:元素覆盖,生成两个指针,val挨个和nums[i]中的元素比较,相同跳过,不同则用nums[k]代替此时的nums[i],同时指针k加一,依次进行。参考链接:https://leetcode-cn.com/problems/remove-element/solution/yi-chu-yuan-su-by-powcai/

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        if not nums :return 0
        k = 0
        for i in range(len(nums)):
            if nums[i] != val:
                nums[k] = nums[i]
                k +=1
        return k

3.搜索插入位置:给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。你可以假设数组中无重复元素。题目链接:https://leetcode-cn.com/problems/search-insert-position/
解法1:自己的弱鸡解法,简单的逻辑判断,易懂。

def searchInsert(nums,target):
    if target< nums[0]:return 0
    elif target > nums[len(nums)-1]:
        return len(nums)
    for i in range(len(nums)):
        nums[i] ==
    for i in range(len(nums)-1):
        if nums[i] == target:
            return i
        elif nums[i] < target <nums[i+1]:
            return i+1

解法2:二分法思想,参考链接:https://leetcode-cn.com/problems/search-insert-position/solution/te-bie-hao-yong-de-er-fen-cha-fa-fa-mo-ban-python-/

def searchInsert(nums,target):
    size = len(nums)
    if size == 0:
        return 0
    left = 0
    right = size
    while left<right:
        mid = (left+right)//2
        if nums[mid] < target:
            left = mid +1
        else:
            assert nums[mid] >= target
            right = mid
    return left 

4.二分查找:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。题目链接:https://leetcode-cn.com/problems/binary-search/
解法1:首先判断一下target是否在数组内,接着再用二分法判断。

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        if target not in nums:return -1
        right = len(nums) 
        left = 0
        while left < right:
            mid = left + (right-left)//2
            if nums[mid] < target:
                left = mid + 1
            elif nums[mid] > target:
                right = mid 
            return right

解法2:直接用二分法判断,注意有三次判别,还有就是right应该len(nums)-1。

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        right = len(nums) - 1
        left = 0
        while left <= right:
            mid = left + (right-left)//2
            if nums[mid] < target:
                left = mid + 1
            elif nums[mid] > target:
                right = mid - 1
            else:
                return mid
        return -1

解法3,利用bisect模块查找(这个模块的源码也是利用二分法查找)。参考链接:https://leetcode-cn.com/problems/binary-search/solution/ji-chu-er-fen-cha-zhao-by-tuotuoli/

import bisect
def search(nums, target) -> int:
    i = bisect.bisect(nums, target)
    return i - 1 if nums[i - 1] == target else -1

5.最大子序和:给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。题目链接:https://leetcode-cn.com/problems/maximum-subarray/
解法1:动态规划:(1)定义当前最大连续子序列和cur_sum=0,最大子序和res=nums[0],数组长度n。(2)对数组进行遍历,对于nums[i],存在两种情况:
a.若当前最大连续子序列和cur_sum>0,说明cur_sum对后续结果有着正向增益,既能使后续结果继续增大,则继续加和cur_sum = sur_sum + nums[i]。b.若当前最大连续子序列和cur_sum<=0,说明cur_sum对后续结果没有增益或负向增益,即若存在更大的加和,一定是从下一元素开始,加上cur_sum,只会使结果更小。因此,令cur_sum更新为nums[i]。
更新最大子序和res,res=max(res,cur_sum),始终保留最大结果。

def maxsubArray(nums):
    cur_sum=0
    res = nums[0]
    for i in range(len(nums)):
        if cur_sum > 0:
            cur_sum += nums[i]  
        else:
            cur_sum = nums[i]
        res = max(cur_sum,res)
    return res

6.加一:给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。你可以假设除了整数 0 之外,这个整数不会以零开头。题目链接:https://leetcode-cn.com/problems/plus-one/

解法:该方法是原创,详细的解题过程在:https://leetcode-cn.com/problems/plus-one/solution/python-luo-ji-qing-xi-dai-ma-shao-shi-jian-fu-za-d/

class Solution:
    def plusOne(self, digits: List[int]) -> List[int]:
        cur = -1
        while digits[cur] +1 == 10:
            digits[cur] = 0
            cur -= 1
            if cur<-len(digits):
                l = [1]
                return l+digits
        digits[cur] +=1
        return digits

7.合并两个有序数组:给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。初始化 nums1 和 nums2 的元素数量分别为 m 和 n。你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。题目链接:https://leetcode-cn.com/problems/merge-sorted-array/

解法:题目要求:列表在原基础上修改。先删除不需要的元素,然后相加再排序

class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        """
        Do not return anything, modify nums1 in-place instead.
        """
        del nums1[m:]
        del nums2[n:]
        nums1 +=nums2
        nums1.sort()

8.买卖股票的最佳时机:给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。注意你不能在买入股票前卖出股票。题目链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/
解法:动态规划,同时记录
最低价格
和卖出的最大利润。参考链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/solution/python-by-yiwei-luo/
最大利润=max{前一天最大利润, 今天的价格 - 之前最低价格}

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        if len(prices) <= 1:return 0
        min_p = prices[0]
        max_p = 0
        for i in range(len(prices)):
            min_p = min(min_p,prices[i])
            max_p = max(max_p,prices[i]-min_p)
        return max_p

9.买卖股票的最佳时机2:给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。题目链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/
解法:(动态规划)建议先看代码,在看我的解释。这个自己误打误撞的解法,逻辑是再买卖股票最佳时机1的基础上改进的,首先我还是计算现在的价格减去前一天的价格,只要利润大于0,就把这次的利润保留,同时更新现在的最低价格为今天的价格,然后循环就可以了。

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        if len(prices) <= 1 : return 0
        min_p = prices[0]
        cur_p = 0
        max_p = []
        for i in range(len(prices)):
            min_p = min(min_p,prices[i])
            cur_p = max(cur_p,prices[i]-min_p)
            if cur_p > 0:
                max_p.append(cur_p)
                min_p = prices[i]
                cur_p = 0
        return sum(max_p)

上面的解法思路有一个更好的编程逻辑和思考逻辑,和我的一比(我就是个菜鸡),参考链接https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/solution/best-time-to-buy-and-sell-stock-ii-zhuan-hua-fa-ji/

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        profit = 0
        for i in range(1, len(prices)):
            tmp = prices[i] - prices[i - 1]
            if tmp > 0: profit += tmp
        return profit

10.两数之和II–输入有序数组 给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。说明:
(1)返回的下标值(index1 和 index2)不是从零开始的。(2)你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。题目链接:https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/

解法1:列表查找,index1从前找,index2反向从后找,问题:运行时间超出范围

class Solution:
    def twoSum(self, numbers: List[int], target: int) -> List[int]:
        for i in numbers:
            if target-i in numbers:
                index1 = numbers.index(i)+1
                index2 = len(numbers)-(numbers[::-1].index(target-i))
                return index1,index2

解法2:指针对撞(注意题目条件有序数组)

class Solution:
    def twoSum(self, numbers: List[int], target: int) -> List[int]:
        n = len(numbers)
        left = 0
        right = n-1
        while left<right:
            if numbers[left] + numbers[right] < target:
                left += 1
            elif numbers[left] + numbers[right] > target:
                right -= 1
            else:
                return left+1,right+1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值