请实现一个函数,将一个字符串中的空格替换成 “%20”。例如,当字符串为 We Are Happy. 则经过替换之后的字符串为 We%20Are%20Happy。
/**
* @author Think
* @since 2016-12-19 11:18:00
*/
public class Solution {
public String replaceSpace(StringBuffer str) {
int tar = 32;
String des = "%20";
StringBuffer reStr = new StringBuffer();
for (int i=0;ichar c = str.charAt(i);
if (tar == c){
reStr.append(des);
}else {
reStr.append(c);
}
}
return reStr.toString();
}
public static void main(String[] args) {
StringBuffer in = new StringBuffer("We Are Happy");
System.out.println(new Solution().replaceSpace(in));
}
}
剑指Offer书本中的题目要求入参格式不一样,因此实现方法也不一样。
void ReplaceBlank(char string[], int length){
//TODO
}
就需要从后往前,逐字节移动替换字符。
public class Solution {
public static void main(String[] args) {
int length = 20;
char[] string = new char[length];
String str = "We are happy";
for (int i = 0; i < str.length(); i++) {
string[i] = str.charAt(i);
}
int pos = 0;
while (string[pos]!='\0'){
System.out.print(string[pos++]);
}
System.out.println();
Solution solution = new Solution();
solution.ReplaceBlank(string, length);
pos = 0;
while (string[pos]!='\0'){
System.out.print(string[pos++]);
}
}
public void ReplaceBlank(char[] string, int length) {
if (string == null || length <= 0) {
return;
}
int originalLength = 0;
int numberOfBlank = 0;
int i = 0;
while (string[i] != '\0') {
originalLength++;
if (string[i] == ' ') {
numberOfBlank++;
}
i++;
}
int newLength = originalLength + 2 * numberOfBlank;
// length为原始字符串数组的长度,如果替换后的总长度newLength超过length,则肯定无法替换成功。
if (newLength > length) {
return;
}
int indexOdOriginal = originalLength;
int indexOfNew = newLength;
while (indexOdOriginal >= 0 && indexOfNew > indexOdOriginal) {
if (string[indexOdOriginal] == ' ') {
string[indexOfNew--] = '0';
string[indexOfNew--] = '2';
string[indexOfNew--] = '%';
} else {
string[indexOfNew--] = string[indexOdOriginal];
}
indexOdOriginal--;
}
}
}
请实现一个函数用来匹配包括’.’和’*’的正则表达式。模式中的字符’.’表示任意一个字符,而’*’表示它前面的字符可以出现任意次(包含 0 次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串 “aaa” 与模式 “a.a” 和 “ab*ac*a” 匹配,但是与 “aa.a” 和 “ab*a” 均不匹配。
public class Solution {
public static void main(String[] args) {
char[] s = "aa".toCharArray();
char[] patten = "a*".toCharArray();
Solution solution = new Solution();
boolean result = solution.match(s, patten);
System.out.println(result);
}
public boolean match(char[] str, char[] pattern) {
if (str == null || pattern == null) {
return false;
}
int i = 0, j = 0;
return matchTwo(str, i, pattern, j);
}
// 注意出现""/"."/"*"/".*"/a*a等情况,需要随时判断数组是否越界。
boolean matchTwo(char[] str, int i, char[] pattern, int j) {
int len1 = str.length;
int len2 = pattern.length;
// 如果Str和pattern匹配字符均已经到达末尾,则匹配成功。
if (i == len1 && j == len2) {
return true;
}
// 如果str还没结束,而pattern已经匹配结束,则匹配失败。
// 另一方面,如果str已经结束,而pattern位结束,不能判断匹配失败。
// 如:pattern以*结尾,可以匹配0位。
if (i < len1 && j == len2) {
return false;
}
// 首先判断pattern的后一位是不是*:*会影响pattern前一位的判断。
// - 如果第二位是*,分一下几类。
// 1 匹配0位,则pattern后移2位。
// 2 字符串匹配1位成功,继续匹配下一位,pattern因为*存在,j不变;
// 3 只匹配1位,pattern后移2位。
// 说实话,2和3非常相似。而且个人感觉有些情况同时适用于2和3,
// 但可能只有一返回true,又因为通过||连接,从而结果为真。
// 求明确清晰的解析,点拨迷雾。
// 通过(j+1)
if ((j + 1) < len2 && pattern[j + 1] == '*') {
if ((i < len1 && pattern[j] == '.') || (i < len1 && str[i] == pattern[j])) {
return matchTwo(str, i, pattern, j + 2) ||
matchTwo(str, i + 1, pattern, j) ||
matchTwo(str, i + 1, pattern, j + 2);
} else {
return matchTwo(str, i, pattern, j + 2);
}
} else {
if ((i < len1 && pattern[j] == '.') || (i < len1 && str[i] == pattern[j])) {
return matchTwo(str, i + 1, pattern, j + 1);
} else {
return false;
}
}
}
}
请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符”go”时,第一个只出现一次的字符是”g”。当从该字符流中读出前六个字符“google”时,第一个只出现一次的字符是”l”。
这里的256是按照《剑指Offer》中说的8位的char类型。
public class Solution {
public static void main(String[] args) {
Solution solution = new Solution();
// String str = "google";
// String str = "";
// String str = "aabbcc";
String str = "think";
for (int i=0;iint charTable[] = new int[256];
StringBuffer sb = new StringBuffer();
//Insert one char from stringstream
public void Insert(char ch) {
sb.append(ch);
if (ch >= 256) {
return;
}
charTable[ch]+=1;
}
//return the first appearence once char in current stringstream
public char FirstAppearingOnce() {
char defaultCh = '#';
char charStr[] = sb.toString().toCharArray();
for (int i=0;iif (charTable[charStr[i]]==1){
return charStr[i];
}
}
return defaultCh;
}
}
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串 “+100”,”5e2”,”-123”,”3.1416” 和 “-1E-16” 都表示数值。 但是 “12e”,”1a3.14”,”1.2.3”,”+-5” 和 “12e+4.3” 都不是。
枚举方式,很多个if嵌套,感觉不是很好。很冗长。不过确实可以体现解题思路。
public class Solution {
public static void main(String[] args) {
Solution solution = new Solution();
// True for: "+100","5e2","-123","3.1416" and "-1E-16"
// False for: "12e","1a3.14","1.2.3","+-5" and "12e+4.3"
// Other test case: +.123, 1+23,
char[] str = "1+23".toCharArray();
System.out.println(solution.isNumeric(str));
}
public boolean isNumeric(char[] str) {
int numOfPoint = 0;
if (str == null) {
return false;
}
int index = 0;
if (str[index] == '+' || str[index] == '-') {
index = 1;
if (!isNumber(str[index]) && str[index] != '.') {
return false;
}
}
for (int i = index; i < str.length; i++) {
if (str[i] == 'e' || str[i] == 'E') {
if ((i + 1) < str.length && (str[i + 1] == '+' || str[i + 1] == '-') && (i + 2) < str.length && isNumber(str[i + 2])) {
index = i + 3;
break;
} else if ((i + 1) < str.length && isNumber(str[i + 1])) {
index = i + 2;
break;
} else {
return false;
}
} else if (str[i] == '.') {
numOfPoint++;
if (numOfPoint > 1) {
return false;
}
} else {
if (!isNumber(str[i])) {
return false;
}
}
index = i;
}
for (int i = index; i < str.length; i++) {
if (!isNumber(str[i])) {
return false;
}
}
if (numOfPoint > 1) {
return false;
}
return true;
}
public boolean isNumber(char ch) {
if (ch < '0' || ch > '9') {
return false;
} else {
return true;
}
}
}
看到有人的解题方法是使用Double.parseDouble(new String(str));方法,感觉不是很好,如果字符串表示的数值范围超出了Double呢?!
public class Solution {
public boolean isNumeric(char[] str) {
String s=String.valueOf(str);
//return s.matches("[+-]?[0-9]*(.[0-9]*)?([eE][+-]?[0-9]+)?");
return s.matches("[+-]?[0-9]*(\\.[0-9]*)?([eE][+-]?[0-9]+)?");
}
}
简洁、简单明了。
有人提到可以使用“编译原理中自动机”实现,思路条理清晰,赞。
注意上述几个问题的边界问题处理方式。null、空字符串、不符合要求的、符合要求的、多重符合题目要求的,均可以自己写出相应的字符串进行测试,防止程序出现异常而崩溃。
题目简单并不意味着代码简单。