leetcode热题 - 6

下标对中的最大距离

问题描述

给你两个 非递增 的整数数组 nums1​​​​​​ 和 nums2​​​​​​ ,数组下标均 从 0 开始 计数。

下标对 (i, j) 中 0 <= i < nums1.length 且 0 <= j < nums2.length 。如果该下标对同时满足 i <= j 且 nums1i <= nums2j ,则称之为 有效 下标对,该下标对的 距离 为 j - i​​ 。​​

返回所有 有效 下标对 (i, j) 中的 最大距离 。如果不存在有效下标对,返回 0 。

一个数组 arr ,如果每个 1 <= i < arr.length 均有 arri-1 >= arri 成立,那么该数组是一个 非递增 数组。

(真题链接:下标对中的最大距离)

解题思路

当看到题目的时候,我们能想到的最快的解法是挨个遍历一遍不就好了。但实际操作下来会发现:挨个遍历,即两层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 ),该下标满足 si == '1' 且 si + 1 == '0'

将字符 si 向 右移 直到它到达字符串的末端或另一个 '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),高效完成求解。

相关推荐
weixin_307779133 小时前
C++代码实现MATLAB中的dlarray函数功能
开发语言·c++·算法·matlab
Ruiery6 小时前
Linux 6.6内核 CPU 深度解析(七):调度器启动 — 从单核到多核,调度器分阶段点亮
linux·运维·服务器
50万马克的面包7 小时前
CSDN-栈队列数组-知识点整理
linux·运维·服务器
wjkjpcba8 小时前
PCBA烧录程序是什么:PCBA包工包料厂家解析烧录与测试
linux·数据库·人工智能·smt贴片加工·pcba贴片加工厂
hetao17338378 小时前
2026-10-03~04 hetao1733837 的刷题记录
c++·算法
꯭自꯭闭꯭8 小时前
达梦事物特性及MVCC
linux·运维·数据库
Zootopia6269 小时前
飞行力学知识梳理1|飞行性能与稳定性
人工智能·python·算法·机器学习·无人机·学习方法·信息与通信
longlongzihan9 小时前
从LeetCode 70. 爬楼梯看动态规划:如何精准推导状态转移方程?
c++·算法·leetcode·动态规划
2601_9603563810 小时前
2027校招采购岗解析:数学基础如何迁移到需求预测、成本与供应商分析
人工智能·算法
羔羊++10 小时前
18_实验十七_其他命令与自定义启动变量
linux