双指针算法-day11(双序列双指针)

1.比较含退格的字符串

题目

解析

  • 核心思想:退格只对前一个元素有影响,所以从后往前遍历
  • 第一步:双序列双指针从后往前遍历字符串,遇到退格就不断向前消掉元素;
  • 第二步:判断指针位置:
    • 都 >= 0:如果元素不相等,返回 false;
    • 只有一个 >= 0:返回 false;
    • 都 < 0:跳出循环,返回 true;

代码

class Solution {
public:
    bool backspaceCompare(string s, string t) {
        // 时间复杂度:O(m + n)
        // 空间复杂度:O(1)

        int n = s.size(),m = t.size();
        int skipS = 0,skipT = 0;// 记录字符串中'#'数量

        int i = n - 1,j = m - 1;
        while(i >= 0 || j >= 0){
            // 从后往前消掉 s 中的 '#'
            while(i >= 0){
                if(s[i] == '#'){
                    skipS ++, i --;
                }else if(skipS > 0){
                    skipS --, i --;
                }else{
                    break;
                }
            }

            // 从后往前消掉 t 中的 '#'
            while(j >= 0){
                if(t[j] == '#'){
                    skipT ++, j --;
                }else if(skipT > 0){
                    skipT --, j --;
                }else{
                    break;
                }
            }

            // i,j 都没有遍历完,继续比较字符
            if(i >= 0 && j >= 0){
                if(s[i] != t[j]){
                    return false;
                }
            }else if(i >= 0 || j >= 0){ // 只有一个遍历完了
                return false;
            }

            i --,j --;
        }

        return true;
    }
};

2.情感丰富的文字

题目

解析

  • 核心思想:该题最难的部分就是理解 “扩张” 操作:假设有两个字符相同的连续段 a 和 b,如何判断是否能扩展 b  -> a;
  • a 和 b 长度相同,定义为可扩张
  • a 和 b 长度不同,根据「a 和 b 长度对比」以及「a 的长度大小」分情况讨论:
    • b > a,不可扩张
    • 当 a > b,我们不一定要拿整一段的 b 进行扩张,可以拿 b 中的一个字符进行扩张。 因此只需要满足 a 扩张后的长度大于等于 3 即可定义为可扩张。

代码

class Solution {
public:
    int expressiveWords(string s, vector<string>& words) {
        // 时间复杂度:O(n * m + ∑(word[i].size()))
        // 空间复杂度:O(1)

        int n = s.size();
        int ans = 0;

        for(string word : words){
            int m = word.size(),i = 0,j = 0;

            // word 为模版字符串,s 为扩展字符串
            while(i < n && j < m){
                if(s[i] != word[j]) break;// 字母不相等

                // 分别找到 s,word 连续相同字符长度 a,b
                int a = i,b = j;
                while(a < n && s[a] == s[i]) a ++;
                while(b < m && word[b] == word[j]) b ++;
                a -= i,b -= j;

                // 如果长度不相等,且扩展的长度 a < b 模版长度,不可扩展
                // 如果扩展长度 a < 3,也不可扩展
                if(a != b && (a < b || a < 3)) break;

                // 更新指针,继续遍历下一个元素
                i += a,j += b;
            }

            if(i == n && j == m) ans ++;
        }

        return ans;
    }
};

3.最小差

题目

解析

  • 核心思想:两个序列数字进行比较,数字更小的指针移动

代码

class Solution {
    typedef long long ll;
public:
    int smallestDifference(vector<int>& a, vector<int>& b) {
        // 时间复杂度:O(nlogn + mlogm)
        // 空间复杂度:O(1)

        int n = a.size(),m = b.size();
        ll ans = INT_MAX;
        
        sort(a.begin(),a.end());
        sort(b.begin(),b.end());

        int i = 0,j = 0;
        while(i < n && j < m){
            if(a[i] == b[j]) return 0;
            else {
                ans = min(ans,abs((ll)a[i] - (ll)b[j]));

                if(a[i] > b[j]) j ++;
                else i ++;
            } 
        }

        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值