1.给定两个字符串s1和s2,判定s2是否能够被s1循环移位得到的字符串包含
s1=ABCD,ABCD->BCDA->CDAB->DABC->ABCD
将前面移走的数据保留则
ABCD->ABCDA->ABCDAB->ABCDABC->ABCDABCD
S1循环移位的字符串都是s1s1的子字符串,只需要判断s1s1.subString(s2)若返回是-1则不包含
2.最少需要多少步可以把一个字符串A转换为另一个字符串B,有字符操作(替换,增加,删除)
分析:step <= n + m (可以通过删除把一个字符串变成空串再将其增加为另一个字符串)
将问题转换为较小的同样问题:如果A[1,2,...,n]和B[1,2,...,m]第一个字符串相同,只需要计算A[2,...,n]和B[2,...,m]的长度,如果第一个字符串不同:
1)修改A或B的第一个字符,然后计算A[2,...,n]和B[2,...,m]的长度;
2)删除A的第一个字符串或(添加A的第一个字符在B的第一个字符之前),然后A[2,...,n]和B[1,...,m]的长度
3)删除B的第一个字符串或(添加B的第一个字符在A的第一个字符之前),然后A[1,...,n]和B[2,...,m]的长度
递归代码:
public int CalculateSteps(String strA, int leftA, int rightA, String strB, int leftB, int rightB)
{
int minSteps = 0;
if (rightA == 0)
{
if (rightB == 0)
{
return 0;
}
else {
return rightB;
}
}
if (rightB == 0)
{
if (rightA == 0)
{
return 0;
}
else {
return rightA;
}
}
if (strA.charAt(leftA) == strB.charAt(leftB))
{
return CalculateSteps(strA, leftA + 1, rightA, strB, leftB + 1, rightB);
}
else {
int t1 = CalculateSteps(strA, leftA, rightA, strB, leftB + 1, rightB);
int t2 = CalculateSteps(strA, leftA + 1, rightA, strB, leftB, rightB);
int t3 = CalculateSteps(strA, leftA + 1, rightA, strB, leftB + 1, rightB);
int tmp = Math.min(t1, t2);
minSteps = Math.min(tmp, t3);
}
return minSteps;
}
3.替换字符串的空格:写一个函数,把字符串中的每个空格换成"%20"。时间复杂度要求O(N)
分析:先遍历一次字符串计算出空格的个数(O(N)),再扩大字符串的长度(O(N)),最后从字符串的由后往前复制,避免重复移位;
public static void replaceBlank(StringBuilder sb)
{
if ("".equals(sb) || sb == null)
{
return;
}
//遍历一次得到空格的数目O(n)
int numberOfBlank = 0;
int originalLength = sb.length();
for(int i = 0; i < originalLength; i++)
{
if (' ' == sb.charAt(i))
{
numberOfBlank++;
}
}
int newLength = originalLength + numberOfBlank * 2;
sb.setLength(newLength);//设置新的长度
int i = originalLength - 1, j = newLength - 1;//从后往前复制,避免重复移位
while(i >= 0 && j > i)//i = j 时没有空格
{
if (' ' == sb.charAt(i))
{
sb.setCharAt(j--, '0');
sb.setCharAt(j--, '2');
sb.setCharAt(j--, '%');
}
else {
sb.setCharAt(j--, sb.charAt(i));
}
i--;
}
}
4.字符串的排列:输入一个字符串,打印出该字符串中字符的所有排列。例如输入abc,输出abc,acb,bac,bca,cab,cba
分析:首先求所有可能出现出现在第一个位置的字符,即把第一个字符和后面所有的字符交换;第二步固定第一个字符,求后面所有字符的排列,如此递归下去
public void permutation(StringBuilder sb)
{
if (sb == null)
{
return;
}
permutation(sb, 0);
}
/**
* @param begin the first character
*/
private void permutation(StringBuilder sb, int begin)
{
if (begin == sb.length())
{
System.out.println(sb);
}
else
{
for(int i = begin; i < sb.length(); i++)
{
//交换i和begin的字符
char tmp = sb.charAt(i);
sb.setCharAt(i, sb.charAt(begin));
sb.setCharAt(begin, tmp);
permutation(sb, begin + 1);
//恢复i和begin的字符
tmp = sb.charAt(i);
sb.setCharAt(i, sb.charAt(begin));
sb.setCharAt(begin, tmp);
}
}
}
abc
a->b->c
->c->b
b->a->c
->c->a
c->a->b
->b->a
5.在字符串中找出第一个只出现一次的字符,如输入"abaccdeff",则输出‘b'
public char getFirstNotRepeatingChar(String str)
{
if (str == null)
{
return '\0';
}
HashMap<Character, Integer> map = new HashMap<Character, Integer>();//key存储字符,value存储次数
for (int i = 0; i < str.length(); i++)
{
if (map.containsKey(str.charAt(i)))
{
Integer value = map.get(str.charAt(i));
map.put(str.charAt(i), ++value);
}
else
{
map.put(str.charAt(i), 1);
}
}
for (int i = 0; i < str.length(); i++)//再遍历一次
{
if (map.get(str.charAt(i)) == 1)
{
return str.charAt(i);//第一次只出现一次的字符
}
}
return '\0';//不存在只出现一次的字符
}
6.翻转单词顺序,输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。例如输入"I am a student.",输出"student. a am I".
分析:两次翻转字符串,第一次翻转整个句子得到".tneduts a ma I",第二次翻转每个单词得到"student. a am I",以空格判断两个单词
public StringBuilder reverseSentence(StringBuilder sb)
{
if (sb == null)
{
return null;
}
reverse(sb, 0, sb.length() - 1);//翻转整个句子
int start = 0;
int end = sb.indexOf(" ");
while (end != -1)
{
reverse(sb, start, end - 1)//翻转每个单词
start = end + 1;//下一个单词的起始位置
end = sb.indexOf(" ", start);
}
return sb;
}
private void reverse(StringBuilder sb, int left, int right)// 翻转字符串
{
while (left < right)
{
char tmp = sb.charAt(left);
sb.setCharAt(left, sb.charAt(right));
sb.setCharAt(right, tmp);
left++;
right--;
}
}
7.字符串转换为整数
boolean invalid = false;// 无效输入变量
public int StrToInt(String str)//没有考虑溢出问题
{
int num = 0;
int start = 0;
if (str == null || "".equals(str))
{
invalid = true;
}
else
{
boolean minus = false;// 正负号
if (str.charAt(start) == '+')
{
start++;
}
else if (str.charAt(0) == '-')
{
start++;
minus = true;
}
num = StrToIntCore(str, minus, start);
}
return num;
}
private int StrToIntCore(String str, boolean minus, int start)
{
int num = 0;
for (int i = start; i < str.length(); i++)
{
if (str.charAt(i) >= '0' && str.charAt(i) <= '9')
{
int flag = minus ? -1 : 1;
num = num * 10 + flag * (str.charAt(i) - '0');
}
else
{
num = 0;
invalid = true;
break;
}
}
return num;
}