算法进阶(第一天)

1.KMP算法(一种改进的字符串匹配算法):

KMP计算流程:

假设有两个字符串str1和str2,求str2是否是str1的子串

1.先定义一个str2字符串长度的数组,数组中存放的为最长前缀后缀匹配数,其中第一个为-1,第二个为0;

2.str1和str2进行匹配,当碰到不匹配的情况,str2则从开头向后走最长匹配数,再进行匹配;

  原因:str1与str2进行匹配,那么不匹配前的数肯定是相等的,因为最长匹配,最后和最前相等,所以最开始的几个数不需要从头匹配,节省时间。

 public static int getIndexOf(String m,String n){
        if(m==null||n==null||n.length()<1||m.length()<n.length()){
            return -1;
        }
        char[] str1 = m.toCharArray();
        char[] str2 = n.toCharArray();
        int i=0;
        int j=0;
        int[] next = getNextArray(str2);
        while(i<str1.length&&j<str2.length){
            if(str1[i]==str2[j]){
                i++;
                j++;
            }
            else if(next[j]==-1){
                i++;
            }
            else{
                j = next[j];
            }
        }
        return j ==str2.length? i-j:-1;
    }

最长前缀后缀匹配数求解:

1.第一个数为-1,第二个为0;

2.现有i-1,i两个位置,如果i-1位置上的数,是i-1的最长前缀后缀数的下一个数,那么i位置上的最长匹配数为i-1的数+1;

3.如果不是,那么去寻找i-1的最长匹配数的位置j,重复上一步;

4.再不是,则i位置的最长匹配数为0。

    public static int[] getNextArray(char[] str2){
        if(str2.length==1){
            return new int[]{-1};
        }
        int[] next = new int[str2.length];
        next[0]=-1;
        next[1]=0;
        int cn = 0;
        int i=2;
        while(i<str2.length){
            if(str2[i-1]==str2[cn]){
                next[i++] = ++cn;
            }
            else if(cn>0){
                cn = next[cn];
            }
            else{
                next[i++] = 0;
            }
        }
        return next;
    }

2.Manacher算法

3. BFPRT算法(求一个数组中第k小或者第k大的数):(arr,k)

    3.1 将数组进行分组,每五个分为一组

    3.2 将组内元素进行排序,组间不排序

    3.3 取出组中的中位数,组成一个新数组

    3.4 递归BFPRT算法,BFPRT(new_Arr,new_Arr.length/2); 此时获得的结果是新数组的中位数;

    3.5 将此中位数作为荷兰国旗划分的标准。

    3.6 荷兰国旗划分最差情况7/10N,原因中位数是新数组的中位数,那么最差情况为1/10个数比它大,新数组中又是中位数,因此至少有3/10N比它大,所以最差是7/10N;

 public static int bfprt(int[] arr,int begin,int end,int k){
        if(begin==end){
            return arr[begin];
        }
        int pivot = medianOfMedians(arr,begin,end);
        int[] index = patation(arr, begin,end,pivot);
        if(k>=index[0]&&k<=index[1]){
            return arr[k];
        }
        else if(k>index[1]){
            return bfprt(arr,index[1]+1,end,k);
        }
        else{
            return bfprt(arr,0,index[0]-1,k);
        }
    }
public static int medianOfMedians(int[] arr,int begin,int end){
        int num = end-begin+1;
        int offset = num%5 ==0?0:1;
        int[] mArr = new int[num%5+offset];
        for(int i=0;i<mArr.length;i++){
            int beginI = begin + i*5;
            int endI = begin + 4 ;
            mArr[i] = getMedian(arr,beginI,Math.min(end,endI));
        }
        return bfprt(mArr,0,mArr.length-1,mArr.length/2);
    }
 public static int getMedian(int[] arr,int begin,int end){
        insertionSort(arr,begin,end);
        int sum = begin + end;
        int mid = sum/2 + sum%2;
        return arr[mid];
    }
    public static void insertionSort(int[] arr,int begin,int end){
        for(int i= begin+1;i!=end+1;i++){
            for(int j = i;j!=begin;j--){
                if(arr[j-1]>arr[j]){
                    swap(arr,j-1,j);
                }
                else{
                    break;
                }
            }
        }
    }
    public static void swap(int[] arr,int i,int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值