2.String
1.Implement strStr()
Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.
思路一:直接两个指针,暴力法
public class Solution {
//success 1
public int strStr(String haystack, String needle) {
//haystack长度必须大
if(haystack.length()<needle.length()){
return -1;
}
if(needle.isEmpty()){
return 0;
}
for (int i = 0; i < haystack.length(); i++) {
for(int j=0;j<needle.length();j++){
//保证charAt(i+j)不越界
if(i+j>=haystack.length()){
return -1;
}
if(haystack.charAt(i+j)==needle.charAt(j)){
if(j==needle.length()-1){
return i;
}
continue;
}else{
break;
}
}
}
return -1;
}
//success 2
//方法1的简洁版
// public int strStr(String haystack, String needle) {
// for (int i = 0; ; i++) {
// for (int j = 0; ; j++) {
// if (j == needle.length()) return i;
// if (i + j == haystack.length()) return -1;
// if (needle.charAt(j) != haystack.charAt(i + j)) break;
// }
// }
// }
}
思路二:可以用KMP子字符串比对算法。
下面我们先来复习一下KMP算法,参考(KMP) Pattern Matching(Substring search)实现之,使上面暴力算法的时间复杂度从O(M×N)
降至O(M+N)
,主要思路是借助了一个辅助数组,避免了每次比对不成功时都从pattern数组最起始位置重新比较,主要原理是找到了pattern中的一个字符串,这个字符串的特征是prefix跟suffix相等,那么我们可以直接从prefix的下一个元素开始比较,在最开始pattern已知,所以我们可以通过某些方法预先存储pattern中字符串重复的形式,patternPrehandle就是干这个事儿的,针对pattern的形式肯定是要预先处理并储存的嘛,不然效率跟不上:
//success 3
//kmp的实现,参考https://www.youtube.com/watch?v=GTJr8OvyEVQ
public class Solution {
public int strStr(String haystack, String needle) {
char[] haystackArray = haystack.toCharArray();
char[] needleArray = needle.toCharArray();
//haystack长度必须大
if (haystack.length() < needle.length()) {
return -1;
}
if (needle.isEmpty()) {
return 0;
}
Integer[] assistArray = patternPrehandle(needle);
int m = haystack.length();
int i=0,j=0;
while(i<m){
if(haystackArray[i]==needleArray[j]){
i++;
j++;
if(j==needle.length()){
return i-needle.length();
}
}else if(j!=0){
j = assistArray[j-1];
}else{
i++;
}
}
return -1;
}
Integer[] patternPrehandle(String pattern1){
char[] pattern = pattern1.toCharArray();
Integer[] result = new Integer[pattern.length];
int i=0,j=1;
result[0] = 0;
if(pattern.length==1){
return result;
}
while((i>=0)&&(i<j)&&(j<pattern.length)){
if(pattern[i]==(pattern[j])){
result[j]=i+1;
i++;
j++;
}else if(i!=0){
i = result[i-1];
}else{
result[j]=0;
j++;
}
}
return result;
}
}
2.Add Binary
Given two binary strings, return their sum (also a binary string).
For example,
a = “11”
b = “1”
Return “100”.
就是简单的实现二进制的加法:
public class Solution {
public String addBinary(String a, String b) {
int i=a.length()-1,j=b.length()-1;
//进位和加和
int carry=0,sum=0;
StringBuilder sb = new StringBuilder("");
while(i>=0||j>=0){
sum=carry;//进位
if(i>=0){
int add1 = a.charAt(i)-'0';
sum+=add1;
i--;
}
if(j>=0){
int add2 = b.charAt(j)-'0';
sum+=add2;
j--;
}
sb.append(String.valueOf(sum%2));
carry=sum/2;
}
if(carry!=0){
sb.append(String.valueOf(carry));
}
return sb.reverse().toString();
}
}
当然,如果想要更简单一点,可以用Java自带的BigInteger实现。
3.Simplify Path
Given an absolute path for a file (Unix-style), simplify it.
For example,
path = “/home/”, => “/home”
path = “/a/./b/../../c/”, => “/c”
Corner Cases:
Did you consider the case where path = “/../”?
In this case, you should return “/”.
Another corner case is the path might contain multiple slashes ‘/’ together, such as “/home//foo/”.
In this case, you should ignore redundant slashes and return “/home/foo”.
两种方式实现,第二种更简洁明了一点:
public class Solution {
//success 1
//直接利用string实现
public String simplifyPath(String path) {
//化简成标准型
String stardardPath="";
String pathTmp = path.replace("/./","/");
//循环,直到所有替换完成
while(pathTmp.contains("/./")){
pathTmp = pathTmp.replace("/./","/");
}
stardardPath = pathTmp.replaceAll("/+","/");
String[] pathArray = stardardPath.split("/");
String finalString = "/";
int lastEleIndex = 1;
for (int i = 1; i < pathArray.length; i++) {
if(i==pathArray.length-1&&("".equals(pathArray[i])||".".equals(pathArray[i]))){
break;
}
if("..".equals(pathArray[i])){
if(finalString.length()==1){
continue;
}else{
//除去"/"char
finalString = finalString.substring(0,finalString.length()-2);
int lastIndex = finalString.lastIndexOf("/");
finalString = finalString.substring(0,lastIndex+1);
}
}else{
finalString = finalString+pathArray[i]+"/";
}
}
if(finalString.length()>1){
//除去"/"char
finalString = finalString.substring(0,finalString.length()-1);
}
return finalString;
}
//success 2,利用stack实现
// public String simplifyPath(String path) {
// Deque<String> stack = new LinkedList<>();
// //特殊情况为..,.,空
// Set<String> skip = new HashSet<>(Arrays.asList("..",".",""));
// for (String dir : path.split("/")) {
// if (dir.equals("..") && !stack.isEmpty()) stack.pop();
// else if (!skip.contains(dir)) stack.push(dir);
// }
// String res = "";
// for (String dir : stack) res = "/" + dir + res;
// return res.isEmpty() ? "/" : res;
// }
}
4.Generate Parentheses
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
For example, given n = 3, a solution set is:
[
“((()))”,
“(()())”,
“(())()”,
“()(())”,
“()()()”
]
采用分治算法实现:
public class Solution {
//success 1
// public List<String> generateParenthesis(int n) {
// List<String> list = new ArrayList<String>();
// backtrack(list, "", 0, 0, n);
// return list;
// }
// public void backtrack(List<String> list, String str, int open, int close, int max){
// if(str.length() == max*2){
// list.add(str);
// return;
// }
// if(open < max)
// backtrack(list, str+"(", open+1, close, max);
// if(close < open)
// backtrack(list, str+")", open, close+1, max);
// }
//success 2
//想象leftIndex和rightIndex为一个数组或者stack的index,从last到0
public List<String> generateParenthesis(int n) {
List list = new ArrayList();
generate("",list,n-1,n-1);
return list;
}
private void generate(String path,List list,int leftIndex,int rightIndex){
//当rightIndex==-1时,一个组合结束
if(rightIndex==-1){
list.add(path);
return;
}
if(leftIndex>=0){
generate(path+"(",list,leftIndex-1,rightIndex);
}
if(rightIndex>leftIndex){
generate(path+")",list,leftIndex,rightIndex-1);
}
}
}
5.Scramble String
解答:
public class Solution {
public boolean isScramble(String s1, String s2) {
if (s1.equals(s2)) return true;
int[] letters = new int[26];
for (int i=0; i<s1.length(); i++) {
letters[s1.charAt(i)-'a']++;
letters[s2.charAt(i)-'a']--;
}
for (int i=0; i<26; i++) if (letters[i]!=0) return false;
for (int i=1; i<s1.length(); i++) {
if (isScramble(s1.substring(0,i), s2.substring(0,i))
&& isScramble(s1.substring(i), s2.substring(i))) return true;
if (isScramble(s1.substring(0,i), s2.substring(s2.length()-i))
&& isScramble(s1.substring(i), s2.substring(0,s2.length()-i))) return true;
}
return false;
}
}