leetcode: 字符串

1. palindrome-partitioning

Given a string s, partition s such that every substring of the partition is a palindrome.

Return all possible palindrome partitioning of s.

For example, given s ="aab",
Return

  [
    ["aa","b"],
    ["a","a","b"]
  ]

给定一个字符串,将字符串分成多个部分,满足每一部分都是回文串,请输出所有可能的情况







2. add-binary

Given two binary strings, return their sum (also a binary string).

For example,
a ="11"
b ="1"
Return"100".

二进制加法都是从最低位(从右加到左)。所以对两个字符串要从最后一位开始加,如果遇见长度不一的情况,就把短的字符串高位补0.每轮计算要加上进位,最后跳出循环后要坚持进位是否为1,以便更新结果。

public class Solution {
    public String addBinary(String a, String b) {
        if(a.length() < b.length()){
            String tmp = a;
            a = b;
            b = tmp;
        }
        
        int pa = a.length()-1;
        int pb = b.length()-1;
        int carries = 0;
        String rst = "";
        
        while(pb >= 0){
            int sum = (int)(a.charAt(pa) - '0') + (int)(b.charAt(pb) - '0') + carries;
            rst = String.valueOf(sum % 2) + rst;
            carries = sum / 2;
            pa --;
            pb --;
        }
        
        while(pa >= 0){
            int sum = (int)(a.charAt(pa) - '0') + carries;
            rst = String.valueOf(sum % 2) + rst;
            carries = sum / 2;
            pa --;
        }       
        
        if (carries == 1)
            rst = "1" + rst;
        return rst;
    }
}
View Code

 

3. valid-number

Validate if a given string is numeric.

Some examples:

 "0"=>true

" 0.1 "=>true
"abc"=>false
"1 a"=>false
"2e10"=>true

Note: It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one.

需要考虑:  数值的开头结尾的空白符; 开始的+/-号; 不同的数值表示方法,一般的,小数点的,科学计数法的; 不同计数法之间的关系

public class Solution{
    public boolean isNumber(String s){
        int len=s.length();
        int i=0,e=len-1;
        
        //isWhitespace 此方法返回true,如果字符是一个Java空白字符,否则返回false
        
        //通过i和e定位字符串的非空部分
        while(i<=e && Character.isWhitespace(s.charAt(i))) i++;
        if(i>len-1) return false;
        while(e>=i && Character.isWhitespace(s.charAt(e))) e--;
        
        //skip leading +/-
        if(s.charAt(i) == '+' || s.charAt(i) =='-') i++;
        boolean num=false; //is a digit
        boolean dot=false; // ia a '.'
        boolean exp=false;  // is a 'e'
        while(i<=e){
            char c=s.charAt(i);
            if(Character.isDigit(c)){
                num=true;
            }else if(c=='.'){
                if(exp || dot) return false;
                dot=true;
            }else if(c=='e'){
                if(exp||num==false) return false;
                exp=true;
                num=false;
            }else if(c=='+' ||c == '-'){
                if(s.charAt(i-1) != 'e') return false;
            }else{
                return false;
            }
            i++;
        }
        return num;        
    }
}
View Code

 

4. text-justification

Given an array of words and a length L, format the text such that each line has exactly L characters and is fully (left and right) justified.

You should pack your words in a greedy approach; that is, pack as many words as you can in each line. Pad extra spaces' 'when necessary so that each line has exactly L characters.

Extra spaces between words should be distributed as evenly as possible. If the number of spaces on a line do not divide evenly between words, the empty slots on the left will be assigned more spaces than the slots on the right.

For the last line of text, it should be left justified and no extra space is inserted between words.

For example,
words:["This", "is", "an", "example", "of", "text", "justification."]
L:16.

Return the formatted lines as:

[
   "This    is    an",
   "example  of text",
   "justification.  "
]

Note: Each word is guaranteed not to exceed L in length.

Corner Cases
  • A line other than the last line might contain only one word. What should you do in this case?
    In this case, that line should be left-justified.

题意:把一个集合的单词按照每行L个字符放,每行要两端对齐,如果空格不能均匀分布在所有间隔中,那么左边的空格要多于右边的空格,最后一行靠左对齐。

 

