面试题(一)-------面试中常见的字符串类型题目及思路解答

1.左旋转字符串

题目描述:

        定义字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部。如把字符串 abcdef 左旋转 2 位得到字符串 cdefab。请实现字符串左旋转的函数,要求对长度为 n 的字符串操作的时间复杂度为 O(n),空间复杂度为 O(1)。

编程之美上有这样一个类似的问题,咱们先来看一下:

设计一个算法,把一个含有 N 个元素的数组循环右移 K 位,要求时间复杂度为 O(N), 且只允许使用两个附加变量。

	/**
	 * 交换两个字符
	 * @param pStr
	 * @param startIndex
	 * @param endIndex
	 */
	public void swap(char[] pStr, int startIndex, int endIndex){

		if(pStr != null || pStr.length > 0 || startIndex < endIndex){
			char temp = pStr[startIndex];
			pStr[startIndex] = pStr[endIndex];
			pStr[endIndex] = temp;
		}
		
	}

	/**
	 * 逆转字符串中的每个字符
	 * @param pStr
	 * @param startIndex
	 * @param endIndex
	 */
	public void reverseString(char[] pStr, int startIndex, int endIndex){

		if(pStr != null || pStr.length > 0 || startIndex < endIndex){
			while(startIndex < endIndex){
				swap(pStr, startIndex, endIndex);
				startIndex++;
				endIndex--;
			}
		}

	}

	/**
	 * 
	 * 做旋转字符串
	 * 
	 * @param pStr
	 * 		需要处理的字符串
	 * @param leftRotateSteps
	 * 		左转的步数
	 */
	public void leftRotate(char[] pStr, int leftRotateSteps){

		if(pStr.length >= 0 || pStr != null || 
				leftRotateSteps > 0 || leftRotateSteps <= pStr.length-1){
			int xStartIndex = 0;
			int xEndIndex = leftRotateSteps - 1;
			int yStartIndex = leftRotateSteps;
			int yEndIndex = pStr.length - 1;
			reverseString(pStr, xStartIndex, xEndIndex);
			reverseString(pStr, yStartIndex, yEndIndex);
			reverseString(pStr, 0, pStr.length-1);
		}

	} 

2.替换空格

题目:请实现一个函数,把字符串中的每个空格替换成“%20”。例如输入“We are happy.”,则输出”We%20are%20happy”。

思路扩展题目:有两个排序的数组A1和A2,内存在A1的末尾有足够多的空余空间容纳A2。请实现一个函数,把A2中的所有数字插入到A1中并且所有的数字是排序的

3.字符串的排列

题目:输入一个字符串,打印出该字符串中字符的所有排列。例如,输入字符串abc, 则打印出由字符串a,b,c所能排列出的所有字符串abc,acb,bac,bca,cab和cba。

public void swap(char[] str, int startIndex, int endIndex){
		if(startIndex == endIndex)
			return;
		char temp = str[startIndex];
		str[startIndex] = str[endIndex];
		str[endIndex] = temp;
	}
	
	/**
	 * 对字符串进行全排列
	 * @param str
	 * @param startIndex
	 */
	public void permutation(char[] str, int startIndex){  
		if(str == null || startIndex < 0 || startIndex > str.length){  
			return;  
		}  
		if( startIndex == str.length ){  
			System.out.println(new String(str));  
		}else{  
			for(int j = startIndex; j < str.length; j++){  
				//交换前缀,使之产生下一个前缀  
				swap(str, startIndex, j);
				permutation(str, startIndex+1);  
				//将前缀换回来,继续做上一个的前缀排列.  
				swap(str, startIndex, j);
			}  
		}  
	}  

3.字符串的组合问题

基本思路:1.将当前选中的字符放入组合中:则在n-1个字符中选择m-1个字符                   2.不把但前选中的字符放入组合中:则在剩下的n-1个字符中选择m个字符

