双指针练习题解

在这里插入图片描述

今天的内容是双指针。

双指针

双指针一般应用于数组,链表,比如用于数组的头尾指针,判断链表带环问题的快慢指针,两个指针的移动速度不一定能够相同。

双指针种类:
1.有用在两个数组中的,遍历比较这两个数组的。
2.同一个数组中同向追赶指针
3.同一个数组中相向最终相遇的指针。
4.链表的快慢指针

题解

2000. 反转单词前缀

思路:先遍历字符串找到那个ch字符,找不到直接返回源字符串。然后用双指针一个指向开头,一个指向ch,两个指针相向移动,交换字符即可。

char * reversePrefix(char * word, char ch){
    int i =0;
    int start = 0;
    for(i = 0;word[i];i++)
    {
        if(word[i]==ch)
        {
            break;
        }
    }
    if(word[i]=='\0')
    {
        return word;
    }
    while(start < i)
    {
        char tmp = word[start];
        word[start] = word[i];
        word[i] = tmp;
        start++;
        i--;
    }
    return word;
}

917. 仅仅反转字母

思路:用双指针遍历字符串,如果左右都是字母就交换,如果左边是字符,右边不是就–right;反之++left,如果两边都不是字母就–rigth;++left

char * reverseOnlyLetters(char * s){
    int len = strlen(s);
    int left = 0;
    int right = len-1;
    while(left<right)
    {
        if(isalpha(s[left])&&isalpha(s[right]))
        {
            char tmp = s[left];
            s[left] = s[right];
            s[right] = tmp;
            left++;
            right--;
        }
        else if(isalpha(s[left]))
        {
            right--;
        }
        else if(isalpha(s[right]))
        {
            left++;
        }
        else
        {
            left++;
            right--;
        }
    }
    return s;
}

475. 供暖器

排序+二分_思路:先对这个heaters进行排序,然后枚举每个房子,去heaters中找到小于等于该房子的最大的供暖器heaters下标记为uleft,也就是从左边,离着这个房子最近的供暖期位置,然后右边里这个房子最近的供暖器下标为uright,计算出左距离,右距离,然后取最小值,然后将最小半径,与ans比较,最小半径里面的最大半径,就是答案。
二分查找时有两个特殊情况,当heaters[0]都>find时,返回-1,让左距离失效,即为INTMAX,这时候右距离就时heaters[0]到房屋的最小距离。当返回的uleft = heaterssize-1(当作n-1),时uleft = n,这时候如果计算右距离就会越界,也就是最右边的供暖器都在房子的左边,右距离为负数,记作INTMAX,然后左距离此时即使最小距离。

int cmp(const void* str1,const void* str2)
{
    return *(int*)str1 - *(int*)str2;
}
int Binary(int* heaters,int heatersSize,int find)
{
    int max = 0;
    int left = 0;
    int right = heatersSize-1;
    if(heaters[left]>find)
    {
        return -1;//返回左下标为-1(无效坐标)右坐标为0,因为这样子右距离为正的,否则返回0的话左距离为负会出错。
    }
    while(left<=right)
    {
        int mid = (left+right)>>1;
        if(heaters[mid]<=find)
        {
            max = mid;
            left = mid+1;
        }
        else
        {
            right = mid-1;
        }
    }
    return max;
}
int findRadius(int* houses, int housesSize, int* heaters, int heatersSize){
    int max = 0;
    int ans = 0;
    int leftdistance = 0;
    int rightdistance = 0;
    qsort(heaters,heatersSize,sizeof(int),cmp);
    
    for(int i =0;i<housesSize;i++)
    {
        int find = houses[i];

        int uleft = Binary(heaters,heatersSize,find);
        int uright = uleft+1;//当left为n-1的时候,右距离失效,防止越界。
        leftdistance = uleft<0?INT_MAX:houses[i]-heaters[uleft];
        rightdistance = uright>=heatersSize?INT_MAX:heaters[uright]-houses[i];
        max = leftdistance<rightdistance?leftdistance:rightdistance;
        ans = max>ans?max:ans;
    }
    return ans;
}

面试题 16.06. 最小差

排序+二分思路:先将b数组排序,然后遍历a数组到b数组内进行二分查找,找到一个小于等于target的最大值的下标,返回,(特殊情况,b的最小元素都比a大,就返回-1,)然后计算左差值和右差值,最后比较两个差值的大小,取最小的,与ans比较,最终返回小的哪一个就是最小差值。
注意:这里求差值可能会超过int的整形,求之前先将被减数强制转换为long long就可以了。

int cmp(const void*str1,const void* str2)
{
    return *(int*)str1 - *(int*)str2;
}

int Binary(int* b,int bSize,int target)
{
    int ans = bSize-1;
    int left = 0;
    int right = bSize-1;
    if(b[left]>target)
    {
        return -1;
    }
    while(left<=right)
    {
        int mid = (right-left)/2+left;
        if(b[mid]<=target)
        {
            ans = mid;
            left = mid+1;
        }
        else
        {
            right = mid-1;
        }
    }
    return ans;
}

int smallestDifference(int* a, int aSize, int* b, int bSize){
    int uleft = 0;
    int uright = 0;
    long long  subleft = 0;
    long long  subright = 0;
    int ans = INT_MAX;
    int min = 0;
    qsort(b,bSize,sizeof(int),cmp);
    for(int i =0;i<aSize;i++)
    {
        uleft = Binary(b,bSize,a[i]);
        uright = uleft+1;
        subleft = uleft<0?INT_MAX:a[i]-b[uleft];
        subright = uright>=bSize?INT_MAX:(long long)b[uright] - a[i];
        min = subleft<subright?subleft:subright;
        ans = ans<min?ans:min;
    }
    return ans;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KissKernel

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值