• LeetCode---String


    Count and Say
    思路:递归求出n - 1时的字符串,然后双指针算出每个字符的次数,拼接在结果后面
    
    public String countAndSay(int n) {
        if(n == 1) return "1";
        String front = countAndSay(n - 1);
        
        int i = 0;
        int j = 0;
        String res = "";
        int count = 0;
        
        while(j < front.length()){
            while(j < front.length() && front.charAt(i) == front.charAt(j)){
                count++;
                j++;
            }
            res = res.concat(String.valueOf(count));
            res += (front.charAt(i));
            count = 0;
            i = j;
        }
        return res;
    }
    
    Add Binary
    思路:当string有值时,就将数值加起来,该位置的结果为sum % 2,利用carry = sum / 2作为下一次的结果初值,拼接起来,最后翻转string
    
    public String addBinary(String a, String b) {
        StringBuilder sb = new StringBuilder();
        int i = a.length() - 1, j = b.length() -1, carry = 0;
        while (i >= 0 || j >= 0) {
            int sum = carry;
            if (j >= 0) sum += b.charAt(j--) - '0';
            if (i >= 0) sum += a.charAt(i--) - '0';
            sb.append(sum % 2);
            carry = sum / 2;
        }
        if (carry != 0) sb.append(carry);
        return sb.reverse().toString();
    }
    
    Mini Parser
    思路:
    If encounters '[', push current NestedInteger to stack and start a new one.
    If encounters ']', end current NestedInteger and pop a NestedInteger from stack to continue.
    If encounters ',', append a new number to curr NestedInteger, if this comma is not right after a brackets.
    Update index l and r, where l shall point to the start of a integer substring, while r shall points to the end+1 of substring.
    
    public NestedInteger deserialize(String s) {
        if(s == null || s.isEmpty()) return null;
        if(s.charAt(0) != '[') return new NestedInteger(Integer.parseInt(s));
        
        int l = 0;
        NestedInteger cur = null;
        Stack<NestedInteger> stack = new Stack<NestedInteger>();
        for(int r = 0; r < s.length(); r++){
            if(s.charAt(r) == '['){
                if(cur != null) stack.push(cur);
                cur = new NestedInteger();
                l = r + 1;
            }
            else if(s.charAt(r) == ','){
                if(s.charAt(r - 1) != ']'){
                    String num = s.substring(l,r);
                    cur.add(new NestedInteger(Integer.parseInt(num)));   
                }
                l = r + 1;
            }
            else if(s.charAt(r) == ']'){
                String num = s.substring(l,r);
                if(!num.isEmpty()){
                    cur.add(new NestedInteger(Integer.parseInt(num)));
                }
                if(!stack.isEmpty()){
                    NestedInteger p = stack.pop();
                    p.add(cur);
                    cur = p;
                }
                l = r + 1;
            }
        }
        return cur;
    }
    
    Group Anagrams
    思路:将每个字符串变成字符数组以后排序,将排序后相同的字符串放在一个list,形成最终结果
    主要学习toCharArray Arrays.sort String.valueOf map.values()
    
    public List<List<String>> groupAnagrams(String[] strs) {
        List<List<String>> res = new ArrayList<List<String>>();
        if(strs.length == 0 || strs == null) return res;
        
        HashMap<String,ArrayList<String>> map = new HashMap<String,ArrayList<String>>();
        for(int i = 0; i < strs.length; i++){
            char[] c = strs[i].toCharArray();
            Arrays.sort(c);
            if(map.containsKey(String.valueOf(c))){
                ArrayList<String> list = map.get(String.valueOf(c));
                list.add(strs[i]);
            }
            else{
                ArrayList<String> list = new ArrayList<String>();
                list.add(strs[i]);
                map.put(String.valueOf(c),list);
            }
        }
        return new ArrayList<List<String>>(map.values());
    }
    
    17. Letter Combinations of a Phone Number
    思路:建立数字和字符串的对应关系,回溯  
    
    public List<String> letterCombinations(String digits) {
        HashMap<Integer,String> map = new HashMap<Integer,String>();
        map.put(2,"abc");
        map.put(3,"def");
        map.put(4,"ghi");
        map.put(5,"jkl");
        map.put(6,"mno");
        map.put(7,"pqrs");
        map.put(8,"tuv");
        map.put(9,"wxyz");
        
        ArrayList<String> list = new ArrayList<String>();
        for(int i = 0; i < digits.length(); i++){
            list.add(map.get(digits.charAt(i) - '0'));
        }
        
        List<String> res = new ArrayList<String>();
        if(digits.equals("")) return res;
        dfs(res,"",list,0);
        return res;
    }
    
    public void dfs(List<String> res,String ans,ArrayList<String> list,int start){
        if(start == list.size()){
            res.add(ans);
            return;
        }
        
        for(int i = start; i < list.size(); i++){
            String s = list.get(i);
            for(int j = 0; j < s.length(); j++){
                ans += s.charAt(j);
                dfs(res,ans,list,i + 1);
                ans = ans.substring(0,ans.length() - 1);
            }
            //强制返回第一层,否则在最后一次回溯结束以后会继续循环i++
            return;
        }
    }
    
    Basic Calculator II
    思路:先判断第一个数的符号和开始下标,然后依次往后循环,若是数字则算出num,若是+-则入栈,是*/则直接计算后入栈,别忘了将最后一个num入栈,最后将栈中数字相加  
    
    public int calculate(String s) {
        if(s == null || s.isEmpty()) return 0;
        Stack<Integer> stack = new Stack<Integer>();
        int num = 0;
        //判断第一个数是正数还是负数
        char sign = (s.charAt(0) == '-') ? '-' : '+';
        int i = (sign == '-') ? 1 : 0;
        while(i < s.length()){
            if(Character.isDigit(s.charAt(i))){
                num = num * 10 + (s.charAt(i) - '0');
            }
            //只有一个数的情况
            if((!Character.isDigit(s.charAt(i)) && s.charAt(i) != ' ') || i == s.length() - 1){
                if(sign == '+'){
                    stack.push(num);
                }
                else if(sign == '-'){
                    stack.push(-num);
                }
                else if(sign == '*'){
                    stack.push(stack.pop() * num);
                }
                else if(sign == '/'){
                    stack.push(stack.pop() / num);
                }
                sign = s.charAt(i);
                num = 0;
            }
            i++;
        }
        int res = 0;
        for(int j : stack){
            res += j;
        }
        return res;
    }
    
    **91. Decode Ways
    思路:用数组dp[n + 1]表示第几位的不同解码数,判断当前位数字范围和前两位数字范围,动态规划
    
    public int numDecodings(String s) {
        if(s == null || s.isEmpty()) return 0;
        int[] dp = new int[s.length() + 1];
        dp[0] = 1;
        dp[1] = (s.charAt(0) == '0') ? 0 : 1;
        
        for(int i = 2; i < s.length() + 1; i++){
            int first = Integer.parseInt(s.substring(i - 1,i));
            int second = Integer.parseInt(s.substring(i - 2,i));
            if(first >= 1 && first <= 9) dp[i] += dp[i - 1];
            if(second >= 10 && second <= 26) dp[i] += dp[i - 2];
        }
        return dp[s.length()];
    }
    
    **93. Restore IP Addresses
    思路:回溯
    
    public List<String> restoreIpAddresses(String s) {
        List<String> res = new ArrayList<String>();
        if(s == null || s.isEmpty()) return res;
        dfs(res,s,"",0,0);
        return res;
    }
    
    //ans表示每个符合要求的solution,idx用来截取每段地址,i表示每段地址的长度,count表示第几段
    public void dfs(List<String> res,String s,String ans,int idx,int count){
        if(count > 4) return;
        if(count == 4 && idx == s.length()){
            res.add(ans);
            return;
        }
        
        for(int i = 1; i < 4; i++){
            if(idx + i > s.length()) break;
            String str = s.substring(idx,idx + i);
            if((str.charAt(0) == '0' && str.length() != 1) || (str.length() == 3 && Integer.parseInt(str) > 255)) continue;
            dfs(res,s,ans + str + ((count == 3) ? "" : "."),idx + i,count + 1);
        }
    }
    
    **214. Shortest Palindrome
    public String shortestPalindrome(String s) {
        int j = 0;
        for(int i = s.length() - 1; i >= 0; i--){
            if(s.charAt(i) == s.charAt(j)) j++;
        }
        if(j == s.length()) return s;
        String str = s.substring(j);
        return new StringBuffer(str).reverse().toString() + shortestPalindrome(s.substring(0,j)) + str;
    }
    
    **76. Minimum Window Substring
    思路:用map存储字符和个数,利用count来控制已经出现的字符个数,然后滑动窗口计算长度
    
    public String minWindow(String s, String t) {
        HashMap<Character,Integer> map = new HashMap<Character,Integer>();
        for(int i = 0; i < t.length(); i++){
            if(map.containsKey(t.charAt(i))){
                map.put(t.charAt(i),map.get(t.charAt(i)) + 1);
            }
            else{
                map.put(t.charAt(i),1);
            }
        }
        
        int left = 0;
        int minLeft = 0;
        int minLen = Integer.MAX_VALUE;
        int count = 0;
        //map中的value值大于0说明还有字符没找到,小于等于0说明窗口已经包含
        for(int right = 0; right < s.length(); right++){
            if(map.containsKey(s.charAt(right))){
                map.put(s.charAt(right),map.get(s.charAt(right)) - 1);
                if(map.get(s.charAt(right)) >= 0) count++;
            }
            
            while(count == t.length()){
                if(minLen > right - left + 1){
                    minLen = right - left + 1;
                    minLeft = left;
                }
                if(map.containsKey(s.charAt(left))){
                    map.put(s.charAt(left),map.get(s.charAt(left)) + 1);
                    if(map.get(s.charAt(left)) > 0) count--;
                }
                left++;
            }
        }
        return (minLen == Integer.MAX_VALUE) ? "" : s.substring(minLeft,minLeft + minLen);
    }
    
    总结
    344:reverse string
    8. String to Integer (atoi):1.判空;2.除空格;3.定符号;4.算数值,判越界
    383. Ransom Note:抽屉法,先将字母一个个放入,然后一个个拿出,若全都能拿出,则返回true
    14. Longest Common Prefix:找出所有字符串中长度最短的,然后判断是否为所有串公共前缀,循环--
    345. Reverse Vowels of a String:双指针,分别从前后找到元音字母(大小写),然后交换
    20. Valid Parentheses:利用栈,若是左括号则入栈,是右括号则判断栈是否为空,然后判断栈顶元素是否为左括号,是则出栈,最后看栈是否为空
    434. Number of Segments in a String:先除首尾空格后按空格分隔,结果为分隔后数组长度
    28. Implement strStr():indexOf
    58. Length of Last Word:利用trim()和lastIndexOf()或者trim()和split()
    468. Validate IP Address:分隔以后判断,考虑全面就行
    151. Reverse Words in a String:分隔以后翻转列表
    22. Generate Parentheses:利用left和right记录左括号数和右括号数,当都为0时即一个solution
    273. Integer to English Words:利用三个字符串数组,递归拼接最终结果
    
    训练
    459. Repeated Substring Pattern:Repeated Substring的长度最多为原串的一半,则循环查找符合长度要求的串,看是不是Repeated Substring
    **6. ZigZag Conversion:一行一行连接,找到每行下标的规律
    13. Roman to Integer:用两个指针分别表示当前指向和前一个指向,注意I V X L C D M,VX前只能是I,LC前只能是X,DM前只能是C
    12. Integer to Roman:利用数组列出所有组合,然后依次减,连接所有字符串
    165. Compare Version Numbers:先按.分隔,然后使用巧妙的方法使两个数组长度对齐,最后利用Integer的compareTo方法得到结果
    125. Valid Palindrome:使用正则表达式先将非字母数字的字符替换成“”,然后利用reverse判断
    **43. Multiply Strings:s1[i] * s2[j]的结果在最终结果的res[i + j]和res[i + j + 1]位,最后去除首位的0即可
    71. Simplify Path:利用栈,通过/分隔,注意用法ArrayList<String> list = new ArrayList<String>(stack);   "/" + String.join("/",list)
    3. Longest Substring Without Repeating Characters:利用map存储字符以及下标,利用双指针控制字符串首尾位置
    **5. Longest Palindromic Substring:分两种情况,考虑结果位数是奇数和偶数,分别求解
    **32. Longest Valid Parentheses:利用栈,将合理的括号都提取出来,只留下分隔的字符,然后依次计算间隔取最大,注意应该入栈字符下标,要不然不好计算间隔长度
    **87. Scramble String:先判断长度和字符是否完全一致,若符合条件则要么左右子树完全一致,要么左右子树完全翻转,递归求解
    **72. Edit Distance:构造int[m + 1][n + 1]表示长度为i的字符串到长度为j的字符串需要多少步,初始化以后,若字符相等则f(i,j) = f(i - 1,j - 1),不相等则在插入、删除和替换三者大的那个加一即可
    
    提示
    String常用函数:
    	charAt compareTo contains concat endsWith equals indexOf(int/string) lastIndexOf(int/string) length() matches(regex) replace(char old, char new) split startsWith substring(begin, end) toCharArray toLowerCase/toUpperCase trim()
    StringBuffer常用函数:
    	charAt indexOf lastIndexOf length() substring
    	append delete reverse setCharAt toString
    	因此需要删除、翻转、set操作应该先将string转化为StringBuffer
    Arrays常用函数:
    	sort copyOfRange(origin[],from,to)包前不包后 asList:list.add(new ArrayList<Integer>(Arrays.asList(1,2,3)));
    
    int string char char[] Array之间的常用用法:
    int->string:String.valueOf(int)    int->char:(char)(int + 48)
    string->int:Integer.parseInt(string)   string->char[]:string.toCharArray()
    char->int:char - '0'/Character.getNumericValue(char)   char->string:String.valueOf(char)
    char[]->string:String.valueOf(char[])
    Arrays.sort(char[])
  • 相关阅读:
    JQuery操作DOM
    JQuery事件和动画
    Jquery选择器
    初学JQuery
    JavaScript对象及面向对象
    JavaScript操作DOM
    JavaScript操作BOM
    JavaScript基础
    网络流之最大流Dinic算法模版
    杭电1532----Drainage Ditches『最大流』
  • 原文地址:https://www.cnblogs.com/LeonNew/p/6202685.html
Copyright © 2020-2023  润新知