-
题目一:替换空格
【题目】
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
【思路】
注意题目是替换原来字符串
1.替换字符串2.先确定原字符串中空格数3.设置字符串长度4.从后往前遍历,进行替换
【解答】
public class Solution {
public String replaceSpace(StringBuffer str) {
int lengthOld=str.length();
int spaceNum=0;
for(int i=0;i<lengthOld;i++) { //空格个数
if(str.charAt(i)==' ') { //单引号表示字符
spaceNum++;
}
}
int lengthNew=lengthOld+spaceNum*2;
str.setLength(lengthNew);
int indexOld=lengthOld-1;
int indexNew=lengthNew-1;
for(;indexOld>=0 && indexOld<lengthNew;--indexOld) { //&& 短路与 从后往前遍历
if(str.charAt(indexOld)==' ') {
str.setCharAt(indexNew--, '0');
str.setCharAt(indexNew--, '2');
str.setCharAt(indexNew--, '%');
}else {
str.setCharAt(indexNew--, str.charAt(indexOld));
}
}
return str.toString();
}
}
-
题目二:正则表达式匹配
【题目】
请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配
【思路】
解这题需要把题意仔细研究清楚,反正我试了好多次才明白的。
首先,考虑特殊情况:
1>两个字符串都为空,返回true
2>当第一个字符串不空,而第二个字符串空了,返回false(因为这样,就无法
匹配成功了,而如果第一个字符串空了,第二个字符串非空,还是可能匹配成
功的,比如第二个字符串是“a*a*a*a*”,由于‘*’之前的元素可以出现0次,
所以有可能匹配成功)
之后就开始匹配第一个字符,这里有两种可能:匹配成功或匹配失败。但考虑到pattern
下一个字符可能是‘*’, 这里我们分两种情况讨论:pattern下一个字符为‘*’或
不为‘*’:
1>pattern下一个字符不为‘*’:这种情况比较简单,直接匹配当前字符。如果
匹配成功,继续匹配下一个;如果匹配失败,直接返回false。注意这里的
“匹配成功”,除了两个字符相同的情况外,还有一种情况,就是pattern
当前字符为‘.’,同时str的当前字符不为‘\0’。
2>pattern下一个字符为‘*’时,稍微复杂一些,因为‘*’可以代表0个或多个。
这里把这些情况都考虑到:
a>当‘*’匹配0个字符时,str当前字符不变,pattern当前字符后移两位,
跳过这个‘*’符号;
b>当‘*’匹配1个或多个时,str当前字符移向下一个,pattern当前字符
不变。(这里匹配1个或多个可以看成一种情况,因为:当匹配一个时,
由于str移到了下一个字符,而pattern字符不变,就回到了上边的情况a;
当匹配多于一个字符时,相当于从str的下一个字符继续开始匹配)
之后再写代码就很简单了。
【解答】
public class Solution{
public boolean match2(char[] str, int i,char[] pattern,int j)
{
//先特殊
if(i==str.length && j==pattern.length) { // 字符串和模式串都为空
return true;
}else if(str.length!=i && pattern.length==j) { // 模式串为空
return false;
}
//后一般
boolean next=(j+1<pattern.length && pattern[j+1]=='*'); // 模式串下一个字符是'*',j+1<=pattern.length?
if(!next) {
if(i<str.length && (pattern[j]==str[i]||pattern[j]=='.')) { //i<=str.length?
return match2(str,i+1,pattern,j+1);
}else {
return false;
}
}else {
if(i<str.length && (pattern[j]==str[i]||pattern[j]=='.')) {
return match2(str,i,pattern,j+2)||match2(str,i+1,pattern,j); //?
}else {
return match2(str,i,pattern,j+2);
}
}
}
public boolean match(char[] str, char[] pattern) {
return match2(str,0,pattern,0); //接收参数
}
}
-
题目三:表示数值的字符串
【题目】
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。
【思路】
正则
【解答】
public class Solution {
public boolean isNumeric(char[] str) {
String str1=str.toString();
//String regex1="(\\.\\d+)?(e\\d)*(\\dE)*"; //(e\\d)*(\\dE)-->([eE][\\+\\-]?\\d+)?
//String regex2="((+-)|(-+))"; //((+-)|(-+)) -->[\\+\\-]?
String regex="[\\+\\-]?\\d*(\\.\\d+)?([eE][\\+\\-]?\\d+)?";
以下对正则进行解释:
[\\+\\-]? -> 正或负符号出现与否
\\d* -> 整数部分是否出现,如-.34, +3.34均符合
(\\.\\d+)? -> 如果出现小数点,那么小数点后面必须有数字;
否则一起不出现
([eE][\\+\\-]?\\d+)? -> 如果存在指数部分,那么e或E肯定出现,+或-可以不出现,
紧接着必须跟着整数;或者整个部分都不出现
if(str1.matches(regex)) {
return true;
}else {
return false;
}
}
}
-
题目四:字符流中第一个不重复的字符
【题目】
请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。
【思路】
使用int[ ]的下标或者hash 标记字符出先的次数
使用队列(先进先出),对字符出现的顺序进行判断
【解答】
import java.util.LinkedList;
import java.util.Queue;
public class Solution{
//Insert one char from stringstream
int[] charCnt=new int[128]; //ASCII字符最多也就128个,用它的下标
Queue<Character> queue=new LinkedList<Character>();
int i=0;
public void Insert(char ch)
{
if(charCnt[ch]++ ==0) { //对应的索引位置,若charCnt[ch]!=0后,对应位置也会++
queue.add(ch);
}
}
//return the first appearence once char in current stringstream
public char FirstAppearingOnce()
{
Character CHAR=null;
char c=0;
while((CHAR=queue.peek())!=null) { //判断队列不是空的
c=CHAR.charValue();
if(charCnt[c]==1) {
return c;
}else {
queue.remove();
}
}
return '#';
}
}