简单基础算法
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]; } }