“这道题属于纯粹的字符串操作,要把一串单词安排成多行限定长度的字符串。主要难点在于空格的安排,首先每个单词之间必须有空格隔开,而当当前行放不下更多的 单词并且字符又不能填满长度L时,我们要把空格均匀的填充在单词之间。如果剩余的空格量刚好是间隔倍数那么就均匀分配即可,否则还必须把多的一个空格放到 前面的间隔里面。实现中我们维护一个count计数记录当前长度,超过之后我们计算共同的空格量以及多出一个的空格量,然后将当行字符串构造出来。最后一 个细节就是最后一行不需要均匀分配空格,句尾留空就可以,所以要单独处理一下。时间上我们需要扫描单词一遍,然后在找到行尾的时候在扫描一遍当前行的单 词,不过总体每个单词不会被访问超过两遍,所以总体时间复杂度是O(n)。而空间复杂度则是结果的大小(跟单词数量和长度有关,不能准确定义,如果知道最 后行数r,则是O(r*L))

 

public ArrayList<String> fullJustify(String[] words, int L) {
    ArrayList<String> res = new ArrayList<String>();
    if(words==null || words.length==0)
        return res;
    int count = 0;
    int last = 0;
    for(int i=0;i<words.length;i++){
        //count是上一次计算的单词的长度,words[i].length()是当前尝试放的一个单词的长度,
        //假设当前放上了这个单词,那么这一行单词跟单词间的间隔数就是i-last
        //判断这些总的长度加起来是不是大于L(超行数了)
        if(count + words[i].length() + (i-last) > L){
            int spaceNum = 0;
            int extraNum = 0;
            //因为尝试的words[i]失败了,所以间隔数减1.此时判断剩余的间隔数是否大于0
            if( i-last-1 >0){
                //是间隔的倍数(为啥要减1,因为尝试当前words[i]后发现比L长了,
                //所以当前这个单词不能算作这行,所以间隔就减少一个
                spaceNum = (L-count)/(i-last-1);
                extraNum = (L-count)%(i-last-1);//不是倍数的话还要计算
            }
            StringBuilder str = new StringBuilder();
            for(int j=last;j<i;j++){
                str.append(words[j]);
                if(j<i-1){//words[i-1]的话后面就不用填空格了,所以这里j<i-1
                    for(int k=0;k<spaceNum;k++)
                        str.append(" ");
                    
                    if(extraNum>0)
                        str.append(" ");
                    
                    extraNum--;
                }
            }
            
            //下面这个for循环作用于一行只有一个单词还没填满一行的情况
            for(int j=str.length();j<L;j++)
                str.append(" ");
                
            res.add(str.toString());
            count=0;
            last=i;//下一个开始的单词
        }
        count += words[i].length();
    }
    
    //处理最后一行
    StringBuilder str = new StringBuilder();
    for(int i=last;i<words.length;i++){
        str.append(words[i]);
        if(str.length()<L)
            str.append(" ");
    }
    for(int i=str.length();i<L;i++)
        str.append(" ");
    
    res.add(str.toString());
    return res;
}
View Code

 

5. 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".

思路一:用Stack完成检测,取出两个"/""/"之间的内容,做出如下判断:

/../ : 返回上一级菜单,即栈size大于1的时候,说明上一级菜单不为空,弹出。

/./ 或者 // 什么都不做,继续循环。

正常情况,压入文件夹名和"/"。

 

public class Solution {
    public String simplifyPath(String path) {
        Stack<String> stack = new Stack<String>();
        stack.push("/");
        
        char flag = '/';
        
        for(int i = 1 ; i < path.length() ; i++){
            int cur = i;
            while(i < path.length() && path.charAt(i) != flag){
                i++;
            }
            String temp = path.substring(cur, i); //取出内容
            
            if(temp.equals("..")){
                if(stack.size() > 1){
                    stack.pop();
                    stack.pop();
                }
                continue;
            }
            if(temp.equals(".") || temp.equals("")){
                continue;
            }
            stack.push(temp);
            stack.push("/");
        }
        if(stack.size() == 1) 
            return "/";
        
        String req = "";
        while(!stack.isEmpty()){
            req = stack.pop() + req;
        }
        return req.substring(0,req.length()-1);  //去掉最后的/
    }
}
View Code

 

