【LeetCode】字符串总结

dfs

22.括号的生成

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

示例 1:
输入:n = 3
输出:[“((()))”,“(()())”,“(())()”,“()(())”,“()()()”]

示例 2:
输入:n = 1
输出:[“()”]

提示:
1 <= n <= 8

思路:
所以的符合条件的组合其实就是一个二叉树,我们遍历这个树就可以得到结果,所以用dfs做:
dfs过程中:

  1. 符合条件:index==2*n即遍历的括号数为需要的括号数
  2. 不符合条件,直接return:
    2.1 右括号数量大于左括号数量
    2.2 左括号数量大于n
    public List<String> generateParenthesis(int n) {
        List<String> res = new ArrayList<>();
        dfs(0,n,0,0,"",res);
        return res;
    }

    private void dfs(int index, int n, int left,int right, String str, List<String> res){
        // 不符合条件:1:左边括号数量<右边括号数量 2:左边括号数量大于n
        if (left>n||right>left){
            return ;
        }
        // 符合条件:当前的个数等于括号总量
        if (index==2*n){
            res.add(str);
            return ;
        }
        // 搜索左边
        dfs(index+1,n,left+1,right,str+"(",res);
        // 搜索右边
        dfs(index+1,n,left,right+1,str+")",res);
    }

动态规划

22.括号的生成

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

关键:
dp[i]的定义:表示第i对所有合法的括号列表,所以返回的结果就是dp[n]
初始:dp[0]:[“”] dp[1]:[“()”]
表达式:“(”+dp[p]中任意一个+“)”+dp[q]中任意一个,其中:0=<p<=i-1 p+q = i-1 也就是从前面满足条件的进行任意组合

    public List<String> generateParenthesis(int n) {
        //dp[i] 表示第i对所有合法的括号列表
        List<List<String>> dp = new ArrayList<>();
        List<String> dp0 = new ArrayList<>();
        dp0.add("");
        List<String> dp1 = new ArrayList<>();
        dp1.add("()");
        dp.add(dp0);
        dp.add(dp1);
        if (n==1){
            return dp.get(1);
        }
        // dp[i] : "("+dp[p]中任意一个+")"+dp[q]中任意一个
        // 其中:0=<p<=i-1 p+q = i-1 也就是从前面满足条件的进行任意组合
        for(int i=2;i<=n;i++){
            List<String> cur = new ArrayList<>();
            // 找到当前i每一个符合条件结果
            for (int p=0;p<=i-1;p++){
                for (String k : dp.get(p)){
                    for (String l : dp.get(i-1-p)){
                        cur.add("("+k+")"+l);
                    }
                }
            }
            dp.add(cur);
        }
        return dp.get(n);
    }

栈的常用:

// new一个栈
Stack<Character> stack = new Stack<Character>();
// 入栈
stack.push(x);
// 出栈
Character x = stack.pop();
// 判断栈是否为空
stack.isEmpty();

20.有效的括号

给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。

示例 1:
输入:s = “()”
输出:true

示例 2:

输入:s = “()[]{}”
输出:true

示例 3:

输入:s = “(]”
输出:false

提示:
1 <= s.length <= 10⁴
s 仅由括号 ‘()[]{}’ 组成


思路:
比较简单,因为左括号必须以正确的顺序闭合,所以只要判断当前右括号是否和栈顶左括号是否匹配就可以了

    public boolean isValid(String s) {
        if (s.length()%2!=0){
            return false;
        }
        Stack<Character> stack = new Stack<>();
        for (int i=0;i<s.length();i++){
            if (s.charAt(i)=='(' || s.charAt(i)=='[' || s.charAt(i)=='{'){
                stack.push(s.charAt(i));
            }else{
                if (stack.isEmpty()){
                    return false;
                }
                char l = stack.pop();
                if (!isMatch(l, s.charAt(i))){
                    return false;
                }
            }
        }
        return stack.isEmpty();
    }

    public boolean isMatch(char l, char r){
        if (l=='(' && r==')'){
            return true;
        }else if(l=='[' && r==']'){
            return true;
        }else if(l=='{' && r=='}'){
            return true;
        }
        return false;
    }

65. 有效数字

在这里插入图片描述
在这里插入图片描述


思路:

