字符串移动k位的时间复杂度o(n)空间复杂度o(1)的解法

本文介绍了一种高效的字符串旋转算法,通过将字符串分为两部分并进行特定变换实现字符串的左移或右移操作。该算法的时间复杂度为O(n),空间复杂度为O(1)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于一个长度为n的字符串,将其左移或右移k位,在此以右移为例。

1.将字符串分成2段,1段是从左计算的长度n-k的段 另一段是剩下的长度为k的串

2.先将第一段与第二段的最后长度为n-k的部分交换;

3.再将原第二段的最后长度n-k的段变换为对称串(即刚交换到前方的部分);

4.再将第二段没动过的部分做对称变换;

5.最后将3 4步骤中的串视为一个串做对称变换 完成。

若k比n大,只需右移k mod n即可。

左移和右移思路一样,不再赘述。

对长度为n的串做对称变换需要时间是n/2 对2个长度为n的串交换需要时间为n,

移动一共需要时间为 (n-k)+(n-k)/2+(k-(n-k))/2+k/2=n

所以时间复杂性为o(n), 交换至多用常数空间,变换不需额外空间。所以空间复杂性为o(1)。

















++


<think>嗯,用户想了解双指针法如何将时间复杂度降到O(n)。首先,我需要回忆一下双指针法的基本概念和应用场景。双指针法通常用于数组或链表这类线性数据结构的问题中,比如查找子数组、判断回文、合并有序数组等等。 用户可能已经知道,普通的暴力解法可能会用到两层循环,导致O()时间复杂度。而双指针法通过两个指针协同工作,可以在一次遍历中解决问题,从而将复杂度降到O(n)。但具体是怎么做到的呢?我需要用简单易懂的例子来说明。 比如,最常见的例子是判断一个字符串是否为回文。如果用暴力法,可能需要比较所有字符对称的置,但双指针法可以用头尾两个指针向中间移动,每次比较对应置的字符是否相同。这样只需要遍历一半的字符串,所以时间复杂度是O(n)。 另一个例子是两数之和的问题。如果数组是有序的,双指针可以从两端开始,根据当前的和调整指针的置,直到找到目标值。这种情况下,只需要一次遍历,时间复杂度也是O(n)。 但要注意,双指针法适用的前提通常是数组已经排序,或者问题本身允许指针单向移动。比如在移除有序数组中的重复元素时,快慢指针可以一次遍历完成,快指针探路,慢指针记录不重复的置,这样时间复杂度同样是O(n)。 用户可能想知道为什么双指针法能降低复杂度。关键在于两个指针的移动方向是否合理,是否减少了不必要的重复计算。比如在滑动窗口问题中,窗口的左右指针都只向前移动,不会回溯,这样每个元素最多被访问两次,总体操作次数是O(n)。 不过,可能有些情况下双指针法并不能直接应用,需要结合其他方法。比如某些情况下可能需要先排序,这会带来O(n log n)的时间,但之后的双指针处理仍然是O(n),整体复杂度由排序步骤决定。这时候可能需要权衡利弊。 总结来说,双指针法通过合理移动两个指针,避免嵌套循环,将问题简化为线性遍历,从而将时间复杂度从O()降到O(n)。需要结合具体例子来讲解,确保用户理解指针移动的策略和如何覆盖所有可能的情况。</think>双指针法通过两个指针的协同移动,将原本需要嵌套循环的问题简化为单层循环,从而将时间复杂度从 $O(n^2)$ 降低到 $O(n)$。以下是逐步解释: --- ### **1. 核心思想** 双指针法利用两个指针(通常称为 **快指针** 和 **慢指针**,或 **左指针** 和 **右指针**)在数据结构(如数组、链表)中按特定规则移动,避免重复遍历元素。 **关键点**:两个指针的移动方向、移动条件,以及如何覆盖所有可能性。 --- ### **2. 典型应用场景** #### **场景1:有序数组的两数之和** - **问题**:在有序数组中找两个数,使它们的和为特定值。 - **暴力法**:双层循环遍历所有组合,时间复杂度 $O(n^2)$。 - **双指针法**: 1. 左指针从数组头开始,右指针从数组尾开始。 2. 计算当前两数之和: - 若和等于目标值,直接返回结果。 - 若和小于目标值,左指针右移(增大数值)。 - 若和大于目标值,右指针左移(减小数值)。 3. 时间复杂度:$O(n)$(只需一次遍历)。 ```plaintext 示例:数组 [2, 7, 11, 15],目标值 18 步骤: 1. 左指针指向 2,右指针指向 15 → 2+15=17 < 18 → 左指针右移。 2. 左指针指向 7,右指针指向 15 → 7+15=22 > 18 → 右指针左移。 3. 左指针指向 7,右指针指向 11 → 7+11=18 → 找到结果。 ``` --- #### **场景2:移除有序数组中的重复元素** - **问题**:原地删除有序数组中的重复项,返回新长度。 - **暴力法**:遍历并标记重复元素,最后整理数组,时间复杂度 $O(n^2)$。 - **双指针法**: 1. 慢指针 `slow` 记录不重复元素的末尾置。 2. 快指针 `fast` 遍历数组,发现新元素时,将其复制到 `slow+1` 的置。 3. 时间复杂度:$O(n)$(仅需一次遍历)。 ```plaintext 示例:数组 [1, 1, 2, 3, 3] 步骤: 1. slow=0(指向第一个1),fast=1(第二个1)→ 重复,fast继续右移。 2. fast=2(元素2)→ 不重复 → 将2复制到slow+11)→ slow=1。 3. fast=3(元素3)→ 不重复 → 复制到置2 → slow=2。 4. fast=4(第二个3)→ 重复 → 结束。 结果:数组前3为 [1, 2, 3],长度为3。 ``` --- #### **场景3:判断链表是否有环** - **问题**:判断链表中是否存在环。 - **暴力法**:用哈希表记录访问过的节点,空间复杂度 $O(n)$。 - **快慢指针法**: 1. 快指针每次移动两步,慢指针每次移动一步。 2. 若存在环,快指针最终会追上慢指针;若无环,快指针会先到达终点。 3. 时间复杂度:$O(n)$(线性遍历)。 --- ### **3. 为什么能降低复杂度?** - **减少重复计算**:双指针通过单向移动或条件性移动,确保每个元素最多被访问两次。 - **缩小搜索范围**:在有序数组中,通过指针移动直接排除不可能的情况(如两数之和过大时右指针左移)。 --- ### **4. 适用条件** - 数据具有单调性(如有序数组)。 - 问题可分解为两个相关变量的协同操作(如头尾、快慢)。 --- ### **总结** 双指针法通过合理设计指针的移动规则,将原本需要嵌套循环的问题简化为单层循环,从而将时间复杂度从 $O(n^2)$ 降低到 $O(n)$。其核心在于 **利用数据特性减少不必要的遍历**。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值