一:字符串空格替换
将字符串中的空格全部替换为“%20”。假定该字符串后面有足够的空间存放新增的字符。
如:Mr John Smith—>Mr%20John
陷阱:Java玩家可能第一时间想到用split(" ")分割原字符串,然后重新拼接的时候在词间添加“%20”。这种思路的不完善之处在于:如果原字符串以空格结尾、或者单词之间不止一个空格,则会导致拼接出来的字符串不符合要求。
解法:该题说明原字符串后面有足够空间(Java玩家可忽略,因为改变字符串都是新开的空间了),所以题目本意是要我们在原字符串基础上进行挪动、替换。
(但是,在原字符串基础上进行挪到,太麻烦了!作为Java玩家,应好好利用String对象的+运算符的特性!)
public String replaceSpace(String iniString, int length) { //初始化结果字符串 String str=""; //把原字符串转为字符数组,使得可以用下标遍历 char[] iniStringArray=iniString.toCharArray(); //遍历 for(int i=0;i<length;++i){ //遍历到一个空格,结果字符串就拼接"%20" if(iniStringArray[i]==' '){ str+="%20"; }else{ //不是空格,就把字符添加到结果字符串 str+=iniStringArray[i]; } } return str; }
二:合法括号序列判断
给定一个字符串A和它的长度n,请返回一个bool值代表它是否为一个合法的括号串(即:()是否能合法、有效地匹配)
思路:我们模拟这个括号序列的生成过程:左右往右开始书写这个括号串,发现一个规律:遍历过程中的任一时刻,一旦 ) 个数大于 ( 个数,则序列非法;当序列遍历到结尾时刻,( 个数 与 ) 刚好相等,则序列合法。
public boolean chkParenthesis(String A, int n) { //字符串问题数组化 char[] chars=A.toCharArray(); //操作数组,统计左右括号个数 int left=0; int right=0; for(char ch:chars){ if(ch=='(') left++; if(ch==')') right++; if(right>left) return false; } if(right==left){ return true; }else{ return false; } }
三:最长无重复字符子串
给定一个字符串A及它的长度n,请返回它的最长无重复字符子串长度。
思路:这道题,模拟字符串A从左往右拼写过程,用map记录每个字符。当拼写到一个已出现过的字符时,则其上次出现的位置到该字符之前为一个无重复字符子串,统计长度并更新当前无重复子串长度最大值;同时,更新该重复字符的最新下标,并移动子串生成起点为原起点+1(因为原起点已出现了重复),继续拼写......直到拼写完毕,则可得到最大值。
(解题金句:从字符串中寻找某种性质的子串问题,与从二叉树中寻找某种性质的子树相类似,解题思路为从头到尾模拟拼写字符串的过程,对拼写过程中的每一个字符,进行性质判断,更新相关信息。当拼写到结尾时,记录下的信息即为所求。)
public static int longestSubstring(String A, int n) { //字符串数组化 char[] chars=A.toCharArray(); //记录当前最长无重复子串长度 int len=0; //记录当前拼写的字符上一次出现的下标 Map<Character,Integer> map=new HashMap<Character,Integer>(); //记录当前拼写的无重复子串的起始位置 int start=0; for(int i=0;i<n;++i){ //若当前拼写字符出现过,并且在当前拼写子串起点的右侧,则说明当前拼写的子串已出现重复字符 if(map.get(chars[i])!=null && map.get(chars[i])>=start){ //则下一拼写的无重复子串从当前重复字符上一次出现的位置右移一位重新开始拼写 start=map.get(chars[i])+1; map.put(chars[i],i);//更新当前字符位置 }else{ map.put(chars[i],i); len=Math.max(len,i-start+1);//如果当前字符没出现过,则计算当前拼写的无重复子串的长度并与此前记录下的最大长度比较,更新最大长度记录 } } return len; }