思路二:

public class Solution {
    public String simplifyPath(String path) {
        String result = "/";
     
        //分隔
        String[] stubs = path.split("/+");

        ArrayList<String> paths = new ArrayList<String>();

        for (String s : stubs){
            if(s.equals("..")){
                if(paths.size() > 0){
                    paths.remove(paths.size() - 1);
                }
            }
            else if (!s.equals(".") && !s.equals("")){
                paths.add(s);
            }
        }
        for (String s : paths){
            result += s + "/";
        }
        if (result.length() > 1)
            result = result.substring(0, result.length() - 1);
        return result;
    }
}

 

 

6. wildcard-matching

Implement wildcard pattern matching with support for'?'and'*'.

'?' Matches any single character.
'*' Matches any sequence of characters (including the empty sequence).

The matching should cover the entire input string (not partial).

The function prototype should be:
bool isMatch(const char *s, const char *p)

Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "*") → true
isMatch("aa", "a*") → true
isMatch("ab", "?*") → true
isMatch("aab", "c*a*b") → false


public class Solution {

public boolean isMatch(String s, String p) {
    // without this optimization, it will fail for large data set
    int plenNoStar = 0;
    for (char c : p.toCharArray())
        if (c != '*') plenNoStar++;
    if (plenNoStar > s.length()) return false;

    s = " " + s;
    p = " " + p;
    int slen = s.length();
    int plen = p.length();

    boolean[] dp = new boolean[slen];
    TreeSet<Integer> firstTrueSet = new TreeSet<Integer>();
    firstTrueSet.add(0);
    dp[0] = true;

    boolean allStar = true;
    for (int pi = 1; pi < plen; pi++) {
        if (p.charAt(pi) != '*')
            allStar = false;
        for (int si = slen - 1; si >= 0; si--) {
            if (si == 0) {
                dp[si] = allStar ? true : false;
            } else if (p.charAt(pi) != '*') {
                if (s.charAt(si) == p.charAt(pi) || p.charAt(pi) == '?') dp[si] = dp[si-1];
                else dp[si] = false;
            } else {
                int firstTruePos = firstTrueSet.isEmpty() ? Integer.MAX_VALUE : firstTrueSet.first();
                if (si >= firstTruePos) dp[si] = true;
                else dp[si] = false;
            }
            if (dp[si]) firstTrueSet.add(si);
            else firstTrueSet.remove(si);
        }
    }
    return dp[slen - 1];
}
}
View Code
public class Solution {  
    public boolean isMatch(String s, String p) {  
        if (s == null || p == null) return false;  
        if (s.equals(p)) return true;  
        int m = s.length();  
        int n = p.length();  
        int posS = 0;  
        int posP = 0;  
        int posStar = -1;  
        int posOfS = -1;  
        //if posS == posP || posP == '?', ++posS and ++posP.  
        //posOfS, posStar, record the positon of '*' in s and p, ++posP and go on.  
        //if not match, go back to star, ++posOfS  
        while (posS < m) {  
            if (posP < n && (s.charAt(posS) == p.charAt(posP) || p.charAt(posP) == '?')) {  
                ++posS;  
                ++posP;  
            }  
            else if (posP < n && p.charAt(posP) == '*') {  
                posStar = posP;  
                posOfS = posS;  
                ++posP;  
                continue;  
            }  
            else if (posStar != -1) {  
                posS = posOfS;  
                posP = posStar + 1;  
                ++posOfS;  
            }  
            else {  
                return false;  
            }  
        }  
        while (posP < n && p.charAt(posP) == '*') {  
            ++posP;  
        }  
      
        return posS == m && posP == n;  
    }  
}  
View Code

 

 

7. anagrams

Given an array of strings, return all groups of strings that are anagrams.

Note: All inputs will be in lower-case.

For example:

Input:  ["tea","and","ate","eat","den"]

Output:   ["tea","ate","eat"]

Anagram(回文构词法)是指由颠倒字母顺序组成的单词,比如“dormitory”颠倒字母顺序会变成“dirty room”,“tea”会变成“eat”。回文构词法有一个特点:单词里的字母的种类和数目没有改变,只是改变了字母的

