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


    一、快慢指针: 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<num;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<loop;i++)
            {
                p=p->next;
            }
            q->next=p;
        }
        p=detectCycle(head);
        cout<<p->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

    面试题57 - II. 和为s的连续正数序列

    class Solution {
    public:
        vector<vector<int>> findContinuousSequence(int target) {
            vector<vector<int>>result;
            int head=1,tail=1;
            int s=1;
            while(head<target)
            {
                if(s<target)
                {
                    tail++;
                    s+=tail;
                }
                else if(s>target)
                {
                    s-=head;
                    head++;
                }
                else if(s==target)
                {
                    vector<int> tmp;
                    for(int i=head;i<=tail;i++)
                    {
                        tmp.push_back(i);
                    }
                    result.push_back(tmp);
                    tail++;
                    s+=tail;
                }
            }
            return result;
        }
    };
    View Code

    三、其他指针

    牛客 替换指针

    有空间限制不能使用第二个数组转存,因此先遍历一遍统计空格‘ ’的数量,然后留足空间(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]!='';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

    56. 合并区间

    #include<algorithm>
    #include<string.h>
    #include<stdlib.h>
    struct donser
    {
        int i;
        int j;
    };
    int qsor(const void* a,const void*b)
    {
        return (*(donser *)a).i-(*(donser *)b).i;
    }
    class Solution {
    public:
        vector<vector<int>> merge(vector<vector<int>>& inte) {
            vector<vector<int>>result;
            struct donser my[10002];
            if(inte.size()==0)
                return result;
            for(int i=0;i<inte.size();i++)
            {
                my[i].i=inte[i][0];
                my[i].j=inte[i][1];
            }
            qsort(my,inte.size(),sizeof(donser),qsor);
            my[inte.size()].i=inte[inte.size()-1][0];
            my[inte.size()].j=inte[inte.size()-1][1];
            int x=my[0].i,y=my[0].j;
            for(int i=0;i<inte.size()+1;i++)
            {
                if(x<=my[i].i&&y>=my[i].i)//有交集 更新y
                {
                    y=max(y,my[i].j);
                    if(i==inte.size())//处理最后
                    {
                        vector<int>tmp;
                        tmp.push_back(x);
                        tmp.push_back(y);
                        result.push_back(tmp);
                    }
                }
                else//无交集 存储
                {
                    vector<int>tmp;
                    tmp.push_back(x);
                    tmp.push_back(y);
                    result.push_back(tmp);
                    if(i==inte.size())
                        break;
                    x=my[i].i;
                    y=my[i].j;
                }
            }
            return result;
        }
    };
    leetcode 56

    75. 颜色分类

    四指针,两个用于标记位置,两个用于查找
    class Solution {
    public:
        void sortColors(vector<int>& nums) {
            if(nums.size()<=1)
                return;
            int x=0,y=nums.size()-1;//扫描指针
            int x1=0,y1=nums.size()-1;//位置指针
            int equ1=0,equ2=0;//重合标记
            while(x<=y)
            {
                if(y!=y1)
                    equ2=1;
                if(x!=x1)
                    equ1=1;
                if(equ1==0)//前一半重合
                {
                    if(nums[x]==0)//继续
                    {
                        x++;
                        x1++;
                        continue;
                    }
                    else if(nums[x]==2)//交换
                    {
                        if(nums[y]!=2)
                        {
                            int tmp=nums[x];
                            nums[x]=nums[y];
                            nums[y]=tmp;
                            continue;
                        }
                    }
                    else if(nums[x]==1)//处理
                    {
                        equ1=1;
                        x++;
                        continue;
                    }
                }
                if(equ2==0)//后一半重合
                {
                    if(nums[y]==2)//继续
                    {
                        y--;
                        y1--;
                        continue;
                    }
                    else if(nums[y]==0)//交换
                    {
                        if(nums[x]!=0)
                        {
                            int tmp=nums[x];
                            nums[x]=nums[y];
                            nums[y]=tmp;
                            continue;
                        }
                        if(nums[x]==0)
                        {
                            equ2=1;
                        }
                    }
                    else if(nums[x]==1)//处理
                    {
                        equ2=1;
                        y--;
                        continue;
                    }
                }
                //处理x不重合情况
                if(nums[x]==2)//和y1交换
                {
                    int tmp=nums[x];
                    nums[x]=nums[y1];
                    nums[y1]=tmp;
                    y1--;
                    y=min(y,y1);
                    if(y1==y)
                        equ2=0;
                }
                else if(nums[x]==0)//和x1交换
                {
                    int tmp=nums[x];
                    nums[x]=nums[x1];
                    nums[x1]=tmp;
                    x1++;
                    x=max(x,x1);
                }
                else if(nums[x]==1)
                    x++;
                //处理y不重合情况
                if(nums[y]==2)//和y1交换
                {
                    //cout<<"***"<<nums[y]<<" "<<nums[x]<<endl;
                    int tmp=nums[y];
                    nums[y]=nums[y1];
                    nums[y1]=tmp;
                    y1--;
                    y=min(y,y1);
                }
                else if(nums[y]==0)//和x1交换
                {
                    int tmp=nums[y];
                    nums[y]=nums[x1];
                    nums[x1]=tmp;
                    x1++;
                    x=max(x,x1);
                    if(x1==x)
                        equ1=0;
                }
                else if(nums[y]==1)
                    y--;
            }
            return ;
        }
    };
    leetcode 75
  • 相关阅读:
    Redis_数据类型
    python 单独设置在plot每条线的label为中文
    制作9patch图片心得——Android开发使用类似QQ聊天的冒泡对话框
    Oracle数据库实验一建立数据库
    Postman使用总结
    jmeter使用小结
    python实现系统调用cmd命令的模块---subprocess模块
    程序进程线程之间的区别
    Fiddler抓包工具简介
    MySQL基础SQL命令---增删改查
  • 原文地址:https://www.cnblogs.com/dzzy/p/12253675.html
Copyright © 2020-2023  润新知