在这里插入图片描述

    class Solution {
        public boolean isNumber(String s) {
            int n = s.length();
            char[] cs = s.toCharArray();
            int idx = -1;
            // 通过 e/E 对字符串进行分割
            for (int i = 0; i < n; i++) {
                if (cs[i] == 'e' || cs[i] == 'E') {
                    if (idx == -1) idx = i;
                    else return false;
                }
            }
            boolean ans = true;
            if (idx != -1) {
                // e/E  左侧为整数或浮点数
                ans &= check(cs, 0, idx - 1, false);
                // e/E  右侧必须为整数
                ans &= check(cs, idx + 1, n - 1, true);
            } else {
                ans &= check(cs, 0, n - 1, false);
            }
            return ans;
        }
        boolean check(char[] cs, int start, int end, boolean mustInteger) {
            if (start > end) return false;
            if (cs[start] == '+' || cs[start] == '-') start++;
            boolean hasDot = false, hasNum = false;
            for (int i = start; i <= end; i++) {
                if (cs[i] == '.') {
                    if (mustInteger || hasDot) return false;
                    hasDot = true;
                } else if (cs[i] >= '0' && cs[i] <= '9') {
                    hasNum = true;
                } else {
                    return false;
                }
            }
            return hasNum;
        }
    }

字符串相加

415. 字符串相加

给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和。
提示:
num1 和num2 的长度都小于 5100
num1 和num2 都只包含数字 0-9
num1 和num2 都不包含任何前导零
你不能使用任何內建 BigInteger 库, 也不能直接将输入的字符串转换为整数形式

十进制字符串相加

class Solution {
    public String addStrings(String num1, String num2) {
        int carry = 0;
        int i = num1.length()-1;
        int j = num2.length()-1;
        String res = "";
        while(i>=0 || j>=0 || carry>0){
            int x = i>=0?num1.charAt(i)-'0':0;
            int y = j>=0?num2.charAt(j)-'0':0;
            int temp = x+y+carry;
            res+=temp%10;
            carry = temp/10;
            i--;
            j--;
        }
        return new StringBuilder(res).reverse().toString();

    }
}

36进制加法

36进制加法解析

36进制由0-9,a-z,共36个字符表示。
要求按照加法规则计算出任意两个36进制正整数的和,如1b + 2x = 48 (解释:47+105=152)
要求:不允许使用先将36进制数字整体转为10进制,相加后再转回为36进制的做法

class Solution {
    public String add36Strings(String num1, String num2) {
        int carry = 0;
        int i = num1.length()-1;
        int j = num2.length()-1;
        String res = "";
        while(i>=0 || j>=0 || carry>0){
            int x = i>=0?getInt(num1.charAt(i)):0;
            int y = j>=0?getInt(num2.charAt(j)):0;
            int temp = x+y+carry;
            res+=getChar(temp%36);
            carry = temp/36;
            i--;
            j--;
        }
        return new StringBuilder(res).reverse().toString();

    }

    public int getInt(char c){
        if(c>='0' && c<='9'){
            return c-'0';
        }else{
            return c-'a'+10;
        }

    }

    public char getChar(int x){
        if(x<=9){
            return x+'0';
        }else{
            return x-10+'a';
        }

    }
}

回文系列

647.回文子串

给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。
具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。

示例 1:
输入:“abc”
输出:3
解释:三个回文子串: “a”, “b”, “c”

示例 2:
输入:“aaa”
输出:6
解释:6个回文子串: “a”, “a”, “a”, “aa”, “aa”, “aaa”


思路: 可以用中心拓展(以每个点作为回文的中心点)的办法,中心拓展的关键就是在于中心可以是一个字符也可以是两个字符

class Solution {
    public int countSubstrings(String s) {
        int num = 0;
        int n = s.length();
        // 遍历回文中心点
        for (int i = 0; i < n; i++) {
            // j==0 表示中心是一个点,j==1 表示中心是两个点
            for (int j = 0; j <= 1; j++) {
                // 往外拓展看是否为回文
                int l = i;
                int r = i+j;
                while(l>=0 && r<n && s.charAt(l)==s.charAt(r)){
                    l--;
                    r++;
                    num++;
                }
            }
        }
        return num;
    }

}

表达式

满足加减乘除和括号

  • 转成前缀表达式
  • 通过前缀表达式进行计算
public class Solution {