按照上述思路,用一个map纪录按字母排序后的字符串及其出现位置(或原字符串),在遍历过程中,如果遇到排序后的字符串相等的,就说明两者互为重排列。

第一次出现的重排列字符串需要特殊照顾下,下述代码中用-1标识第一次出现的重排列字符串是否已经加入结果。

此外,对字符串按字母排序的方法可以用Java类库的char数组排序;也可以利用题目所说的字符串中只含有小写字母这一信息,进行计数排序

public ArrayList<string> anagrams(String[] strs) 
{
      ArrayList<string> list = new ArrayList<string>();
      HashMap<string, integer=""> map = new HashMap<string, integer="">();
       
      for (int i = 0; i < strs.length; ++i) 
      {
        char[] chars = strs[i].toCharArray();
         
        Arrays.sort(chars);
         
        String anagram = new String(chars);
         
        if (map.containsKey(anagram)) 
        {
          int index = map.get(anagram);
          if (index != -1)
          {
            list.add(strs[index]);
            map.put(anagram, -1);//用-1标识第一次出现的重排列字符串
          }
          list.add(strs[i]);
        } 
        else
          map.put(anagram, i);
 
      }
      return list;
 }
View Code

 

 

8. ength-of-last-word

Given a string s consists of upper/lower-case alphabets and empty space characters' ', return the length of last word in the string.

If the last word does not exist, return 0.

Note: A word is defined as a character sequence consists of non-space characters only.

For example, 
Given s ="Hello World",
return5.

给定一个由大小写字母组和空格组成的字符串,返回字符串中的最后一个单词长度。

 

思路:  先从后找第一个字母的位置x,如果没有找到就返回0,如果找到,再找第一个空格的位记为y(y可能是-1,因为没有找到空格),返回结果x-y。

public class Solution{
    public int lengthOfLastWord(String s){
        int index=s.length()-1;
        //从后向前找第一个不是‘ ’的字符
        while (index>=0 && s.charAt(index)==' '){
            index--;
        }
        
        if(index<0){
            return 0;
        }
        
        int tmp=index;
    
        //从后面向前面找第一个是' ' 的字符
        while (index>=0 && s.charAt(index)!=' '){
            index--;
        }
        return tmp-index;
    }
}
View Code

 

 

9. string-to-integer-atoi

Implement atoi to convert a string to an integer.

Hint: Carefully consider all possible input cases. If you want a challenge, please do not see below and ask yourself what are the possible input cases.

Notes: It is intended for this problem to be specified vaguely (ie, no given input specs). You are responsible to gather all the input requirements up front.

Requirements for atoi:

The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.

The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.

If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.

If no valid conversion could be performed, a zero value is returned. If the correct value is out of the range of representable values, INT_MAX (2147483647) or INT_MIN (-2147483648) is returned.

 

思路:题目不难,但是corner case比较多,需要仔细处理。

  1. 空字符:    特殊处理
  2. 空白:       最好trim一下,自己处理也行
  3. +/-符号:    小心可选的+
  4. 溢出:简单处理可以用long或者double存放结果最后强转回来;或者累积算结果时提前对 max/10或者min/10比较一下来预测是否会溢出,等到溢出再比较就来不及了。
public int atoi(String str){
    if(str==null || str.length()<1)
        return 0;
    //java.lang.String.trim() 方法返回一个字符串副本,并忽略(去除)开头和结尾的空白
    str=str.trim();
    
    char flag='+';
    
    //char negative or positive
    int i=0;
    if(str.charAt(0)=='-'){
            flag='-';
            i++;
    }else if (str.charAt(0)=='+'){
        i++;
    }
    
    //use double to store result
    double result=0;
    
    //calculate value
    while(str.length()>i &&str.charAt(i)>='0' && str.charAt(i)<='9'){
        result=result*10+(str.charAt(i)-'0');
        i++;
    }
    
    if(flag=='-')
        result=-result;
    
    //handle max and min
    if(result>Integer.MAX_VALUE)
        return Integer.MAX_VALUE;
    if(result<Integer.MIN_VALUE)
        return Integer.MIN_VALUE;
    return (int)result;
}
View Code

 

 

 

10. regular-expression-matching

Implement regular expression matching with support for'.'and'*'.

