当前位置: 首页 > news >正文

【刷题2025】单指针双指针+滑动窗口+二分法三分法+区间问题

1.数组理论基础

2.单指针双指针

双指针法(快慢指针法):通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。

  • 暴力解法时间复杂度:O(n^2)
  • 双指针时间复杂度:O(n)

例题:移除元素

'''
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
'''
# (版本一)快慢指针法
class Solution:def removeElement(self, nums: List[int], val: int) -> int:# 快慢指针fast = 0  # 快指针slow = 0  # 慢指针size = len(nums)while fast < size:  # 不加等于是因为,a = size 时,nums[a] 会越界# slow 用来收集不等于 val 的值,如果 fast 对应值不等于 val,则把它与 slow 替换if nums[fast] != val:nums[slow] = nums[fast]slow += 1fast += 1return slow

例题:有序数组的平方

'''
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
'''
class Solution:def sortedSquares(self, nums: List[int]) -> List[int]:l, r, i = 0, len(nums)-1, len(nums)-1res = [float('inf')] * len(nums) # 需要提前定义列表,存放结果while l <= r:if nums[l] ** 2 < nums[r] ** 2: # 左右边界进行对比,找出最大值res[i] = nums[r] ** 2r -= 1 # 右指针往左移动else:res[i] = nums[l] ** 2l += 1 # 左指针往右移动i -= 1 # 存放结果的指针需要往前平移一位return res

 (1)跳房子II

题目描述

跳房子,也叫跳飞机,是一种世界性的儿童游戏。

游戏参与者需要分多个回合按顺序跳到第1格直到房子的最后一格,然后获得一次选房子的机会,直到所有房子被选完,房子最多的人获胜。

跳房子的过程中,如果有踩线等违规行为,会结束当前回合,甚至可能倒退几步。假设房子的总格数是count,小红每回合可能连续跳的步数都放在数组steps中,请问数组中是否有一种步数的组合,可以让小红三个回合跳到最后一格?

如果有,请输出索引和最小的步数组合(数据保证索引和最小的步数组合是唯一的)。

注意:数组中的步数可以重复,但数组中的元素不能重复使用。

(在list中选三个数和为房子总格数?)

输入描述

第一行输入为房子总格数count,它是int整数类型

第二行输入为每回合可能连续跳的步数,它是int整数数组类型

输出描述

返回索引和最小的满足要求的步数组合 (顺序保持 steps中原有顺序)

备注

−count≤10000−3≤steps.length≤10000−−100000≤steps[i]≤100000

样例

输入

[1,4,5,2,0,2]
9

输出

[4,5,0]

输入

[1,5,2,0,2,4]
9

输出

[5,2,2]

输入

[-1,2,4,9]
12

输出

[-1,4,9]
# 超时
# 排序后遍历每个元素作为第一个节点,取l和r作为第三个节点
# 总和偏小时l右移,总和偏大时r左移
steps = list(map(int, input()[1:-1].split(",")))
n = int(input())def solve():ans = []newsteps = []for i in range(len(steps)):newsteps.append([steps[i], i])newsteps.sort()for i in range(len(newsteps)-2):# 剪枝if newsteps[i][0] > 0 and 0 < n < newsteps[i][0]:breakif i > 0 and newsteps[i][0] == newsteps[i-1][0]:continuel = i + 1r = len(newsteps) - 1while l < r:if newsteps[i][0] + newsteps[l][0] + newsteps[r][0] > n:r -= 1elif newsteps[i][0] + newsteps[l][0] + newsteps[r][0] == n:while l < r-1 and newsteps[r][0] == newsteps[r-1][0]:r -= 1a = [newsteps[i], newsteps[l], newsteps[r]]a.sort(key=lambda x:x[1])ans.append(a)r -= 1else:l += 1ans.sort(key=lambda x:(x[0][1]+x[1][1]+x[2][1], x[0][1], x[1][1], x[2][1]))return ans[0]s = solve()
a = [s[0][0], s[1][0], s[2][0]]
print("[" + ",".join(list(map(str, a))) + "]")

(2)事件推送

题目描述

同一个数轴X上有两个点的集合A={A1,A2,..,Am}和B={B1,B2,…,Bn},Ai和Bj均为正整数,A、B已经按照从小到大排好序,

A、B均不为空,给定一个距离R(正整数),列出同时满足如下条件的所有(Ai,Bj)数对:

  1. Ai<= Bj
  2. Ai,Bj之间的距离小于等于R
  3. 在满足1,2的情况下,每个Ai只需输出距离最近的Bj
  4. 输出结果按Ai从小到大的顺序排序

输入描述

第一行三个正整数m,n,R

第二行m个正整数,表示集合A

第三行n个正整数,表示集合B

输入限制:

1<=R<=100000,1<=n,m<=100000,1<=Ai,Bj<=1000000000

这个题目和ABR很像,但是条件差不就那么一点点。

输出描述

