劍指 offer——字符串篇

05. 替換空格

題意:面試題05. 替換空格
思路:題目要求將空格字符‘ ’替換爲‘20%’,即將一個字符替換爲三個。咱們能夠先遍歷一遍字符串,統計出字符串中空格的個數count,根據這個數字能夠計算出:java

\[替換以後字串的長度 = 原字串長度 + 2 * count \]

而後從後向前,依次將原字符串的非空格內容複製到新的字符數組中,遇到空格,則依次添加‘%’、‘0’、‘2’。面試

class Solution {
    public String replaceSpace(String s) {
        char[] arr = s.toCharArray();
        int count = 0;
        for (int i = 0; i < arr.length; i ++) {
            if (arr[i] == ' ') {
                count ++;
            }
        }
        char[] res = new char[arr.length + count * 2];
        int index = res.length - 1;
        int i = arr.length - 1;
        while (i >= 0) {
            if (arr[i] == ' ') {
                res[index --] = '0';
                res[index --] = '2';
                res[index --] = '%';
            } else {
                res[index --] = arr[i];
            }
            i --;
        }
        return String.valueOf(res);
    }
}

20. 表示數值的字符串

題意:[面試題20. 表示數值的字符串](https://leetcode-cn.com/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof/)
思路:參照題解有限狀態機DFA
狀態轉移圖
狀態轉移矩陣數組

class Solution {
    int[][] transTable = {
        {1, 2, 7, -1, -1, 0,},
        {-1, 2, 7, -1, -1, -1},
        {-1, 2, 3, 4, -1, 9},
        {-1, 3, -1, 4, -1, 9},
        {6, 5, -1, -1, -1, -1},
        {-1, 5, -1, -1, -1, 9},
        {-1, 5, -1, -1, -1, -1},
        {-1, 8, -1, -1, -1, -1},
        {-1, 8, -1, 4, -1, 9},
        {-1, -1, -1, -1, -1, 9}
    };

    Map<String, Integer> indexMap = new HashMap<String, Integer>() {
        {
            put("sign", 0);
            put("number", 1);
            put(".", 2);
            put("exp", 3);
            put("other", 4);
            put("blank", 5);
        }
    };

    Set<Integer> set = new HashSet<>(Arrays.asList(2, 3, 5, 8, 9));

    public boolean isNumber(String s) {
        int state = 0;
        for (char c : s.toCharArray()) {
            state = transTable[state][nextState(c)];
            if (state == -1) {
                return false;
            }
        }
        return set.contains(state);
    }

    private int nextState(char c) {
        String name;
        if (c >= '0' && c <= '9') {
            name = "number";
        } else if (c == '+' || c == '-') {
            name = "sign";
        } else if (c == '.') {
            name = ".";
        } else if (c == 'E' || c == 'e') {
            name = "exp";
        } else if (c == ' ') {
            name = "blank";
        } else {
            name = "other";
        }
        return indexMap.get(name);
    }
}

38. 字符串的排列

題意:面試題38. 字符串的排列
思路:遞歸構建。每次固定一個位置上的值,而後讓其後面位置上的元素進行全排列。固定某一個位置的元素能夠使用交換的方式。ui

class Solution {
    public String[] permutation(String s) {
        char[] arr = s.toCharArray();
        Set<String> res = new HashSet<>();
        permutation(arr, 0, res);
        return res.toArray(new String[0]);
    }

    private void permutation(char[] arr, int start, Set<String> res) {
        if (start == arr.length) {
            res.add(String.valueOf(arr));
            return;
        }
        for (int i = start; i < arr.length; i ++) {
            swap(arr, i, start);
            permutation(arr, start + 1, res);
            swap(arr, i, start);
        }
    }

    private void swap(char[] arr, int i, int j) {
        char tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
}

對於有重複元素的字符串,還能夠使用如下作法。某一個位置上固定的元素只須要固定一次就行。指針

class Solution {
    public String[] permutation(String s) {
        char[] arr = s.toCharArray();
        Set<String> res = new HashSet<>();
        permutation(arr, 0, res);
        return res.toArray(new String[0]);
    }

    private void permutation(char[] arr, int start, Set<String> res) {
        if (start == arr.length) {
            res.add(String.valueOf(arr));
            return;
        }
        for (int i = start; i < arr.length; i ++) {
            if (i > start && arr[i] == arr[start]) {
                continue;
            }
            swap(arr, i, start);
            permutation(arr, start + 1, res);
            swap(arr, i, start);
        }
    }

    private void swap(char[] arr, int i, int j) {
        char tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
}

48. 最長不含重複字符的子字符串

題意:面試題48. 最長不含重複字符的子字符串
思路:滑動窗口。使用兩個指針指向滑動窗口的左右邊界,先移動右邊界,直到出現重複字符,再移動左邊界,直到消除重複字符。重複以上過程直到右邊界到達字串的最後位置。code

class Solution {
    public int lengthOfLongestSubstring(String s) {
        Set<Character> set = new HashSet<>();
        char[] arr = s.toCharArray();
        int left = -1;
        int right = 0;
        int max = 0;
        while (right < arr.length) {
            if (set.contains(arr[right])) {
                while (left < right) {
                    set.remove(arr[++left]);
                    if (arr[left] == arr[right]) {
                        break;
                    }
                }
            }
            set.add(arr[right]);
            max = Math.max(right - left, max);
            right ++;
        }
        return max;
    }
}

50. 第一個只出現一次的字符

題意:面試題50. 第一個只出現一次的字符
思路:使用hash表記錄字串中每一個字符出現的次數。而後再遍歷一遍字符,找到第一個出現次數爲1的字符返回便可。blog

class Solution {
    public char firstUniqChar(String s) {
        if (s == null || s.length() == 0) {
            return ' ';
        }
        char[] arr = s.toCharArray();
        int[] chars = new int[26];
        for (char c : arr) {
            chars[c - 'a']++;
        }
        for (char c : arr) {
            if (chars[c - 'a'] == 1) {
                return c;
            }
        }
        return ' ';
    }
}

58-I. 翻轉單詞順序

題意:面試題58 - I. 翻轉單詞順序
思路:將句子以空格分隔開,而後反過來拼接便可。遞歸

import java.util.StringJoiner;
class Solution {
    public String reverseWords(String s) {
        String[] words = s.trim().split("\\s+");
        StringJoiner sj = new StringJoiner(" ");
        for (int i = words.length - 1; i >= 0; i --) {
            sj.add(words[i]);
        }
        return sj.toString();
    }
}

58-II. 左旋轉字符串

題意:面試題58 - II. 左旋轉字符串
思路:將左右兩部分分別翻轉,而後字符串總體翻轉便可。ci

class Solution {
    public String reverseLeftWords(String s, int n) {
        char[] arr = s.toCharArray();
        swap(arr, 0, n - 1);
        swap(arr, n, arr.length - 1);
        swap(arr, 0, arr.length - 1);
        return String.valueOf(arr);
    }

    private void swap(char[] arr, int start, int end) {
        if (start >= end) {
            return;
        }
        char tmp;
        while (start < end) {
            tmp = arr[start];
            arr[start] = arr[end];
            arr[end] = tmp;
            start ++;
            end --;
        }
    }
}

67. 把字符串轉換成整數

題意:面試題67. 把字符串轉換成整數
思路:按照如下幾步轉換:
1)丟棄字符串前的空格;
2)若是有正負號,則記錄正負號;
3)將緊跟着的數字記錄並轉換爲整數,這裏注意要使用long類型;
4)每次將符號與數字組合與整數的最大值與最小值比較,超過則直接返回。leetcode

class Solution {
    public int strToInt(String str) {
        int i = 0;
        char[] arr = str.trim().toCharArray();
        long res = 0;
        int sign = 1;
        if (arr.length == 0) {
            return 0;
        }
        if (arr[i] == '-' || arr[i] == '+') {
            sign = arr[i] == '-' ? -1 : 1;
            i ++;
        }
        while (i < arr.length) {
            if (arr[i] >= '0' && arr[i] <= '9') {
                res = 10 * res + (arr[i ++] - '0');
                if (sign > 0 && sign * res > Integer.MAX_VALUE) {
                    return Integer.MAX_VALUE;
                } else if (sign < 0 && sign * res < Integer.MIN_VALUE) {
                    return Integer.MIN_VALUE;
                }
            } else {
                break;
            }
        }
        return sign * (int)res;
    }
}
相關文章
相關標籤/搜索