zoukankan      html  css  js  c++  java
  • 两指针扫描算法举例

    问题一:求sum值

    描述:给定一有序序列ary和sum值,求序列中是否存在两元素e1和e2,其和刚好为sum。

    算法思想:
    这是典型的两指针的用法。
    i指针从头部开始,j指针从尾部开始,相向移动,
    本质向讲,在移动过程中比较ary[i]+ary[j]与sum的大小,达到逐步排除元素的过程,缩短查找范围。
    最开始,i和j处于序列首部和尾部
    如果ary[i]+ary[j]=sum,直接返回结果。
    如果ary[i]+ary[j]<sum,需要增大ary[i]或者ary[j],但是j已经不能在增大,只能i++,因此ary[i]永远被排除掉,缩短了查找范围,
    然后在新的序列范围中,继续排除元素逐步缩短查找范围。
    如果ary[i]+ary[j]>sum,需要减小ary[i]或者ary[j],但是i已经不能在减小,只能j--,因此ary[j]永远被排除掉,缩短了查找范围,
    然后在新的序列范围中,继续排除元素逐步缩短查找范围。

    从归纳法的角度看,不难发现,在缩短序列范围的过程中只能是i++或者j--,i只能想后一定吗,j只能向前一定,不能回溯。

    java实现:

        public static boolean search(int[] ary,int low,int high,int sum){
            int i = low,j = high;//一前一后两指针
            while(i<j){//两指针i,j不能碰头,这样能够避免sum=2*ary[i]=2*ary[j]的情况
                if (ary[i]+ary[j] < sum) {
                    i++;
                }else if(ary[i]+ary[j] > sum){
                    j--;
                }else {
                    return true;
                }
            }
            return false;
        }

    问题二:数组原地去重

    描述:给定一重复元素ary,包含若干重复元素,求数组中不重复元素的个数的原地算法,可修改元素组。

    Java实现:

    /*
         *实现原地数组去重,可改变原数组,返回唯一元素的个数。
         *实际上如果利用额外的辅助空间的话,数组去重的方式有很多,
         *此算法思想的优势就在于只需常数的额外辅助空间,也即是就地算法
         * */
        public static int removeDuplicates(int[] ary,int low,int high){
            int i = low,j = i+1;//两指针,i从low开始,j从i+1开始
            for (; j <= high; j++) {
                if (ary[i] != ary[j]) {
                    ary[++i] = ary[j];//i始终记录唯一序列的末尾位置
                }
            }
            return i-low+1;
        }
    
        /*
         * 如果要求重复元素的个数最多可为n(n>=1)
         * */
        public static int removeDuplicates(int[] ary,int low,int high,int n){
            int i = low+n-1,j = i+1;//i直接从第n个元素开始,j从i+1开始
            for (; j <= high; j++) {
                if (ary[i-n+1] != ary[j]) {//在ary[i]前面且距离为n的元素为ary[i-n+1]
                    ary[++i] = ary[j];
                }
            }
            return Math.min(i-low+1, ary.length);
        }

    问题三:三色排序

    问题描述:输入一个整形的数组,每个元素在0到2之间,其中0,1,2分别代表红色、白色和蓝色。现要求对数组进行排序,相同颜色在一起,而且白色在红色之后,蓝色在白色之后,要求之间复杂度在O(n).

    算法思想:
    用两指针i和j记录0序列,1序列,2序列的分界位置
    只要确定了i和j的值,就可以将三个序列区分开来。
    让i指针记录1序列的头部
    j指针记录2序列的头部
    扫描指针k整个序列头开始扫描,过程中实时更新i和j的值,直到k遇到j位置,此时j后面的元素全为2
    i前面的元素全为0,其余元素(i到j之间的元素)全为1。

    java实现:

        public static void sort(int[] ary){
            int i = 0,j = ary.length,k = 0;//i记录1序列的头部,j记录2序列的头部,k始终处于1序列尾部的下一个位置
            while(k<j){
                if (ary[k] == 0) {//将ary[k]=0与ary[i]=1交换,此时可以明确知道ary[i]的值
                    swap(ary, i++, k++);
                }else if(ary[k] == 1){
                    k++;
                }else {//将ary[k]=?与ary[j]=2交换,此时无法知道ary[j--]的值,因此,k保持不变
                    swap(ary, k, --j);
                }
            }
        }
  • 相关阅读:
    GeoMesa Java API-写入与查询数据
    GeoMesa命令行,索引概述
    HBase,以及GeoMesa设计基于HBase的设计分析,从数据模型到典型查询场景,最后进行RowKey设计
    笔趣看小说Python3爬虫抓取
    python网络爬虫
    Kafka客户端Producer与Consumer
    ScalikeJDBC,操作mysql数据,API
    mysqldb
    Python 反射
    Go 类型转换
  • 原文地址:https://www.cnblogs.com/qcblog/p/7583628.html
Copyright © 2011-2022 走看看