力扣--数组题目

26. 删除有序数组中的重复项

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

32. 最长有效括号

难度困难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)

33. 搜索旋转排序数组

难度中等2240

整数数组 nums 按升序排列,数组中的值 互不相同 。

在传递给函数之前,nums 在预先未知的某个下标 k0 <= 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值