'.' Matches any single character.
'*' Matches zero or more of the preceding element.

The matching should cover the entire input string (not partial).

The function prototype should be:
bool isMatch(const char *s, const char *p)

Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "a*") → true
isMatch("aa", ".*") → true
isMatch("ab", ".*") → true
isMatch("aab", "c*a*b") → true

 将问题分成两类:

  • the second char of pattern is "*"
  • the second char of pattern is not "*"

For the 1st case, if the first char of pattern is not ".", the first char of pattern and string should be the same. Then continue to match the remaining part.

For the 2nd case, if the first char of pattern is "." or first char of pattern == the first i char of string, continue to match the remaining part.

注意:要考虑p长度为1的特殊情况

         递归

public boolean isMatch(String s, String p) {
    // base case
    if (p.length() == 0) {
        return s.length() == 0;
    }
 
    // special case
    if (p.length() == 1) {
 
        // if the length of s is 0, return false
        if (s.length() < 1) {
            return false;
        }
 
        //if the first does not match, return false
        else if ((p.charAt(0) != s.charAt(0)) && (p.charAt(0) != '.')) {
            return false;
        }
 
        // otherwise, compare the rest of the string of s and p.
        else {
            return isMatch(s.substring(1), p.substring(1));
        }
    }
 
    // case 1: when the second char of p is not '*'
    if (p.charAt(1) != '*') {
        if (s.length() < 1) {
            return false;
        }
        if ((p.charAt(0) != s.charAt(0)) && (p.charAt(0) != '.')) {
            return false;
        } else {
            return isMatch(s.substring(1), p.substring(1));
        }
    }
 
    // case 2: when the second char of p is '*', complex case.
    else {
        //case 2.1: a char & '*' can stand for 0 element
        if (isMatch(s, p.substring(2))) {
            return true;
        }
 
        //case 2.2: a char & '*' can stand for 1 or more preceding element, 
        //so try every sub string
        int i = 0;
        while (i<s.length() && (s.charAt(i)==p.charAt(0) || p.charAt(0)=='.')){
            if (isMatch(s.substring(i + 1), p.substring(2))) {
                return true;
            }
            i++;
        }
        return false;
    }
}
View Code
public class Solution {
    public boolean isMatch(String s, String p) {
 
        if(p.length() == 0)
            return s.length() == 0;
 
        //p's length 1 is special case    
        if(p.length() == 1 || p.charAt(1) != '*'){
            if(s.length() < 1 || (p.charAt(0) != '.' && s.charAt(0) != p.charAt(0)))
                return false;
            return isMatch(s.substring(1), p.substring(1));    
 
        }else{
            int len = s.length();
 
            int i = -1; 
            while(i<len && (i < 0 || p.charAt(0) == '.' || p.charAt(0) == s.charAt(i))){
                if(isMatch(s.substring(i+1), p.substring(2)))
                    return true;
                i++;
            }
            return false;
        } 
    }
}
View Code

 

 

 11. longest-substring-without-repeating-characters

Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the longest substring is "b", with the length of 1.

 求一个字符串中最长的不含重复字符的子串

 分析:开一个数组记录当前字符最近出现的位置,一遍算过去,更新左边界,用它计算最大值就行了。
需要花费常数的空间。

public class Solution {  
  
    public int lengthOfLongestSubstring(String s) {  
        int res = 0, left = 0;  
        int prev[] = new int[300];  
  
        // init prev array  
        for (int i = 0; i < 300; ++i)  
            prev[i] = -1;  
  
        for (int i = 0; i < s.length(); ++i) {  
            if (prev[s.charAt(i)] >= left)  
                left = prev[s.charAt(i)] + 1;  
            prev[s.charAt(i)] = i;  
            if (res < i - left + 1)  
                res = i - left + 1;  
        }  
        return res;  
    }  
}  
View Code

 

 

12. longest-palindromic-substring

 Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.

 最长回文字符串(从左向右和从右向左是一样的)

 

思路1(naive approach):依次检查所有的子串(n^2),判断是否是palindrome(n),复杂度 O(n^3)。

 

思路2(dp):dp[i][j] 代表从i到j的子串是否是palindrome。自下而上自左而右计算dp数组。时空复杂度都是 O(n^2)。

    dp[i][j]=1  if:

  1.     i=j;
  2.     s.charAt(i)==s.charAt(j)    &&    j-i<2
  3.     s.charAt(i)==s.charAt(j)    &&    dp[i+1][j-1]==1

思路3:遍历字符串的每个字符,从这个字符出发(或者这个字符和下一个字符出发)向两侧辐射找出最长的子串。时间复杂度 O(n^2),空间复杂度O(1)。

    注意回文字符串的奇偶对称之分,  以i为对称 和 以 i,i+1为对称

 

public static String longestPalindrome1(String s) {
 
    int maxPalinLength = 0;
    String longestPalindrome = null;
    int length = s.length();
 
    // check all possible sub strings
    for (int i = 0; i < length; i++) {
        for (int j = i + 1; j < length; j++) {
            int len = j - i;
            String curr = s.substring(i, j + 1);
            if (isPalindrome(curr)) {
                if (len > maxPalinLength) {
                    longestPalindrome = curr;
                    maxPalinLength = len;
                }
            }
        }
    }
 
    return longestPalindrome;
}
 
public static boolean isPalindrome(String s) {
 
    for (int i = 0; i < s.length() - 1; i++) {
        if (s.charAt(i) != s.charAt(s.length() - 1 - i)) {
            return false;
        }
    }
 
    return true;
}
View Code

 

public class Solution {
    public String longestPalindrome(String s) {
        if (s == null || s.length() == 0)
            return null;
        int start = 0;
        int end = 0;
        int len = 0;
        boolean[][] dp = new boolean[s.length()][s.length()];
        for (int i = s.length() - 1; i >= 0; i--) {
            for (int j = i; j < s.length(); j++) {
                if (i == j || (s.charAt(i) == s.charAt(j) && j - i < 2)
                        || (s.charAt(i) == s.charAt(j) && dp[i + 1][j - 1])) {
                    dp[i][j] = true;
                    if (j - i + 1 > len) {
                        len = j - i;
                        start = i;
                        end = j + 1;
                    }
                }
 
            }
        }
 
        return s.substring(start, end);
    }
}
View Code

 

public String longestPalindrome(String s) {
    if (s.isEmpty()) {
        return null;
    }
 
    if (s.length() == 1) {
        return s;
    }
 
    String longest = s.substring(0, 1);
    for (int i = 0; i < s.length(); i++) {
        // get longest palindrome with center of i
        String tmp = helper(s, i, i);
        if (tmp.length() > longest.length()) {
            longest = tmp;
        }
 
        // get longest palindrome with center of i, i+1
        tmp = helper(s, i, i + 1);
        if (tmp.length() > longest.length()) {
            longest = tmp;
        }
    }
 
    return longest;
}
 
// Given a center, either one letter or two letter, 
// Find longest palindrome
public String helper(String s, int begin, int end) {
    while (begin >= 0 && end <= s.length() - 1 && s.charAt(begin) == s.charAt(end)) {
        begin--;
        end++;
    }
    return s.substring(begin + 1, end);
}
View Code

 

 

 13. zigzag-conversion

The string"PAYPALISHIRING"is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)

P   A   H   N
A P L S I I G
Y   I   R

And then read line by line:"PAHNAPLSIIGYIR"

Write the code that will take a string and make this conversion given a number of rows:

string convert(string text, int nRows);

convert("PAYPALISHIRING", 3)should return"PAHNAPLSIIGYIR".

 

 

n=2时,字符串坐标变成zigzag的走法就是:

 0 2 4 6

 1 3 5 7

 n=3时的走法是:

 0     4     8

 1  3 5  7 9

     6    10 

 n=4时的走法是:

 0      6        12

   5 7    11 13

 2 4   8 10    14

 3      9         15 

 可以发现规律,画红色的长度永远是 2n-2 (想法是你试想把所有这些行压缩成两列,两边手挤一下,第二列永远的第一行和最后一行少字)。

 利用这个规律,可以按行填字,第一行和最后一行,就是按照2n-2的顺序一点点加的。

 其他行除了上面那个填字规则,就是还要处理斜着那条线的字,可以发现那条线的字的位置永远是当前列j+(2n-2)-2i(i是行的index)。 

 

