下标对中的最大距离
问题描述
给你两个 非递增 的整数数组 nums1 和 nums2 ,数组下标均 从 0 开始 计数。
下标对 (i, j) 中 0 <= i < nums1.length 且 0 <= j < nums2.length 。如果该下标对同时满足 i <= j 且 nums1[i] <= nums2[j] ,则称之为 有效 下标对,该下标对的 距离 为 j - i 。
返回所有 有效 下标对 (i, j) 中的 最大距离 。如果不存在有效下标对,返回 0 。
一个数组 arr ,如果每个 1 <= i < arr.length 均有 arr[i-1] >= arr[i] 成立,那么该数组是一个 非递增 数组。
(真题链接:下标对中的最大距离)
解题思路
当看到题目的时候,我们能想到的最快的解法是挨个遍历一遍不就好了。但实际操作下来会发现:挨个遍历,即两层for循环会导致时间复杂度直接爆炸,无法通过。
这时候笔者就要介绍一个优化方法:双指针 。
我们可以定义两个指针,分别为i和j,并让他们分别指向两个数组的首元素。因为整数数组是非递增的,且i <= j,所以i到j的距离一定比i+1到j的距离大。所以我们只需要先固定i和j的初始位置,然后比较对应i和j各个位置上的元素的大小,求出他们之间的距离即可。这种两个指针同时移动的方法,我们就叫做双指针。
代码实现
cpp
class Solution {
public:
int maxDistance(vector<int>& nums1, vector<int>& nums2) {
int ret = 0;
int i = 0, j = 0;
// 优化:双指针
for(i = 0, j = 0; i < nums1.size() && j < nums2.size();)
{
if(nums1[i] <= nums2[j])
{
ret = max(ret, j - i);
j++;
}
else
{
i++;
j++;
}
}
return ret;
}
};
复杂度分析
| 复杂度 | 量级 |
|---|---|
| 时间复杂度 | O(n) |
| 空间复杂度 | O(1) |
总结
本题给定两个非递增数组,需找出满足下标i ≤ j且nums1[i] ≤ nums2[j]的最大下标距离;暴力双重循环效率过低,利用数组非递增的特性采用双指针解法,两个指针从头开始遍历,满足条件就更新最大距离并向后移动j,不满足则同时后移i和j,仅需一次遍历就能求解,时间复杂度为线性、空间复杂度为常量,是本题最优解题方式。
将1移动到末尾的最大操作次数
问题描述
给你一个 二进制字符串 s。
你可以对这个字符串执行 任意次 下述操作:
选择字符串中的任一下标 i( i + 1 < s.length ),该下标满足 s[i] == '1' 且 s[i + 1] == '0'
将字符 s[i] 向 右移 直到它到达字符串的末端或另一个 '1'。例如,对于 s = "010010",如果我们选择 i = 1,结果字符串将会是 s = "000110"。
返回你能执行的 最大 操作次数。
(真题链接:将1移动到末尾的最大操作次数)
解题思路
该通过一次线性遍历 实现二进制字符串最大操作数的求解,核心逻辑为:初始化总操作数计数器cnt和已遍历到的连续1的数量n,遍历字符串时直接跳过字符0,仅对字符1进行处理;当检测到当前1右侧存在连续0时,标记为有效操作并直接跳过整段连续0,触发有效操作后将当前累计的1的数量n累加到总操作数cnt中;若遍历到后续的字符1,则递增n的计数,最终通过单次遍历完成所有有效操作的统计。
代码实现
cpp
class Solution {
public:
int maxOperations(string s) {
int cnt = 0;
int n = 1;
for(int i = 0; i < s.size(); i++)
{
if(s[i] == '0')continue;
bool flag = false;
if(i < s.size() - 1 && s[i + 1] == '0')
{
s[i] = '0';
flag = true;
i++;
}
while(i < s.size() - 1 && s[i + 1] == '0')
{
i++;
}
if(flag)
{
cnt += n;
s[i] = '1';
}
if(i < s.size() - 1 && s[i + 1] == '1')n++;
}
return cnt;
}
};
复杂度分析
| 复杂度 | 量级 |
|---|---|
| 时间复杂度 | O(n) |
| 空间复杂度 | O(1) |
总结
总结
本题求解二进制字符串中1按规则右移的最大操作次数,采用线性遍历+计数统计的最优解法,仅需一次遍历字符串,通过累计已遍历的1的数量,在遇到1右侧的连续0时累加操作数,无需额外空间;算法时间复杂度为O(n)、空间复杂度为O(1),高效完成求解。