    public static void main(String[] args) {
        Solution solution = new Solution();
        System.out.println(solution.solve("(1+2)*3+6/2"));
    }
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 返回表达式的值
     * @param s string字符串 待计算的表达式
     * @return int整型
     */
    public int solve (String s) {
        // write code here
        // 得到前缀表达式
        ArrayList<String> list = getSuffix(s);
        Deque<Integer> stack = new LinkedList<>();
        for(String str : list){
            if("+".equals(str) || "-".equals(str) || "*".equals(str) || "/".equals(str)){
                int a = Integer.valueOf(stack.pop());
                int b = Integer.valueOf(stack.pop());
                if("+".equals(str)){
                    stack.push(a + b);
                }else if("-".equals(str)){
                    stack.push(b - a);
                }else if("*".equals(str)){
                    stack.push(a * b);
                }else if("/".equals(str)){
                    stack.push(b/a);
                }
            }else{
                stack.push(Integer.valueOf(str));
            }
        }
        return stack.pop();
    }

    public ArrayList<String> getSuffix(String s){
        HashMap<Character, Integer> map = new HashMap<>();
        map.put('+', 0);
        map.put('-', 0);
        map.put('*', 1);
        map.put('/', 1);

        int n = s.length();
        Deque<Character> stack = new LinkedList<>();
        ArrayList<String> list = new ArrayList<>();
        int i = 0;

        while(i < n){
            int index = i;
            Character cur = s.charAt(i);
            if(cur == '('){
                stack.push(cur);
            }else if(cur == ')'){
                while(!stack.isEmpty() ){
                    Character ch = stack.pop();
                    if(ch == '(') break;
                    list.add(ch.toString());
                }

            }else if(cur == '+' || cur == '-' || cur == '*'|| cur == '/'){
                if (stack.isEmpty()){
                    stack.push(s.charAt(i));
                }else {
                    while (!stack.isEmpty() &&(stack.peek() == '+' || stack.peek() == '-' || stack.peek() =='*'|| stack.peek() =='/')&&map.get(s.charAt(i)) <= map.get(stack.peek())){
                        Character pop = stack.pop();
                        list.add(pop.toString());
                    }
                    stack.push(s.charAt(i));
                }

            }else{
                StringBuilder sb = new StringBuilder();
                while(i < n && s.charAt(i) >= '0' && s.charAt(i) <= '9'){
                    sb.append(s.charAt(i));
                    i++;
                }
                list.add(sb.toString());
            }
            if(i == index){
                i++;
            }
        }

        while(!stack.isEmpty()){
            list.add(stack.pop().toString());
        }
        return list;
    }
}

只有加减括号

class Solution {
    public int calculate(String s) {
        char[] chars=s.toCharArray();
        Stack<Integer>stack=new Stack<>();
        int res=0,cur=0,flag=1;
        for(int i=0;i<chars.length;i++){
            char c=chars[i];
            if(c==' ')continue;
            if(Character.isDigit(c)){
                cur=cur*10+c-'0';
                if(i+1<chars.length&&Character.isDigit(chars[i+1])){
                    continue;
                }
            }else if(c=='+'||c=='-'){
                cur=0;
                if(c=='+'){flag=1;}
                else flag=-1;
            }else if(c=='('){
                stack.push(res);
                stack.push(flag);
                res=0;
                flag=1;
            }else if(c==')'){
                flag=stack.pop();
                cur=res;
                res=stack.pop();
            }
            res+=cur*flag;
        }
        return res;
    }
}

加减乘除没括号

class Solution {
    public int calculate(String s) {
        char[] chars=s.toCharArray();
        Stack<Integer>stack=new Stack<>();
        int num=0;
        char flag='+';
        for(int i=0;i<s.length();i++){
            char c=chars[i];
            if(Character.isDigit(c)){
                num=num*10+c-'0';
            }if(c<'0'&& c!=' '||i==s.length()-1){
                if(flag=='-'){
                    stack.push(-num);
                }
                if(flag=='+'){
                    stack.push(num);
                }
                if(flag=='*'){
                    stack.push(stack.pop()*num);
                }
                if(flag=='/'){
                    stack.push(stack.pop()/num);
                }
                flag=c;
                num=0;
            }
        }
        int res=0;
        while(!stack.isEmpty()){
            res+=stack.pop();
        }
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值