【无标题】

简单基础算法

1、前缀和

问题描述 :对于给定的数列,求出任意区间的和

问题分析:计算出所有从 0 到第 i 项的和,sa[i] = a[0] + … + a[i];

​ 因此,当要计算 [4~6]的和时,只需要 sa[6] - sa[3];

​ 不难发现:计算 [L,R]的和时,只需要 sa[R] - sa[L-1];

代码逻辑

    int[] a = {3,6,3,7,5};

     //前缀和数组求解
    for (int i = 0; i < a.length;i++) {
        sa[i] = (i == 0) ? a[i] : sa[i-1] + a[i]; //这种前缀和,在求解[0,i]以0开头的前缀和时,直接返回sa[i]即可
    }

    System.out.println("----------前缀和验证-----------");
    //[i,j] <==>  i==0 ? as[j] : sa[j]-sa[i]
    System.out.println("[2,4]的区间和:" + (sa[4] - sa[1]));
    System.out.println("[2,2]的区间和:" + (sa[2] - sa[1]));
    System.out.println("[0,0]的区间和:" + sa[0]); //特殊
    System.out.println("[0,2]的区间和:" + sa[2]); //特殊
2、差分

问题描述:对于一个给定的序列,要将任意区间内的所有数字 + k

问题分析:计算出数列的差分数组,即:da[i] = a[i] - a[i-1]

​ 因此,当我们求解差分数组的前缀和时,就会发现,刚好与原数列相同。

​ 当要计算,[4,6]的区间内的所有数 + k时,由于原数组 = 差分数组的前缀和,因此,只需要在 da[4] + k,da[6+1] - k,后再求解

​ 差分数组就会发现,[4,6]的所有数都 +k,因为,对于 [i,j] 当给 da[i] + k 时,由于原数组 = 差分数组的前缀和,而差分数组的

​ 第 i 项 +k,从 i 项开始的后面所有项在计算时,后会 +k,因此要将 j+1项 -k。

​ 例如:1 2 3 4 5 【原数组】

1 1 1 1 1 【差分数组】

2 1 1 0 1【原数组0~2 项+1 == 差分数组:0项 + 1,3项-1】

2 3 4 4 5【前缀和】

代码逻辑

	    int[] a = {3,6,3,7,5};

        //差分数组求解
        for(int i = 0;i < a.length;i++){
            da[i] = (i == 0) ? a[i] : a[i] - a[i-1];
        }

	    System.out.println("---------差分验证------------");
	    //[i,j]+k <==> da[i]+=k; if(j != da.length-1) da[i+1]-=k;
        System.out.print("\n[2,3]的区间+1:" + (da[2] += 1) +" "+ (da[4] -= 1));
        System.out.print("\n[2,2]的区间+1:" + (da[2] += 1) +" "+ (da[3] -= 1));
        System.out.print("\n[0,2]的区间+1:" + (da[0] += 1) +" "+ (da[3] -= 1));
        System.out.print("\n[2,4]的区间+1:" + (da[2] += 1)); //特殊处理
        System.out.print("\n[3,4]的区间+1:" + (da[3] += 1)); //特殊处理
3、KMP算法

问题描述:从给定的字符串中获取模板字符串的位置

问题分析:预处理一个位置数组,保存当前位置与最开始的位置的前缀等于后缀的最大长度 abab –> 就是 2 :(前缀)ab == (后缀)ab

​ 获得最大前缀等于后缀的值后,再通过改记录的位置数组,当遇到不匹配的字符时,就不要返回,直接回到上一个匹配的即可

代码逻辑

        String s = " " + "abcababbababbfiababbababb";
        String p = " " + "ababbababb";

        /*
        答案:
            匹配成功!下标为:4
            匹配成功!下标为:16
        */

        //获取next数组
        int[] next = new int[p.length()];
        for(int i = 2,j = 0;i <= next.length-1;i++){
            while(j > 0 && p.charAt(i) != p.charAt(j+1)) j = next[j]; //如果匹配不成功,回到上一个匹配成功的位置再次匹配
            if(p.charAt(i) == p.charAt(j+1)) j++;
            next[i] = j;
        }

        //匹配字符串
        int len = s.length();
        for(int i =1,j = 0;i <= len-1;i++){
            while(j > 0 && s.charAt(i) != p.charAt(j+1)) j = next[j];
            if(s.charAt(i) == p.charAt(j+1)) j++;
            if(j == next.length-1){
                //匹配成功
                System.out.println("匹配成功:" + (i - next.length + 2));
                j = next[j];
            }
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值