每组数对输出一行Ai和Bj,以空格隔开

注意

1.Ai<=Bj
2.Ai,Bj距离小于等于R,但如果Ai找不到R范围内的B,则列出距它最近的1个Bj,当然此种情况仍然要满足1,
但如果仍然找不到,就丢弃Ai。

用例

输入
4 5 5
1 5 5 10
1 3 8 8 20
输出
1 1
5 8
5 8
m, n, R = list(map(int,input().split()))
A = list(map(int,input().split()))
B = list(map(int,input().split()))def solve():aj = 0bj = 0while aj < m and bj < n:if A[aj] <= B[bj]:if B[bj] - A[aj] <= R:print(" ".join(list(map(str, [A[aj], B[bj]]))))aj += 1else:bj += 1returnsolve()
# 知识点总结
# 当出现TLE RTE时检查循环跳出是否正确
# 检查坐标是否超出界限
m, n, R = list(map(int,input().split()))
A = list(map(int,input().split()))
B = list(map(int,input().split()))def solve():aj = 0bj = 0while aj < m and bj < n:while bj < n and B[bj] < A[aj]:bj += 1if bj >= n:breakif B[bj] - A[aj] > R:aj += 1continueprint(" ".join(list(map(str, [A[aj], B[bj]]))))aj += 1returnsolve()

(3)最长连续子序列

题目描述

有N个正整数组成的一个序列。给定整数sum,求长度最长的连续子序列,使他们的和等于sum,返回此子序列的长度。如果没有满足要求的序列,返回-1。

输入描述

第一行输入是:N个正整数组成的一个序列
第二行输入是:给定整数sum

输出描述

最长的连续子序列的长度

备注

输入序列仅由数字和英文逗号构成,数字之间采用英文逗号分隔。序列长度:1<=N<= 200
输入序列不考虑异常情况

示例1:
输入
1,2,3,4,2
6
输出
3
说明
1,2,3和4,2两个序列均能满足要求,所以最长的连续序列为1,2,3,因此结果为3.

示例2:
输入
1,2,3,4,2
20
输出
-1
说明
没有满足要求的子序列,返回-1

# 当left>=right时不要轻易break再给他一次机会吧!
# 先把问题解决了再想剪枝吧!
num = list(map(int, input().split(",")))
n = int(input())def solve():result = 0if len(num) == 1 and num[0] == n:return 1left, right = 0, 1  # 左闭右开区间cursum = num[0]while left < len(num) and right <= len(num):if (left >= right and right <len(num)) or cursum < n:right += 1if right <= len(num):cursum += num[right-1]else:breakelif cursum == n:result = max(result, right-left)if right < len(num) - 1 and left < len(num)-2:cursum += num[right]cursum -= num[left]right += 1left += 1else:breakelif cursum > n:cursum -= num[left]left += 1return result if result != 0 else -1print(solve())
# 或者采用前缀和方法也是可以滴
# 输入获取
nums = list(map(int, input().split(",")))
target = int(input())# 算法入口
def getResult():n = len(nums)preSum = [0] * (n + 1)for i in range(1, n + 1):preSum[i] = preSum[i - 1] + nums[i - 1]maxLen = -1for l in range(1, n + 1):for r in range(l, n + 1):if preSum[r] - preSum[l - 1] == target:maxLen = max(maxLen, r - l + 1)return maxLen# 算法调用
print(getResult())

(4)分割数组的最大差值

题目描述
给定一个由若干整数组成的数组nums,可以在数组内的任意位置进行分割,将该数组分割成两个非空子数组(即左数组和右数组),分别对子数组求和得到两个值,计算这两个值的差值,请输出所有分割方案中,差值最大的值。

输入描述
第一行输入数组中元素个数n,1<n<= 100000
第二行输入数字序列,以空格进行分隔,数字取值为4字节整数

输出描述
输出差值的最大取值

示例1:
输入:
6
1 -2 3 4 -9 7
输出:
10
说明:
将数组nums划分为两个非空数组的可行方案有:
左数组=[1]且右数组=[-2,3,4,-9,7],和的差值=|1-3|=2
左数组=[1,-2]且右数组=[3,4,-9,7],和的差值=|1-5|=6
左数组=[1,-2,3]且右数组=[4,-9,7],和的差值=|2-2|=0
左数组=[1,-2,3,4]且右数组=[-9,7],和的差值=|6-(-2)|= 8,
左数组=[1,-2,3,4,-9]且右数组=[7],和的差值=|-3-7|=10最大的差值为10

n = int(input())
nums = list(map(int, input().split()))def solve():maxdiff = 0index = 0  # 左数组[0, index],右数组[index+1, -1]leftsum = 0rightsum = sum(nums)while index < n -1:leftsum += nums[index]rightsum -= nums[index]maxdiff = max(maxdiff, abs(leftsum-rightsum))index += 1return maxdiffprint(solve())

(5)最大花费金额

题目描述

