七月集训day05双指针

541. 反转字符串 II

代码/思路

思路:拿到字符串,我们以每次2 * k 的距离从头到尾进行遍历;
每次遍历,就在 2 * k 的子串长度内反转 k 长度的子串,如果这次遍历的长度小于2 * k,那么就在整个子串进行反转 k 长度子串的操作。

void swap(char *a, char *b)
{
    char t = *a;
    *a = *b;
    *b = t;
}
/*
反转思路:双指针,分别指向头和尾 依次进行交换
*/
void reverse(char* l, char* r)
{
    while(l < r)
    {
        swap(l++, r--);
    }
}

int min(int a, int b)
{
    return a < b ? a : b;
}

/*
思路:模拟
每计数 2k 个字符就反转这 2k 个字符的前 k 个字符;
所以循环时 i += 2 * k
每次反转操作 就看下 前 k 个字符的长度 和 字符总长谁更短
选择更短的进行反转操作


*/
char * reverseStr(char * s, int k){
    int n = strlen(s);
    for(int i = 0; i < n; i += 2 * k)
    {
        reverse( &s[i], &s[min(i + k - 1, n - 1)] );
    }
    return s;
}

技巧

反转一个字符串

392. 判断子序列

在这里插入图片描述

代码/思路

class Solution {
public:
    bool isSubsequence(string s, string t) {
        /*
        定义两个指针 i, j 分别指向 s 和 t 中的每一个元素
        看 i 和 j 号元素是否相等
        如果相等则 i j 都 ++
        否则 j++
        最后看 i 指向的数组元素是否遍历完
        */
        int i = 0, j = 0;
        //只要指针还指向元素
        while(s[i] && t[j])
        {
            if(s[i] == t[j])
            {
                i++;
            }
            //每次遍历都让j++
            j++;
        }
        //最后看有没有遍历完s数组
        return s[i] == '\0';
    }
};

面试题 16.24. 数对和

在这里插入图片描述

代码/思路

class Solution {
public:
    vector<vector<int>> pairSums(vector<int>& nums, int target) {
        /*
        先把这个数组进行排序
        然后定义两个指针,分别指向头和尾元素
        用val 保存 头尾指针的和 并与目标值target比较
        */
        sort(nums.begin(), nums.end());
        int i = 0;
        int j = nums.size() - 1;
        vector<vector<int>> ans;
        while(i < j)
        {
            int val = nums[i] + nums[j];
            if(val > target)
            {
                j--;
            }
            else if(val < target)
            {
                i++;
            }
            else
            {
                ans.push_back( {nums[i], nums[j]} );
                i++;
                j--;
            }
        }
        return ans;
    }
};

696. 计数二进制子串

在这里插入图片描述

代码/思路

int countBinarySubstrings(char * s){
    /*
    思路:因为0 和 1 都是连续出现的,所以我们统计每次连续的0 或者 1 的个数存入count数组
    然后在count数组中累加相邻的俩个元素中的最小者到res中就是最后的答案
    */
   int f = 0;
   int n = strlen(s);
   int count[n];
   int num = 0;
   memset(count, 0, sizeof(count));
   //统计每次连续的0 或者 1 的个数存入count数组
   while(f < n)
   {
       int index = 0;
       char temp = s[f];
       while(f < n && temp == s[f])
       {
           index++;
           f++;
       }
       count[num++] = index; 
   }
    //在count数组中累加相邻的俩个元素中的最小者到res中
    int res = 0;
    for(int i = 1; i < num; i++)
    {
        res += fmin(count[i], count[i - 1]);
    }
    return res;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值