您的位置:首页 > 理论基础 > 数据结构算法

算法与数据结构-字符串 讲解与java代码实现

2018-02-01 11:10 866 查看

1.基础























2.例题

1. 拓扑结构相同子树练习题







KMP算法及示例讲解:http://blog.csdn.net/bury_/article/details/79199228

import java.util.*;
//拓扑结构相同的子树判断,要求时间复杂度为O(n)
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}*/
public class IdenticalTree {
public boolean chkIdentical(TreeNode A, TreeNode B) {
//采用先序遍历的方法遍历并序列化树,有值则打印val!,空值则打印#!
String Astr=serilizeTree(A);
String Bstr=serilizeTree(B);
int len=Astr.length();
int lenP=Bstr.length();
char[] Aarray=Astr.toCharArray();
char[] Barray=Bstr.toCharArray();

//KMP算法计算序列化后的A是否包含B
//遍历长度为m的字符串,时间复杂度O(m)
return KMP(Aarray,Barray);
}
//str是待检测字符串,ptr是搜索的模式子串
public boolean KMP(char[] str,char[] ptr){
//计算模式子串的next数组
int[] next=cal_next(ptr);

int slen=str.length;
int plen=ptr.length;//子串的长度
int k
11145
=-1;
for(int i=0;i<slen;i++){
while(k>-1&&ptr[k+1]!=str[i]){
k=next[k];
}
if(ptr[k+1]==str[i]){
k=k+1;
}
if(k==(plen-1)){
//return i-lenp+1;
return true;
}
}
return false;
}
public String serilizeTree(TreeNode A){
Stack<TreeNode> stack=new Stack<TreeNode>();
stack.push(A);
String result=new String();
TreeNode cur;
while(!stack.isEmpty()){
cur=stack.pop();
if(cur==null){
result+="#!";
}else{
result+=cur.val+"!";
stack.push(cur.right);
stack.push(cur.left);
}
}
return result;
}

public int[] cal_next(char[] s){
int len=s.length;
int[] next=new int[len];
next[0]=-1;
int k=-1;//k表示s[0,k]字符串的最长前缀等于最长后缀时的最长前缀长度减去1
//遍历长度为n的子串,时间复杂度O(n)
for(int q=1;q<=(len-1);q++){
//如果下一个不同,那么k就变成next[k],注意next[k]是小于k的,无论k取任何值。
while(k>-1&&s[k+1]!=s[q]){
k=next[k];//往前回溯
}
if(s[k+1]==s[q]){
k=k+1;
}
//这个是把算的k的值(就是相同的最大前缀或最大后缀的长度减去1)赋给next[q]
next[q]=k;
}
return next;
}
}


2.变形词判断





import java.util.*;
//变形词判断
public class Transform {
public boolean chkTransform(String A, int lena, String B, int lenb) {
if(A==null||B==null||A.length()!=B.length()){
return false;
}
//对A建立哈希数组
int[] map=new int[256];//0-255是ASCII码对应的十进制编码
int lenA=A.length();
int lenB=B.length();
char[] Aarray=A.toCharArray();
char[] Barray=B.toCharArray();
for(int i=0;i<lenA;i++){
map[Aarray[i]]++;
}
//遍历B查询A的哈希数组,看是否对应
for(int i=0;i<lenB;i++){
if(map[Barray[i]]--==0){
return false;
}
}
return true;
}
}


3.两串旋转练习题

如果对于一个字符串A,将A的前面任意一部分挪到后边去形成的字符串称为A的旋转词。比如A=”12345”,A的旋转词有”12345”,”23451”,”34512”,”45123”和”51234”。对于两个字符串A和B,请判断A和B是否互为旋转词。

给定两个字符串A和B及他们的长度lena,lenb,请返回一个bool值,代表他们是否互为旋转词。

测试样例:

“cdab”,4,”abcd”,4

返回:true

import java.util.*;
public class Rotation {
public boolean chkRotation(String A, int lena, String B, int lenb) {
char[] Aarray=(A+A).toCharArray();
int[] next=cal_next(B);
char[] Barray=B.toCharArray();
int len=Aarray.length;
int lenB=B.length();
//使用KMP算法计算B是否包含在A+A中
int k=-1;
for(int i=0;i<len;i++){
while(k>-1&&Barray[k+1]!=Aarray[i]){
k=next[k];
}
if(Barray[k+1]==Aarray[i]){
k=k+1;
}
if(k==(lenB-1)){
//return i-lenp+1;
return true;
}
}
return false;
}
//计算next数组
public int[] cal_next(String str){
char[] s=str.toCharArray();
int len=str.length();
int[] next=new int[len];
next[0]=-1;
int k=-1;
for(int q=1;q<=(len-1);q++){
//如果下一个不同,那么k就变成next[k],注意next[k]是小于k的,无论k取任何值。
while(k>-1&&s[k+1]!=s[q]){
k=next[k];//往前回溯
}
if(s[k+1]==s[q]){
k=k+1;
}
//这个是把算的k的值(就是相同的最大前缀和最大后缀长)赋给next[q]
next[q]=k;
}
return next;
}
}


4.字符串逆序





方法一:使用split函数分离出单词