public String convert(String s, int nRows) {  
        if(s == null || s.length()==0 || nRows <=0)  
            return "";  
        if(nRows == 1)  
            return s;
            
        StringBuilder res = new StringBuilder();  
        int size = 2*nRows-2;  
        for(int i=0;i<nRows;i++){  
            for(int j=i;j<s.length();j+=size){  
                res.append(s.charAt(j));  
                if(i != 0 && i != nRows - 1){//except the first row and the last row
                    int temp = j+size-2*i;
                    if(temp<s.length())
                        res.append(s.charAt(temp));
                }
            }                  
        }  
        return res.toString();  
    }
View Code

 

 

 14. substring-with-concatenation-of-all-words

You are given a string, S, and a list of words, L, that are all of the same length. Find all starting indices of substring(s) in S that is a concatenation of each word in L exactly once and without any intervening characters.

For example, given:
S:"barfoothefoobarman"
L:["foo", "bar"]

You should return the indices:[0,9].
(order does not matter).

 

 给一个字符串 S 和一个单词列表,单词长度都一样,找出所有 S 的子串,子串由所有单词组成,返回子串的起始位置

 思路:固定每一个字符串开始的位置,然后向后搜索,使用Map帮助判断子字符串是否符合要求

public class Solution {
    public ArrayList<Integer> findSubstring(String S, String[] L) {
        ArrayList<Integer> result = new ArrayList<Integer>();
        HashMap<String, Integer> toFind = new HashMap<String, Integer>();
        HashMap<String, Integer> found = new HashMap<String, Integer>();
        int m = L.length, n = L[0].length();
        for (int i = 0; i < m; i ++){
            if (!toFind.containsKey(L[i])){
                toFind.put(L[i], 1);
            }
            else{
                toFind.put(L[i], toFind.get(L[i]) + 1);
            }
        }
        for (int i = 0; i <= S.length() - n * m; i ++){
            found.clear();
            int j;
            for (j = 0; j < m; j ++){
                int k = i + j * n;
                String stub = S.substring(k, k + n);
                if (!toFind.containsKey(stub)) break;
                if(!found.containsKey(stub)){
                    found.put(stub, 1);
                }
                else{
                    found.put(stub, found.get(stub) + 1);
                }
                if (found.get(stub) > toFind.get(stub)) break;
            }
            if (j == m) result.add(i);
        }
        return result;
    }
}
View Code

 

 

15. implement-strstr

Implement strStr().

Returns a pointer to the first occurrence of needle in haystack, or null if needle is not part of haystack.

 在一个字符串里找另一个字符串在其中的位置。

 

思路一: 暴力解决

public int strStr(String haystack, String needle) {
    if(haystack==null || needle==null)    
        return 0;
 
    if(needle.length() == 0)
        return 0;
 
    for(int i=0; i<haystack.length(); i++){
        if(i + needle.length() > haystack.length())
            return -1;
 
        int m = i;
        for(int j=0; j<needle.length(); j++){
            if(needle.charAt(j)==haystack.charAt(m)){
                if(j==needle.length()-1)
                    return i;
                m++;
            }else{
                break;
            }
 
        }    
    }   
 
    return -1;
}
View Code

 

思路二: KMP算法

 

public int strStr(String haystack, String needle) {
        if(haystack==null || needle==null)    
            return 0;
 
    int h = haystack.length();
    int n = needle.length();
 
    if (n > h)
        return -1;
    if (n == 0)
        return 0;
 
    int[] next = getNext(needle);
    int i = 0;
 
    while (i <= h - n) {
        int success = 1;
        for (int j = 0; j < n; j++) {
            if (needle.charAt(0) != haystack.charAt(i)) {
                success = 0;
                i++;
                break;
            } else if (needle.charAt(j) != haystack.charAt(i + j)) {
                success = 0;
                i = i + j - next[j - 1];
                break;
            }
        }
        if (success == 1)
            return i;
    }
 
    return -1;
}
 
