难度简单2763
给你一个 升序排列 的数组 nums
,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k
个元素,那么 nums
的前 k
个元素应该保存最终结果。
将最终结果插入 nums
的前 k
个位置后返回 k
。
不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
判题标准:
系统会用下面的代码来测试你的题解:
int[] nums = [...]; // 输入数组 int[] expectedNums = [...]; // 长度正确的期望答案 int k = removeDuplicates(nums); // 调用 assert k == expectedNums.length; for (int i = 0; i < k; i++) { assert nums[i] == expectedNums[i]; }
如果所有断言都通过,那么您的题解将被 通过。
思考:这是一道简单题,这里的断言就是逐个判断,这道题一看就是双指针的方法进行计算,一个确定需要调整的数值位置,另外一个不断判断确认下一个需要替换的位置。
left, right = 1, 1
while right < len(nums):
if nums[right] != nums[right - 1]:
nums[left] = nums[right]
left+= 1
right += 1
return left
难度困难1938
给你一个只包含 '('
和 ')'
的字符串,找出最长有效(格式正确且连续)括号子串的长度。
示例 1:
输入:s = "(()" 输出:2 解释:最长有效括号子串是 "()"
示例 2:
输入:s = ")()())" 输出:4 解释:最长有效括号子串是 "()()"
示例 3:
输入:s = "" 输出:0
思考:最长有效子串,主要就是关于最长括号。我是看答案才知道的。
先用栈的方法,主要技巧需要先在栈中放入-1,来判断0之前的数。
class Solution:
def longers(self,strs):
stack = [-1]
maxlen, lens = 0, 0
if not nums:return -1
for i in range(len(strs)):
if strs[i] == "(": #当为左括号的时候,只要压入就行
stack.append(i) # 压入位置就好
else: # 否则马上弹出
stack.pop()
if not stack: # 如果栈中已经没有东西,需要将当前的位置压入,这点很关键。
stack.append(i)
else:
lens = i - stack[-1]
maxlen = max(maxlen, lens)
return maxlen
这里需要判断的状态函数有,i-dp[i-1] - 1,为外部接触的最长括号,或者说没有别切断的连接括号。
动态规划的方法。
class Solution:
def longers(self,strs):
dp = [0] * (len(strs)
for i in range(len(strs)):
# 状态函数
if s[i] ==')" and i - dp[i -1] - 1 > 0 and s[i - dp[i -1] - 1] == "(":
dp[i] = dp[i - 1] + 2 + dp[i - dp[i - 1] - 2]
# 变量为,内有效值,判断条件为i-1,外有效条件为i -dp[i-1] - 2
return max(dp)
难度中等2240
整数数组 nums
按升序排列,数组中的值 互不相同 。
在传递给函数之前,nums
在预先未知的某个下标 k
(0 <= k < nums.length
)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]]
(下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7]
在下标 3
处经旋转后可能变为 [4,5,6,7,0,1,2]
。
给你 旋转后 的数组 nums
和一个整数 target
,如果 nums
中存在这个目标值 target
,则返回它的下标,否则返回 -1
。
你必须设计一个时间复杂度为 O(log n)
的算法解决此问题。
示例 1:
输入:nums = [4,5,6,7,0,1,2]
, target = 0
输出:4
示例 2:
输入:nums = [4,5,6,7,0,1,2]
, target = 3
输出:-1
思考:题目给的是一个正序数组,然后在一个地方旋转啦。也就是说,将正序数组后面一段截断。直接放在前面。形成一个一段有序。另一段有序的现象。
但是时间复杂度为logn,这个很容易想到二分查找的方法,主要先将数组分成两部分,由于是正序数组,如果与满足某一部分的边界值,可以继续对这一部分进行二分查找,相当于本来是16,8,4,2.查找方式十分迅速。
class Solution:
def retort(self, nums):
***
二分查找是这样的,在一个递增的数列当中,如果target也就是我们的目标数值在所需要的数值前面的时候。
left, right = 0 ,len(nums) -1
while left < right:
mid = (left + right) // 2
if nums[mid] > target:
r = mid - 1
else:
l = mid + 1
这里的问题在于只有某一段是递增的,所以只需要查询递增部分就好。
while l <= r:
mid = (l + r ) // 2
if nums[mid] == target:return mid
elif nums[mid] < nums[r]:
if nums[mid] < target <= nums[r]:
l = mid + 1
else:
r = mid - 1
else:
if nums[l] <= target < nums[mid]:
r = mid - 1
else:
l = mid + 1
return -1