import java.util.*;
//字符串逆序
public class Reverse {
public String reverseSentence(String A, int n) {
String reverseA=reverse(A);
String[] words=reverseA.split(" ");
int len=words.length;
String result=new String();
for(int i=0;i<len;i++){
result+=reverse(words[i]);
if(i<len-1){
result+=" ";
}
}
return result;
}
//调整字符串为逆序
public String reverse(String s){
char[] a=s.toCharArray();
int len=a.length;
int left=0,right=len-1;
while(left<right){
char temp=a[left];
a[left]=a[right];
a[right]=temp;

left++;
right--;
}
return String.valueOf(a);
}
}


方法二:自动判断单词

import java.util.*;
//字符串逆序
public class Reverse {
public String reverseSentence(String A, int n) {
char[] a=A.toCharArray();
rotateWord(a);
return String.valueOf(a);
}
public void rotateWord(char[] a){
//整个字符串进行逆序
reverse(a,0,a.length-1);
//对单词再进行逆序
int left=-1,right=-1;//left指向单词的第一个,right指向单词最后一个
int len=a.length;
for(int i=0;i<len;i++){
if(a[i]!=' '){
left=i==0||a[i-1]==' '?i:left;
right=i==len-1||a[i+1]==' '?i:right;
}
//left和right分别指向了单词的第一个和最后一个时
if(left!=-1&&right!=-1){
reverse(a,left,right);
left=-1;
right=-1;
}
}
}
//调整字符串为逆序
public void reverse(char[] a,int start,int end){
while(start<end){
char temp=a[start];
a[start]=a[end];
a[end]=temp;

start++;
end--;
}
}
}


5.字符串移位





import java.util.*;
//原地字符串移位练习
public class Translation {
public String stringTranslation(String A, int n, int len) {
char[] a=A.toCharArray();
//将字符串0-(len-1)部分逆序
reverse(a,0,len-1);
//将字符串len到最后的部分逆序
reverse(a,len,a.length-1);
//将整个字符串逆序
reverse(a,0,a.length-1);

return String.valueOf(a);
}
//局部逆序操作
public void reverse(char[] a,int start,int end){
while(start<end){
char temp=a[start];
a[start]=a[end];
a[end]=temp;

start++;
end--;
}
}
}


6. 拼接最小字典序练习题

对于一个给定的字符串数组,请找到一种拼接顺序,使所有小字符串拼接成的大字符串是所有可能的拼接中字典序最小的。

给定一个字符串数组strs,同时给定它的大小,请返回拼接成的串。

测试样例:

[“abc”,”de”],2

“abcde”







import java.util.*;
//拼接最小字典序列
public class Prior {

public String findSmallest(String[] strs, int n) {
Arrays.sort(strs,new Comparator<String>(){
@Override
public int compare(String a,String b){
return (a+b).compareTo(b+a);
}
});
String result=new String();

for(int i=0;i<n;i++){
result+=strs[i];
}
return result;
}
}


7. 空格替换





import java.util.*;
//字符串空格替换
public class Replacement {
public String replaceSpace(String iniString, int length) {
//首先遍历字符串找到空格的数量以确定替换后的总长度
int space=0;
char[] s=iniString.toCharArray();
for(int i=0;i<length;i++){
if(s[i]==' '){
space++;
}
}
int total=length+2*space;//替换后的字符个数
char[] result=new char[total];
//将字符依次拷贝到后面的空间,遇到空格时替换为%20
for(int i=length-1,index=total-1;i>=0&&index>=0;i--,index--){
if(s[i]!=' '){
result[index]=s[i];
}else{
result[index--]='0';
result[index--]='2';
result[index]='%';
}
}

return String.valueOf(result);
}
}


直接使用StringBuilder

import java.util.*;
//字符串空格替换
public class Replacement {
public String replaceSpace(String iniString, int length) {
//将字符依次拷贝到后面的空间,遇到空格时替换为%20
StringBuilder sb=new StringBuilder();
for(int i=0;i<length;i++){
char c=iniString.charAt(i);
if(c==' '){
sb.append("%20");
}else{
sb.append(c);
}
}

return sb.toString();

}
}


8.合法括号判断



import java.util.*;
//合法括号串判断
public class Parenthesis {
public boolean chkParenthesis(String A, int n) {
int num=0;
Stack<String> stack=new Stack<String>();
for(int i=0;i<n;i++){
char c=A.charAt(i);
if(c=='('){
stack.push("(");
continue;
}
if(c==')'){
if(stack.isEmpty()==true||stack.pop()!="("){
return false;
}

}
}
return stack.isEmpty();
}
}


9.最长无重复子串











import java.util.*;
//最长无重复子串长度计算
public class DistinctSubstring {
public int longestSubstring(String A, int n) {
//哈希表map记录每种字符最近出现的位置
//pre记录当前字符的上一个字符串结尾的情况下,最长无重复字符子串的起始位置-1
int[] map=new int[256];
for(int i=0;i<256;i++){
map[i]=-1;
}
int max=0,pre=-1,temp=0;
for(int i=0;i<n;i++){
pre=Math.max(pre,map[A.charAt(i)]);
temp=i-pre;
max=Math.max(max,temp);
map[A.charAt(i)]=i;
}
return max;
}
}


3.JAVA实现tips

*     String的长度用length()
* “ ”双引号表示空字符串,‘ ’单引号表示空字符
* 字符数组转换成String,String.valueOf(char[] ch)
* compareTo()方法 http://www.runoob.com/java/number-compareto.html * StringBuilder() 增加字符串append("XXX")
* StringBuilder转换为String类型 toString()
* String获取字符元素 s.charAt(index)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: