读书笔记之《程序员代码面试指南(字符串问题)》
字符串问题也是老生常谈的算法问题,该书罗列的字符串问题以我做算法的经验来看,都是很好的题。
判断两个字符串是否互为变形词
给定两个字符串str1和str2,如果str1和str2中出现的字符种类一样且每种字符出现的次数也一样,那么str1和str2互为变形词。请实现函数判断两个字符串是否互为变形词。
str1="123",str2="231",返回true。
str1="123",str2="2331",返回false。
先判断长度是不是一致
再用一个长度为256的数组标记,一个加,一个减。最后看是不是互抵了。
package String;
/**
* Created by zdmein on 2017/9/1.
* 判断两个字符串是否互为变形词
* 给定两个字符串str1和str2,如果str1和str2中出现的字符种类一样且每种字符出现的次数也一样,
* 那么str1和str2互为变形词。请实现函数判断两个字符串是否互为变形词。
str1="123",str2="231",返回true。
str1="123",str2="2331",返回false。
*/
public class isDeformation1 {
public static void main(String args []){
String str1="54s6";
String str2="465d";
System.out.println(isDeformation(str1,str2));
}
public static boolean isDeformation(String str1 ,String str2){
if(str1.length()!=str2.length()){
return false;
}
int res[]=new int [256];
int index=0;
while (index!=str1.length()){
res[str1.charAt(index)]++;
res[str2.charAt(index++)]--;
}
for(int i=0;i<256;i++){
if(res[i]!=0){
return false;
}
}
return true;
}
}
字符串的调整与替换
*把 "a b c" 替换后为 “a%20b%20%20c”
开辟空间,从尾部遍历替换到头部
package String;
/**
* Created by zdmein on 2017/9/1.
* 字符串的调整与替换
*把 "a b c" 替换后为 “a%20b%20%20c”
*/
public class replace1 {
public static void main(String [] args ){
String str="a b c";
char chas[]=new char[20];
for(int i=0;i<str.length();i++){
chas[i]=str.charAt(i);
}
replace(chas);
}
public static void replace(char [] chas){
int len=0;
int num=0;
for(;len<chas.length && chas[len]!=0;len++){
if(chas[len]==' '){
num++;
}
}
int index=len+num*2;
for(;index>=0;index--){
if (chas[len--]==' '){
chas[index--]='0';
chas[index--]='2';
chas[index]='%';
}else {
chas[index]=chas[len+1];
}
}
System.out.println(chas);
}
}
扩展:
只含有数字字符和“”字符的字符类型数组,把数字字符挪到右边, *挪到左边
12**35
**1235
package String;
/**
* Created by zdmein on 2017/9/1.
* 只含有数字字符和“”字符的字符类型数组,把数字字符挪到右边, *挪到左边
12**35
**1235
*/
public class replace2 {
public static void main(String [] args ){
String str="12**35";
char chas[]=new char[20];
for(int i=0;i<str.length();i++){
chas[i]=str.charAt(i);
}
modify(chas);
}
public static void modify(char [] chas){
if(chas==null||chas.length==0){
return;
}
int j=chas.length-1;
for(int i=chas.length-1;i>=0;i--){
if(chas[i]!='*'){
chas[j--]=chas[i];
}
}
for(;j>=0;j--){
chas[j]='*';
}
System.out.println(chas);
}
}
翻转字符串
写一个函数,将字符串翻转,翻转方式如下:“I am a student”反转成“student a am I”,不借助任何库函数。
写个函数,先整体翻转一次,然后再每个单词翻转一次。easy!
package String;
/**
* Created by zdmein on 2017/9/2.
* 翻转字符串
* 写一个函数,将字符串翻转,翻转方式如下:“I am a student”反转成“student a am I”,不借助任何库函数。
*/
public class rotateWord1 {
public static void main(String [] args){
String str= "dogs love pig.";
rotateWord(str);
}
public static void rotateWord(String str){
if(str==null||str.length()==0){
return ;
}
char [] strArr = str.toCharArray();
reverse(strArr,0,strArr.length-1);
int index=0;
for(int i=0;i<strArr.length;i++){
if(strArr[i]==' '){
reverse(strArr,index,i-1);
index=i+1;
}
}
reverse(strArr,index,strArr.length-1);
System.out.println(strArr);
}
public static void reverse(char[] strArr ,int first ,int end){
while (first<end){
char tmp=strArr[first];
strArr[first]=strArr[end];
strArr[end]=tmp;
first++;
end--;
}
}
}
数组中两个字符串的最小距离
-
Assume that words = ["practice", "makes", "perfect", "coding", "makes"].
-
Given word1 = “coding”, word2 = “practice”, return 3.
-
Given word1 = "makes", word2 = "coding", return 1.
用2个下标指向2个字符串,跟新位置,互相减,然后Math.min取小的。
package String;
/**
* Created by zdmein on 2017/9/3.
* 数组中两个字符串的最小距离
*Assume that words = ["practice", "makes", "perfect", "coding", "makes"].
* Given word1 = “coding”, word2 = “practice”, return 3.
* Given word1 = "makes", word2 = "coding", return 1.
*/
public class minDistance1 {
public static void main(String args[]){
String [] strs ={"1","3","3","3","2","3","1"};
String str1="1";
String str2="2";
minDistance(strs,str1,str2);
}
public static void minDistance(String[] strs,String str1 , String str2){
if(strs==null||strs.length==0||str1==null||str2==null){
return;
}
int index1=-1;
int index2=-1;
int min=Integer.MAX_VALUE;
for(int i=0;i<strs.length;i++){
if(strs[i]==str1){
index1=i;
if(index2!=-1){
min=Math.min(min,index1-index2);
}
}else if(strs[i]==str2){
index2=i;
if(index1!=-1){
min=Math.min(min,index2-index1);
}
}
}
//
if(min!=Integer.MAX_VALUE){
System.out.println(min);
}else {
System.out.println(-1);
}
//上面这个渣渣代码可以这样写:
// min==Integer.MAX_VALUE ? -1 : min;
}
}
替换字符串中连续出现的指定字符串
题目:
给定单个字符串str、from和to,已知from字符串中无重复字符,把str中所有from的子串全部替换成to字符串,对连续出现from的部分要求只替换成一个to字符串,返回最终结果字符串。
举例:
str="123abc",from="abc",to="4567",返回"1234567";
str="123",from="abc",to="4567",返回"123";
str="123abcabc",from="abc",to="X",返回"123X";
思路:
把from匹配的字符,设为0,然后把0的部分全部替换掉成to,就好了
package String;
/**
* Created by zdmein on 2017/9/4.
* 替换字符串中连续出现的指定字符串
题目:
给定单个字符串str、from和to,已知from字符串中无重复字符,把str中所有from的子串全部替换成to字符串,对连续出现from的部分要求只替换成一个to字符串,返回最终结果字符串。
举例:
str="123abc",from="abc",to="4567",返回"1234567";
str="123",from="abc",to="4567",返回"123";
str="123abcabc",from="abc",to="X",返回"123X";
*/
public class replace3 {
public static void main(String args[]){
String str="123abcabc";
String from="abc";
String to = "4567";
System.out.println(replace(str,from,to));
}
private static String replace(String str,String from ,String to){
if(str==null||from==""||to==""){
return str;
}
char[] chstr=str.toCharArray();
char[] chfrom=from.toCharArray();
int match=0;
for(int i=0;i<str.length();i++){
if(chstr[i]==chfrom[match++]){
if(match==chfrom.length){
clear(chstr,i,chfrom.length);
match=0;
}
}else {
match=0;
}
}
String res="";
for(int i=0;i<chstr.length;i++){
if(chstr[i]!=0){
while (chstr[i]!=0){
res+=chstr[i++];
}
}
if(chstr[i]==0){
while (i!=chstr.length&&chstr[i]==0){
i++;
}
res+=to;
i--;
}
}
return res;
}
private static void clear(char[] chstr , int end ,int len){
while(len--!=0){
chstr[end--]=0;
}
}
}
字符串的统计字符串
统计字符串中每个字符的出现频率,返回一个字符串统计,key 为统计字符,value 为出现频率
输入:
aaabbadddffc
输出:
a_3_b_2_a_1_d_3_f_2_c_1
先记录a,然后一项一项对比记录
String.valueof()的使用
package String;
/**
* Created by zdmein on 2017/9/5.
* 字符串的统计字符串
统计字符串中每个字符的出现频率,返回一个字符串统计,key 为统计字符,value 为出现频率
输入:
aaabbadddffc
输出:
a_3_b_2_a_1_d_3_f_2_c_1
*/
public class getCountString1 {
public static void main(String [] args){
String str="aaabbadddffc";
System.out.println(getCountString(str));
}
private static String getCountString(String str){
if(str==null||str.length()==0){
return "";
}
char [] chs=str.toCharArray();
String res=String.valueOf(chs[0]);
int num=1;
for(int i=1;i<str.length();i++){
if(chs[i]==chs[i-1]){
num++;
}else {
res=res+"_"+String.valueOf(num)+"_"+String.valueOf(chs[i]) ;
num=1;
}
}
return res+"_"+String.valueOf(num)+"" ;
}
}
判断两个字符串是否互为旋转词
题目:
如果一个字符串str,把字符串str前面任意的部分挪到后面形成的字符串叫做str的旋转词。
如str="12345",str的旋转词有"12345"、"23451"、"34512"、"45123"、"51234"。
给定两个字符串a和b,请判断a和b是否互为旋转词。
举例:
a="cdab",b="abcd",返回true;
a="1ab2",b="ab12",返回false;
a="2ab1",b="ab12",返回true。
要求:
如果a和b长度不一样,那么a和b必然不互为旋转词,可以直接返回false。
当a和b长度一样,都为N时,要求解法的时间复杂度为O(N)。
package String;
/**
* Created by zdmein on 2017/9/6.
*/
public class isRotation {
public boolean isRotation(String a ,String b){
if(a==null||b==null||a.length()!=b.length()){
return false;
}
String b2=b+b;
return KMP(b2,a)!=-1; // KMP算法
}
public static int KMP(String source , String pattern){
// int [] N=getN(pattern);
return -1;
}
}
判断是不是整体有效的括号字符串
package String;
import java.util.Scanner;
/**
* Created by zdmein on 2017/9/18.
* 判断是不是整体有效的括号字符串
* 括号字符串的有效性和最长有效长度
*/
public class isValid1 {
public static void main(String [] args){
Scanner cin=new Scanner(System.in);
String str=cin.next();
System.out.println(isValid(str));
}
public static boolean isValid(String str){
if(str==null ||str.equals("")){
return false;
}
char [] chs=str.toCharArray();
int status=0;
for(int i=0;i<str.length();i++){
if(chs[i]!=')'&&chs[i]!='('){
return false;
}
if(chs[i]==')'&&--status<0){
return false;
}
if(chs[i]=='('){
status++;
}
}
return status==0;
}
}