1、岛问题:一个矩阵中只有0和1两种值,每个位置都可以和自己的上下左右四个位置相连,如果有一片1连在一起,这个部分叫做一个岛,求一个矩阵中有多少个岛?
递归:
package hh;
public class Demo {
public static int countIslands(int[][] m) {
if(m==null || m[0]==null) {//此处不要忘记判断
return 0;//没有数组或数组中无值
}
int x=m.length;
int y=m[0].length;
int res=0;
for(int i=0;i<x;i++) {
for(int j=0;j<y;j++) {
if(m[i][j]==1) {
res++;
infect(m,i,j,x,y);
}
}
}
return res;
}
public static void infect(int[][] m,int i,int j,int x,int y) {
if(i<0 || i>=x || j<0 || j>=y || m[i][j]!=1) {//m[i][j]为2或者0
return;
}
//i,j没越界,且当前位置为1
m[i][j]=2;
infect(m,i-1,j,x,y);//感染上
infect(m,i+1,j,x,y);//下
infect(m,i,j-1,x,y);//左
infect(m,i,j+1,x,y);//右
}
public static void main(String[] args) {
int[][] m1= {
{1,1,1,1,1,1,1,1},
{1,0,0,0,0,0,0,1},
{1,0,1,1,1,1,1,1},
{1,0,1,0,0,0,0,0},
{1,0,1,1,1,1,1,1},
{1,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1}
};
System.out.println(countIslands(m1));
int[][] m2= {
{1,1,1,1,1,1,1,1},
{1,0,0,0,0,0,0,1},
{1,0,0,1,1,1,1,1},
{1,0,1,0,0,0,0,0},
{1,0,1,1,1,1,1,1},
{1,0,0,0,0,0,0,1},
{1,0,1,1,1,1,1,0}
};
System.out.println(countIslands(m2));
}
}
//1
//3
2、并查集结构
package hh;
import java.util.*;
public class Demo {
public static class Element<V>{//泛型,样本进来会包一层,为一个元素
public V value;
public Element(V value) {
this.value=value;
}
}
public static class UnionFindSet<V> {//并查集结构
public HashMap<V,Element<V>> elementMap;
public HashMap<Element<V>,Element<V>> fatherMap;
public HashMap<Element<V>,Integer> sizeMap;//代表节点和归属它的总节点数
//代表节点其实就像一个树的根
public UnionFindSet(List<V> list) {//初始化
elementMap=new HashMap<>();
fatherMap=new HashMap<>();
sizeMap=new HashMap<>();
for(V value:list) {
Element<V> element=new Element<V>(value);
elementMap.put(value, element);
fatherMap.put(element, element);
sizeMap.put(element, 1);
}
}
//返回element的代表节点,一路往上找,向上过程中进行扁平化优化
private Element<V> findHead(Element<V> element){
Stack<Element<V>> path=new Stack<>();//用栈存沿途经过的节点
Element<V> father=fatherMap.get(element);
while(father!=element) {
path.add(element);
element=father;
father=fatherMap.get(element);
}
while(!path.isEmpty()) {
fatherMap.put(path.pop(), element);
}
return element;
}
public boolean isSameSet(V a,V b) {//判断a、b是否为同一集合
if(elementMap.containsKey(a) && elementMap.containsKey(b)) {//注意前提:a、b有初始化,包了一层
return findHead(elementMap.get(a))==findHead(elementMap.get(b));
}
return false;
}
public void union(V a,V b) {//合并
if(elementMap.containsKey(a) && elementMap.containsKey(b)) {
Element<V> n1=findHead(elementMap.get(a));
Element<V> n2=findHead(elementMap.get(b));
//不同集合才合并,即有不同的代表节点
if(n1!=n2) {
int size1=sizeMap.get(n1);
int size2=sizeMap.get(n2);
Element<V> big=size1>size2? n1:n2;
Element<V> small=big==n1? n2:n1;
fatherMap.put(small, big);//big挂到small下
sizeMap.put(big, size1+size2);
sizeMap.remove(small);
}
}
}
}
}
3、KMP算法
package hh;
import java.util.*;
public class Demo {
public static int getIndexOf(String s,String m) {
if(s==null || m==null || m.length()<1 || s.length()<m.length()) {
return -1;
}
char[] s1=s.toCharArray();
char[] s2=m.toCharArray();
int[] next=getNextArray(s2);
int i1=0;
int i2=0;
while(i1<s1.length && i2<s2.length) {
if(s1[i1]==s2[i2]) {
i1++;
i2++;
}else if(i2==0) {//若不相等,回跳 //条件也可以为next[i2]==-1
//若i2已指向s2的0位置,是无法回跳的
i1++;//换i1下一个字符和i2比较
}else {//可以回跳的情况
i2=next[i2];
}
}
return i2==s2.length? i1-i2:-1;
}
//求每个字符前(不包括该字符)最长前后缀匹配长度
public static int[] getNextArray(char[] ms) {
if(ms.length==1) {
return new int[] {-1};
}
//长度至少为2
int[] next=new int[ms.length];
next[0]=-1;
next[1]=0;
int i=2;
int cn=0;//cn保存当前和i-1位置比较的位置,第一次循环应为0,1位置比,以保存第2位置的信息
while(i<ms.length) {
if(ms[cn]==ms[i-1]) {
next[i]=cn+1;
i++;
cn++;//cn同时也是i位置的最长前后缀匹配长度,保存供i+1位置使用
}else if(cn==0) {//cn已经跳到了ms的0位置,仍然与i-1位置上的字符不相等
next[i++]=0;
//next[i]=0;
//i++; -
}else {
cn=next[cn];
}
}
return next;
}
public static void main(String[] args) {
String s1="abcabcababaccc";
String s2="abac";
System.out.println(getIndexOf(s1,s2));//8
String s11="abbsabbcabbsabbe";
String s22="abbsabbcabbsabbw";
System.out.println(getIndexOf(s11,s22));
//-1
String s3="11111112";
String s4="12";
System.out.println(getIndexOf(s3,s4));//6
}
}