难度:简单
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