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循环会导致时间复杂度直接爆炸,无法通过。

这时候笔者就要介绍一个优化方法:双指针

我们可以定义两个指针,分别为ij,并让他们分别指向两个数组的首元素。因为整数数组是非递增的,且i <= j,所以ij的距离一定比i+1j的距离大。所以我们只需要先固定ij的初始位置,然后比较对应ij各个位置上的元素的大小,求出他们之间的距离即可。这种两个指针同时移动的方法,我们就叫做双指针。

代码实现

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 ≤ jnums1[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),高效完成求解。

相关推荐
kk”4 小时前
Linux的组和权限管理
linux·运维·服务器
YH55269844 小时前
GPT‑5.6 Sol 原本支持 1M 上下文,Codex 现已放开此前限制,如何看待这次调整?
java·jvm·人工智能·gpt·算法·chatgpt
mohesashou5 小时前
红帽linux的K8S部署
linux·kubernetes·ansible
xiaoye-duck6 小时前
《Linux网络编程》UDP Socket 编程实战:从 Echo 回显、通用字典服务到套接字封装全流程
linux·网络·udp
遥感知识服务6 小时前
从局部阈值、双极化到暗地表剔除:NASA OPERA DSWx-S1全球动态水体算法拆解
大数据·人工智能·深度学习·神经网络·算法·机器学习
晚风醉蝶6 小时前
1-13-TimSort
算法
ZJU_统一阿萨姆6 小时前
【算子开发】算子融合与Softmax_LayerNorm实现
人工智能·算法·语言模型·硬件架构
孙克旭_7 小时前
Docker 镜像构建|Vue+SpringBoot+Go 多语言项目 Dockerfile 案例
linux·运维·vue.js·spring boot·docker·dockerfile
life码农7 小时前
Linux截取Nginx指定时间段日志的三种方法(grep/awk/sed)
linux·nginx