双十一众多商品进行打折销售,小明想购买自己心仪的一些物品,但由于受购买资金限制,所以他决定从众多心仪商品中购买三件,而且想尽可能的花完资金。

现在请你设计一个程序帮助小明计算尽可能花费的最大资金数额

输入描述

输入第一行为一维整型数组M,数组长度小于100,数组元素记录单个商品的价格,单个商品价格小于1000.

输入第二行为购买资金的额度R,R小于100000

输入格式是正确的,无需考虑格式错误的情况.

输出描述

输出为满足上述条件的最大花费额度

如果不存在满足上述条件的商品,请返回-1。

用例

prices = list(map(int, input().split(",")))
n = len(prices)
target = int(input())def solve():prices.sort()if n < 3:return -1if n == 3:return sum(prices) if sum(prices) <= target else -1ans = 0for i in range(n-2):for j in range(i+1, n-1):if prices[i] + prices[j] >= target or prices[i] + prices[j]*2 > target:continuefor k in range(j+1, n):if prices[i] + prices[j] + prices[k] == target:return targetelif prices[i] + prices[j] + prices[k] < target:ans = max(ans, prices[i] + prices[j] + prices[k])else:breakreturn ans if ans != 0 else -1print(solve())

3.滑动窗口

根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)的暴力解法降为O(n)。

  • 暴力解法时间复杂度:O(n^2)
  • 滑动窗口时间复杂度:O(n)

例题:长度最小的子数组

209.长度最小的子数组

'''
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
'''
class Solution:def minSubArrayLen(self, s: int, nums: List[int]) -> int:l = len(nums)left = 0right = 0min_len = float('inf')cur_sum = 0 #当前的累加值while right < l:cur_sum += nums[right]while cur_sum >= s: # 当前累加值大于目标值min_len = min(min_len, right - left + 1)cur_sum -= nums[left]left += 1right += 1return min_len if min_len != float('inf') else 0

 (1)寻找符合要求的最长子串

题目描述:
给定一个字符串 s ,找出这样一个子串:
1)该子串中的任意一个字符最多出现2次;
2)该子串不包含指定某个字符;
 请你找出满足该条件的最长子串的长度。
输入描述:
第一行为要求不包含的指定字符,为单个字符,取值范围[0-9a-zA-Z]
第二行为字符串s,每个字符范围[0-9a-zA-Z],长度范围[1,10000]
输出描述:
一个整数,满足条件的最长子串的长度;如果不存在满足条件的子串,则返回0
示例1
输入:
D
ABC123
输出:
6
示例2
输入:
D
ABACA123D
输出:
7

forbid = input()
s = input()def solve():count = [0] * 128max_length = 0left = 0right = 0  # 左闭右闭区间while right < len(s):# 不是指定字符,上一子串结束,记录结果if not (s[right].isdigit() or s[right].isalpha()) or s[right] == forbid:for c in s[left:right]:count[ord(c)] -= 1max_length = max(max_length, right - left)left, right = right + 1, right + 1else:# 有重复字符if count[ord(s[right])] == 2:max_length = max(max_length, right - left)

相关文章:

  • 如何一键检查网页里的失效链接和废弃域名?
  • 【加密算法】SM2密钥生成与转换详解:从原理到代码实现
  • ecovadis分为哪些类别,要进行ecovadis认证有什么要求
  • 榕壹云场馆预定系统:基于ThinkPHP+MySQL+UniApp打造的全能运动馆智慧运营解决方案
  • 解锁Grok-3的极致潜能:高阶应用与创新实践
  • 多模态大模型文字识别 vs OCR识别模型
  • 【Python进阶】断言(assert)的十大核心应用场景解析
  • RelativeLayout(相对布局)
  • Mac电脑交叉编译iphone设备可以运行的redsocks, openssl, libsevent
  • Rust + WebAssembly 性能剖析指南
  • 辛格迪客户案例 | 厦门三维丝实施SAP系统
  • js ES6箭头函数的作用
  • 0415-批量删除操作
  • ERR_PNPM_DLX_NO_BIN No binaries found in tailwindcss
  • ClickHouse 数据库中的 “超时”
  • 游戏引擎学习第227天
  • Java微服务线程隔离技术对比:线程池隔离 vs 信号量隔离
  • union all 关联查询
  • OpenAI发布GPT-4.1:开发者专属模型的深度解析 [特殊字符]
  • 无服务器架构(Serverless)在Web开发与云原生中的应用研究
  • 继微软之后,亚马逊也放缓人工智能数据中心计划
  • 女子拿蘸料时触电受伤,海底捞回应
  • 商务部新闻发言人就美国以关税手段胁迫其他国家限制对华经贸合作事答记者问
  • 全国登记在册民营企业超过5700万户,占企业总量92.3%
  • 官方披露:定西民政局原局长将收受烟酒高价“倒卖”给单位,用于违规接待
  • 诺奖得主等数十位经济学家发表宣言反对美关税政策