算法复习:双指针(对撞指针、快慢指针)

一、快慢指针: leedcode 142. 环形链表 II

快慢指针的思想是设置慢指针slow和快指针fast,slow每次走一步,fast每次走两步,如果有环fast指针和slow指针必然相遇,相遇时

定义新的指针p从head开始和slow从当前位置起每次都走一步,直到相遇,相遇的位置就是环的入口。

class Solution {
public:
    ListNode *detectCycle(ListNode *head)
    {
        int lable=0;
        struct ListNode *slow,*fast,*pp;
        if(head==NULL)
            return NULL;
        if(head->next==NULL)
            return NULL;
        slow=head->next;
        if(slow->next==NULL)
            return NULL;
        fast=slow->next;
        while(slow!=fast)// 步骤一:使用快慢指针判断链表是否有环
        {
            if(fast->next==NULL)
            {
                lable=1;
                break;
            }
            fast=fast->next;//快指针走两步
            if(fast->next==NULL)
            {
                lable=1;
                break;
            }
            fast=fast->next;
            slow=slow->next;//慢指针走一步
        }
        if(lable==1)
            return NULL;
        pp=head;
        while(pp!=slow)// 步骤二:若有环,找到入环开始的节点
        {
            pp=pp->next;
            slow=slow->next;
        }
        return pp;
    }
};
leedcode 142
int main()
{
    struct ListNode *head,*p,*q;
    head=NULL;
    q=(ListNode*)malloc(sizeof(ListNode));//malloc的方法
    q->next=NULL;
    int num;
    cout<<"Input num"<<endl;
    scanf("%d",&num);
    for(int i=0;i//建链表插入链表
    {
        p=(ListNode*)malloc(sizeof(ListNode));
        cout<<"Input number"<<endl;
        p->next=NULL;
        scanf("%d",&p->val);
        if(i==0)
            head=p;
        else
            q->next=p;
        q=p;
    }
    int loop;
    cout<<"Input loop"<<endl;
    scanf("%d",&loop);
    if(loop==-1)
        q->next=NULL;
    else//建循环链表
    {
        p=(ListNode*)malloc(sizeof(ListNode));
        p=head;
        for(int i=0;i)
        {
            p=p->next;
        }
        q->next=p;
    }
    p=detectCycle(head);
    cout<val<<endl;
    return 0;
}
main函数

 

二、对撞指针:leedcode 11. 盛最多水的容器

对撞指针要求两个指针up和down分别从前后两端向中间走,指定一个指针更新规则

本题计算面积,水的上限由短板决定,因此更新规则是选取短的那一个边的方向向中间移动,直到指针碰撞

int min(int a,int b)
    {
        if(a>b)
            return b;
        else
            return a;
    }
    int maxArea(vector<int>& height)
    {
        int up=0,down=height.size()-1;
        int area=down*min(height[0],height[down]),tmp_area=0;
        while(up<down)
        {
            tmp_area=(down-up)*min(height[up],height[down]);
            if(tmp_area>area)
                area=tmp_area;
            if(height[up]>height[down])
                down--;
            else
                up++;
        }
        return area;
    }
leedcode 11

leedcode 125. 验证回文串

双指针根据规则向中间靠拢即可

class Solution {
public:
    bool isPalindrome(string s) {
        int up=0,down=s.size()-1;
        int lable=0;
        while(up<=down)
        {
            if((s[up]>='0'&&s[up]<='9')||(s[up]>='A'&&s[up]<='Z')||(s[up]>='a'&&s[up]<='z'))
            {
                if(s[up]>='A'&&s[up]<='Z')
                    s[up]=s[up]+('a'-'A');
            }
            else
            {
                up++;
                continue;
            }
            if((s[down]>='0'&&s[down]<='9')||(s[down]>='A'&&s[down]<='Z')||(s[down]>='a'&&s[down]<='z'))
            {
                if(s[down]>='A'&&s[down]<='Z')
                    s[down]=s[down]+('a'-'A');
            }
            else
            {
                down--;
                continue;
            }
            if(s[up]==s[down])
            {
                up++;
                down--;
            }
            else
            {
                lable=1;
                break;
            }
        }
        if(lable==1)
            return false;
        else
            return true;
    }
};
leedcode 125

 leedcode 167. 两数之和 II - 输入有序数组

class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        int up=0,down=numbers.size()-1;
        while(up<=down)
        {
            if(numbers[up]+numbers[down]>target)
            {
                down--;
                continue;
            }
            if(numbers[up]+numbers[down]<target)
            {
                up++;
                continue;
            }
            if(numbers[up]+numbers[down]==target)
                break;
        }
        vector<int>result;
        result.push_back(up+1);
        result.push_back(down+1);
        return result;
    }
};
leedcode 167

 

三、其他指针

牛客 替换指针

有空间限制不能使用第二个数组转存,因此先遍历一遍统计空格‘ ’的数量,然后留足空间(2倍空格数量),

down指针从后往前扫,up指针从原串最后往前扫,碰到‘ ’就替换成‘0’‘2’‘%’,直到up down相撞

class Solution {
public:
    void replaceSpace(char *str,int length) {
        int num=0,i;
        for(i=0;str[i]!='\0';i++)
        {
            if(str[i]==' ')
                num++;
        }
        int len_final=i+num*2;
        char *down=str+len_final;
        char *up=str+i;
        while(up!=down)
        {
            if(*up==' ')
            {
                *down--='0';
                *down--='2';
                *down--='%';
            }
            else
                *down--=*up;
            up--;
        }
        return;
    }
};
View Code

 

你可能感兴趣的:(算法复习:双指针(对撞指针、快慢指针))