string Leetcode 字符串算法题

344.反转字符串

API: StringBuffer 内部是 append 实现字符串的改变,不会每次改变字符串都创建一个新对象

StringBuffer(String.valueOf(s)).reverse().toString()

不调用API, 使用双指针,分别从两端向中间聚拢

class Solution {
    public void reverseString(char[] s) {
        int l = 0, r = s.length - 1;
        while(l < r){
            char chL = s[l];
            char chR = s[r];
            s[l] = chR;
            s[r] = chL;
            ++l;
            --r;
        }
    }
}

541.反转字符串 II

class Solution {
    public String reverseStr(String s, int k) {
        char[] str = s.toCharArray();
        int n = str.length;
        int l = 0;
        while(l < n){
            int r = (l-1) + k;
            if(r >= n) r = n - 1;
            int nextl = (l-1)+2*k+1;
            while(l < r){
                char ch = str[l];
                str[l] = str[r];
                str[r] = ch;
                ++l;
                --r;
            }
            l = nextl;
        }
        return new String(str);
    }
}

122.路径加密/替换空格

API:

path.replaceAll("\\.", " ");
class Solution {
    public String pathEncryption(String path) {
        char[] p = path.toCharArray();
        for(int i = 0; i < p.length; ++ i){
            if(p[i] == '.'){
                p[i] = ' ';
            }
        }
        return new String(p);
    }
}

182.动态口令/左旋字符串

substring(begin, len)

class Solution {
    public String dynamicPassword(String password, int target) {
        int n = password.length();
        return password.substring(target, n) + password.substring(0, target);
    }
}

StringBuilder

class Solution {
    public String dynamicPassword(String password, int target) {
        StringBuilder res = new StringBuilder();
        for(int i = target; i < password.length() + target; ++i){
            res.append(password.charAt(i % password.length()));
        }
        return res.toString();
    }
}

源字符串上操作

28.实现strStr

找第一个匹配子串的下标

KMP

求Next数组:

  1. Next 数组长度为 n + 1,用于获取 next[n],也就是整个字符串相同前后缀的长度
  2. 刚开始 Next[0] = -1, j = -1,便于观察当前是否已经退回到下标 0 了
  3. 可以求所有匹配位置,在 while 循环里判断 j 是否到n,然后让 j = next[j],继续匹配
class Solution {
    public int strStr(String haystack, String needle) {
        int n = needle.length(), m = haystack.length();
        int[] next = new int[n+1];

        next[0] = -1;
        int i = 0, j = -1;
        while(i < n){
            if(j == -1 || needle.charAt(j) == needle.charAt(i)){
                ++j;
                ++i;
                next[i] = j;
            }else{
                j = next[j];
            }
        }

        i = 0;
        j = 0;
        while(i < m && j < n){
            if(j == -1 || haystack.charAt(i) == needle.charAt(j)){
                ++i;
                ++j;
            }else{
                j = next[j];
            }
        }
        if(j == n){
            return i - n;
        }
        return -1;
    }
}

暴力

public class Solution {
    public int strStr(String haystack, String needle) {
        for(int i = 0; i < haystack.length(); ++i){
            String compare = haystack.substring(i, Math.min(i+needle.length(), haystack.length()));
            if(compare.equals(needle)){
                return i;
            }
        }
        return -1;
    }
}

459.重复的子字符串

求循环节

注意这里需要剔除特殊情况,防止后面的取模一直为0,

  • 避免 next[n] = 0,否则变成 n % n == 0
  • 避免 n = 1,否则 n % (n - 0) = 1 % 1 == 0
class Solution {
    public boolean repeatedSubstringPattern(String s) {
        int n = s.length();
        int[] next = new int[n+1];

        next[0] = -1;
        int i = 0, j = -1;
        while(i < n){
            if(j == -1 || s.charAt(j) == s.charAt(i)){
                ++j;
                ++i;
                next[i] = j;
            }else{
                j = next[j];
            }
        }

        if(next[n] != 0 && n != 1 && n % (n - next[n]) == 0){
            return true;
        }
        return false;
    }
}

93.复原IP地址

细节注意:

  • IP 地址不能超过 3 位
  • 不能前导 0 开头
  • 不能大于 255
  • 只有 4 节:终止条件
class Solution {
    List<String> res = new ArrayList<>();
    List<String> ans = new ArrayList<>();
    public List<String> restoreIpAddresses(String s) {
        dfs(s, 0, 0);
        return res;
    }

    public void dfs(String s, int beg, int num){
        if(num == 4 && beg == s.length()){
            String ip = "";
            for(int i = 0; i < ans.size(); ++ i){
                ip += ans.get(i) + ((i < ans.size() - 1) ? "." : "");
            }
            res.add(ip);
            return;
        }
        if(num > 4){
            return;
        }

        for(int i = beg; i < beg + 3 && i < s.length(); ++ i){
            String str = s.substring(beg, i+1);
            if(str.length() > 1 && str.charAt(0) == '0') continue;
            int strnum = Integer.parseInt(str);
            if(strnum < 0 || strnum > 255) continue;
            ans.add(str);
            dfs(s, i + 1, num+1);
            ans.remove(ans.size() - 1);
        }
    }

}

可以用 StringBuilder 来累加节约空间

更方便的写法:

String.join(".", ans);
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LeetCode是一个非常受欢迎的在线编程平台,提供了大量的算法目,涵盖了各种难度级别和型。下面是一些常用的LeetCode算法: 1. 两数之和(Two Sum):给定一个整数数组和一个目标值,找出数组中和为目标值的两个数的索引。 2. 反转字符串(Reverse String):反转给定字符串中的字符顺序。 3. 最长公共前缀(Longest Common Prefix):找出一组字符串中最长的公共前缀。 4. 合并两个有序链表(Merge Two Sorted Lists):将两个有序链表合并为一个新的有序链表。 5. 有效的括号(Valid Parentheses):判断给定的字符串中的括号是否有效。 6. 盛最多水的容器(Container With Most Water):给定一组非负整数,表示一组垂直线在x轴上的坐标,找出两条线与x轴组成的容器可以容纳的最大水量。 7. 三数之和(3Sum):给定一个包含n个整数的数组nums,判断nums中是否存在三个元素a,b,c,使得a + b + c = 0。 8. 最长回文子串(Longest Palindromic Substring):找出给定字符串中的最长回文子串。 9. 二叉树的最大深度(Maximum Depth of Binary Tree):计算二叉树的最大深度,即从根节点到最远叶子节点的最长路径上的节点数。 10. 两个排序数组的中位数(Median of Two Sorted Arrays):给定两个大小为m和n的有序数组,找出这两个数组合并后的中位数。 以上只是LeetCode中的一小部分常用算法目,LeetCode还有很多其他类型的目,包括动态规划、回溯、贪心算法等等。如果你有具体的算法或者需要更多的目推荐,请告诉我。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值