Leetcode之字符串(一)

目錄

1.length-of-last-word

2.add-binary

3.multiply-strings

4.valid-number

5.string-to-integer-atoi

6.roman-to-integer

7.integer-to-roman

8.longest-common-prefix

9.longest-substring-without-repeating-characters

10.longest-palindromic-substring


1.length-of-last-word

題目:給出一個只包含大小寫字母和空格的字符串s,請返回字符串中最後一個單詞的長度,如果字符串中沒有最後一個單詞,則返回0。注意:單詞的定義是僅由非空格字符組成的字符序列。例如:s ="Hello World",返回5。

分析:先用String的trim()方法去掉前後的空格,反向遍歷進行計算倒數第一個單詞的長度即可。

   public int lengthOfLastWord(String s) {
        s = s.trim();
        int count = 0;
        for(int i = s.length() - 1;i >= 0;i--){
            if(s.charAt(i) == ' ')
                break;
            count++;
        }
        return count;
    }

2.add-binary

題目:給出兩個用字符串表示的二進制數,返回他們的和(也用字符串表示)。例如:a ="11",b ="1",返回"100".

分析:先在短的字符串前面填充0讓兩字符串長度相同,從後往前依次相加即可,二進制相加可以用異或進行計算,可提高計算效率。

   public String addBinary(String a, String b) {
        if(a.length() == 0 || b.length() == 0)
            return a + b;
        int len = Math.max(a.length(),b.length());
        while(a.length() < len)
            a = "0" + a;
        while(b.length() < len)
            b = "0" + b;
        String result = "";
        int flag = 0;
        for(int i = len - 1;i >= 0;i--){
            int m = a.charAt(i) - '0',n = b.charAt(i) - '0';
            result = (m ^ n ^ flag) + result;
            if(m + n + flag < 2)
                flag = 0;
            else
                flag = 1;
        }
        if(flag == 1)
            result = 1 + result;
        return result;
    }

3.multiply-strings

題目:給出兩個用字符串表示的數字,將兩個數字的乘積作爲字符串返回。備註:數字可以無限大,且是非負數。

分析:分治法。先舉個簡單的例子來說,比如99 * 33實際上會等於90 * 33 + 9 * 33,也就是把99從中間拆分,分別乘以33.所以我們可以將大數相乘a和b中的其中一個數從中間進行拆分,假設我們將a前後拆成a1、a2,那麼就將問題拆成了a1*b,a2*b,最後結果就是a1*b後面添加a2.length個0與a2*b的和,問題又轉化成了大數相加的問題。對於大數相加問題,可以將兩個數字的後八位分離出來進行相加,再與數字其它位數的和進行拼湊,注意拼湊時有可能後8位數字相加之後的長度小於8,這時我們要進行補0,有可能長度大於9,也就是最高位爲1時,這時我們要將高位數之和加上1,再與剩下8位進行拼湊。Integer.MAX_VALUE爲2147483647,所以當兩個數的長度均小於等於4時才進行直接相乘,長度小於等於8時才進行直接相加,以防止溢出。

     public String multiply(String num1, String num2) {
        int len1 = num1.length(),len2 = num2.length();
        if(len1 <= 4 && len2 <= 4)//遞歸出口
            return Integer.parseInt(num1) * Integer.parseInt(num2) + "";
        if(len1 > 4){//將長度大於4的字符串從中間進行拆分
            int mid = len1 >> 1;
            String s1 = num1.substring(0,mid);
            String s2 = num1.substring(mid);
            return add(multiply(s1,num2) + zero(s2.length()),multiply(s2,num2));
        }
        return multiply(num2,num1);
    }

    private String add(String num1, String num2) {//大數相加
        int len1 = num1.length(),len2 = num2.length();
        if(len1 <= 8 && len2 <= 8)//遞歸出口
            return Integer.parseInt(num1) + Integer.parseInt(num2) + "";
        String a1 = "0",a2 = num1;
        if(len1 > 8) {//分離出num1後8位
            a1 = num1.substring(0,len1 - 8);
            a2 = num1.substring(len1 - 8);
        }
        String b1 = "0",b2 = num2;
        if(len2 > 8) {//分離出num2後8位
            b1 = num2.substring(0,len2 - 8);
            b2 = num2.substring(len2 - 8);
        }
        String result = add(a2,b2);
        if(result.length() > 8)
            return add(add(a1,b1),"1") + result.substring(1);
        else
            return add(a1,b1) + zero(8 - result.length()) + result;
    }

    private String zero(int n){//返回n個0的字符串
        if(n == 0) return "";
        if(n == 1) return "0";
        String s = zero(n / 2);
        return s + s + zero(n % 2);
    }

4.valid-number

題目:判斷給出的字符串是否是數字。一些例子:"0"=>true;" 0.1 "=>true;"abc"=>false;"1 a"=>false;"2e10"=>true

分析:見劍指offer面試題20 https://blog.csdn.net/Nibaby9/article/details/103822794

5.string-to-integer-atoi

題目:實現函數 atoi 。函數的功能爲將字符串轉化爲整數。提示:仔細思考所有可能的輸入情況。這個問題故意描述的很模糊(沒有給出輸入的限制),你需要自己考慮所有可能的情況。