/**
	 * 
	 * 字符串的组合问题
	 * @param chs
	 * 
	 */
	public static void combiantion(char chs[]){  
		if(chs==null || chs.length==0){  
			return ;  
		}  
		List<Character> list=new ArrayList();  
		for(int i=1; i <= chs.length; i++){  
			combine(chs,0,i,list);  
		}  
	}  
	
	/**
	 * 
	 * @param cs
	 *        处理的字符串
	 * @param begin
	 * 		  字符串开始座标
	 * @param number
	 * 		  字符串长度
	 * @param list
	 */
	//从字符数组中第begin个字符开始挑选number个字符加入list中  
	public static void combine(char[] cs, int begin, int number, List<Character> list){  
		if(number==0){  
			System.out.println(list.toString());  
			return ;  
		}  
		if(begin==cs.length){  
			return;  
		}  
		list.add(cs[begin]);  
		//字符放入组合中,则在n-1个字符分中选择number-1个字符
		combine(cs,begin+1,number-1,list);
		
		list.remove((Character)cs[begin]);  
		//字符不放入组合中,则在n-1个字符中选择number个字符
		combine(cs,begin+1,number,list);  
	}  

4.字符串包含问题

题目:假设这有一个各种字母组成的字符串A,和另一个字符串B,字符串里B的字母相对少一些。什么方法能最快查出所有小字符串B里的字母在大字符串A里都有?

比如, 如果是下面两个字符串:

String 1: ABCDEFGHLMNOPQRS
String 2:DCGSRQPO
答案是true

算法设计思想:因为只存在大写字母,故只需定义一个存储26个不同字母的HashMap进行存储。时间复制度为O(m+n)其中m,n为两个字符串的长度

	/**
	 * 判断是否短字符串包含于长字符串
	 * @param longStr
	 * @param shortStr
	 * @return
	 */
	public boolean isContain(String longStr, String shortStr){

		//判断字符串是否符合规范!
		if(longStr == null || shortStr == null || 
				shortStr.length() <= 0 || longStr.length() <= shortStr.length())
			return false;
		
		//设置26个字母
		Map strMap = new HashMap(26);
		int num = 0;
		
		//用HashMap记录短字符串中出现的所有字符,并用num记录出现的个数
		for(int i = 0; i < shortStr.length(); i++){
			if(!strMap.containsKey(shortStr.charAt(i))){
				strMap.put(shortStr.charAt(i), 1);
				num++;
			}
		}
		
		//统计HashMap中是否有存储长字符串中的字符。
		for(int i = 0; i < longStr.length(); i++){
			if(strMap.containsKey(longStr.charAt(i))){
                               num--;
			}
		}
		
		//如果num重新置为0,表示包含
		if(num == 0){
			return true;
		}else{
			return false;
		}
		
	}

思路扩展1:在字符串中查找子串

题目描述:
给定一个字符串 A,要求在 A 中查找一个子串 B。
如 A=”ABCDF”,要你在 A 中查找子串 B=“CD”。

思路扩展2:字符串匹配问题

题目描述:
假设两个字符串中所含有的字符和个数都相同我们就叫这两个字符串匹配,
比如:abcda 和 adabc,
由于出现的字符个数都是相同,只是顺序不同,所以这两个字符串是匹配的。

5.在一个字符串中找到第一个只出现一次的字符

如输入 abaccdeff,则输出 b

	public char firstNotRepeatChar(String pStr){

		if(pStr == null || pStr.length() <= 0)
			return '\0';

		Map<Character, Integer> charMap = new HashMap<Character, Integer>(256);
		for(int i = 0; i < pStr.length(); i++){
			char c = pStr.charAt(i);
			if(charMap.containsKey(c)){
				int num = charMap.get(c);
				charMap.put(c, ++num);
			}else{
				charMap.put(c, 1);
			}
		}
		Character result = null;
		//注意这种递归方式非常新颖
		//但是递归效果近似到序!
		for(Character key: charMap.keySet()){
			Integer value = charMap.get(key);
			if(value == 1)
				result = key;
		}

		return result;
	}

6.字符串转换为整数

题目:输入一个表示整数的字符串,把该字符串转换成整数并输出。
例如输入字符串”345″,则输出整数 345。

7.字符串拷贝

点赞