//calculate KMP array
public int[] getNext(String needle) {
    int[] next = new int[needle.length()];
    next[0] = 0;
 
    for (int i = 1; i < needle.length(); i++) {
        int index = next[i - 1];
        while (index > 0 && needle.charAt(index) != needle.charAt(i)) {
            index = next[index - 1];
        }
 
        if (needle.charAt(index) == needle.charAt(i)) {
            next[i] = next[i - 1] + 1;
        } else {
            next[i] = 0;
        }
    }
 
    return next;
}
View Code

 

 

16. multiply-strings

Given two numbers represented as strings, return multiplication of the numbers as a string.

Note: The numbers can be arbitrarily large and are non-negative.

 字符串乘法,有两个字符串表示的正数a,b ,求乘积c,也用字符串表示

注:数字会非常大且是非负的

 

方法一: 利用java的 BigInteger

import java.math.BigInteger;
public calss Solution
{
    public String multiply(String num1, String num2)
    {
        BigInteger temp1=new BigInteger(num1);
        BigInteger temp2=new BigInteger(num2);
        BigInteger result=temp1.multiply(temp2);
        return result.toString();
    }
}
View Code

 

方法二: mn位数的乘积,最终结果为m+n-1位或是m+n位(进位时)。乘法计算中可以发现,结果中第i位,应该由第一个字符串中的第1位乘以第二个字符串中的第i位,第一个字符串中的第2位乘以第二个字符串中的第i-1位,.......第一个字符串中的第i位乘以第二个字符串中的第1位,最后累加求得,最后我们取个位上的数值,然后剩下的作为进位放到下一轮循环中

public String multiply(String num1, String num2) {
    String n1 = new StringBuilder(num1).reverse().toString();
    String n2 = new StringBuilder(num2).reverse().toString();
 
    int[] d = new int[num1.length()+num2.length()];
 
    //multiply each digit and sum at the corresponding positions
    for(int i=0; i<n1.length(); i++){
        for(int j=0; j<n2.length(); j++){
            d[i+j] += (n1.charAt(i)-'0') * (n2.charAt(j)-'0');
        }
    }
 
    StringBuilder sb = new StringBuilder();
 
    //calculate each digit
    for(int i=0; i<d.length; i++){
        int mod = d[i]%10;
        int carry = d[i]/10;
        if(i+1<d.length){
            d[i+1] += carry;
        }
        sb.insert(0, mod);
    }
 
    //remove front 0's
    while(sb.charAt(0) == '0' && sb.length()> 1){
        sb.deleteCharAt(0);
    }
 
    return sb.toString();
}
View Code

 

 17. count and say

The count-and-say sequence is the sequence of integers beginning as follows:
1, 11, 21, 1211, 111221, ...

1is read off as"one 1"or11.
11is read off as"two 1s"or21.
21is read off as"one 2, thenone 1"or1211.

Given an integer n, generate the nth sequence.

Note: The sequence of integers will be represented as a string.

 

 n=1时输出字符串1;n=2时,数上次字符串中的数值个数,因为上次字符串有1个1,所以输出11;n=3时,由于上次字符是11,有2个1,所以输出21;n=4时,由于上次字符串是21,有1个2和1个1,所以输出1211。依次类推,写个countAndSay(n)函数返回字符串。 

 

 第一种情况:n<0时返回null。 
  第二种情况:当n=1时,返回1 
  第三种情况:当n>1时,假设n-1返回的字符串是s,对s的串进行处理理,对不同的数字进行分组比如112365477899,分成11,2,3,6,5,4,77,8,99。最有就2个1,1个2,1个3,1个6,1个5,一个4,2个7,1个8,2个9,就是211213161614271829,返回此结果。 

 

public String countAndSay(int n) {
    if (n <= 0)
        return null;
 
    String result = "1";
    int i = 1;
 
    while (i < n) {
        StringBuilder sb = new StringBuilder();
        int count = 1;
        for (int j = 1; j < result.length(); j++) {
            if (result.charAt(j) == result.charAt(j - 1)) {
                count++;
            } else {
                sb.append(count);
                sb.append(result.charAt(j - 1));
                count = 1;
            }
        }
 
        sb.append(count);
        sb.append(result.charAt(result.length() - 1));
        result = sb.toString();
        i++;
    }
 
    return result;
}
View Code

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 



























































































































































































































































































 

 

转载于:https://www.cnblogs.com/zxqstrong/p/5336418.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值