分析:見劍指offer面試題67 https://blog.csdn.net/Nibaby9/article/details/103822794

6.roman-to-integer

題目:請將給出的羅馬數字轉化爲整數,保證輸入的數字範圍在1 到 3999之間。

分析:羅馬數字轉換規則:I --> 1、V --> 5、X --> 10、L --> 50、C --> 100、D --> 500、M --> 1000,單個符號重複多少次,就表示多少倍。最多重複3次,比如:CCC表示300 XX表示20,但150並不用LLL表示,這個規則僅適用於I X C M;如果相鄰級別的大單位在右,小單位在左,表示大單位中扣除小單位,比如:IX表示9 IV表示4 XL表示40。這裏用暴力破解法,IV:4 IX:9 XL:40 XC:90 CD:400 CM:900這種組合實際上在羅馬數中只會出現一次,所以可以遇到這種組合可以在計算的和中減去多加的數,比如說IV如果用I+V的值就爲6,只要再減去2即可。

   public int romanToInt(String s) {
        int sum = 0;
        for(int i = 0;i < s.length();i++) {
            char c = s.charAt(i);
            if(c == 'I') sum+=1;
            if(c == 'V') sum+=5;
            if(c == 'X') sum+=10;
            if(c == 'L') sum+=50;
            if(c == 'C') sum+=100;
            if(c == 'D') sum+=500;
            if(c == 'M') sum+=1000;
        }
        if(s.contains("IV") || s.contains("IX"))//4、9
            sum -= 2;
        if(s.contains("XL") || s.contains("XC"))// 40、90
            sum -= 20;
        if(s.contains("CD") || s.contains("CM"))// 400、900
            sum -= 200;
        return sum;
    }

7.integer-to-roman

題目:請將給出的整數轉化爲羅馬數字,保證輸入數字的範圍在1 到 3999之間。

分析:利用窮舉法,將各位數分別轉換爲羅馬數字即可。

    public String intToRoman(int num) {
        String[] one = {"","I","II","III","IV","V","VI","VII","VIII","IX"};
        String[] two = {"","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"};
        String[] three = {"","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"};
        String[] four = {"","M","MM","MMM"};
        String result = "";
        result += four[num / 1000];
        result += three[num % 1000 / 100];
        result += two[num % 100 / 10];
        result += one[num % 10];
        return result;
    }

8.longest-common-prefix

題目:編寫一個函數來查找字符串數組中的最長公共前綴。如果不存在公共前綴,返回空字符串 ""。假設所有輸入只包含小寫字母 a-z 。

分析:依次遍歷字符串,當遍歷到第 i個字符串時,找到最長公共前綴LCP(s_{1},...,s_{i}),當公共前綴爲“”時,可直接返回答案爲空字符串,否則遍歷完字符串數組後可以得到LCP(s_{1},...,s_{n})

   public String longestCommonPrefix(String[] strs) {
        if (strs.length == 0)
            return "";
        String prefix = strs[0];
        for (int i = 1; i < strs.length; i++) {
            while (strs[i].indexOf(prefix) != 0) {//如果不爲0,說明prefix不是str[i]的前綴
                prefix = prefix.substring(0, prefix.length() - 1);
                if (prefix.length() == 0)
                    return "";
            }
        }
        return prefix;
    }

9.longest-substring-without-repeating-characters

題目:給定一個字符串,找出最長的不具有重複字符的子串的長度。例如,“abcabcbb”不具有重複字符的最長子串是“abc”,長度爲3。對於“bbbbb”,最長的不具有重複字符的子串是“b”,長度爲1。

分析:見劍指offer面試題48 https://blog.csdn.net/Nibaby9/article/details/10382279

10.longest-palindromic-substring

題目:找出給出的字符串S中最長的迴文子串。假設S的最大長度爲1000,並且只存在唯一解。

分析:動態規劃。定義一個函數f(i,j)表示字符串第i個位置到第j個位置是否爲迴文串,從左到右依次掃描字符將其作爲子串的結束位置,讓子串往前進行延伸,在計算f(i,j)時就可保證f(i+1,j-1)已計算出,那麼f(i,j) = (s.charAt(i) == s.charAt(j) && f(i+1,j-1))。

    public String longestPalindrome(String s) {
        if(s.length() == 0)
            return s;
        int max = 1;
        int start = 0;//保存最長迴文子串的起始點
        boolean [][]dp = new boolean[s.length()][s.length()];//子串s[i..j] 是否是迴文子串
        for(int i = 0;i < s.length();i++)
            dp[i][i] = true;
        for(int j = 1;j < s.length();j++){//子串結束位置
            for(int i = j-1;i >= 0;i--){//子串開始位置
               if(j - i < 2)
                   dp[i][j] = s.charAt(i) == s.charAt(j);
               else
                   dp[i][j] = (s.charAt(i) == s.charAt(j) && dp[i+1][j-1]);
               if(dp[i][j] && j-i+1 > max){
                   max = j - i + 1;
                   start = i;
               }
            }
        }
        return s.substring(start,start + max);
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章