字符串面试笔试题

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;
	}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值