LeetCode & 剑指offer 经典题目总结——字符串

1. 验证回文串

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。
示例 1:

输入: “A man, a plan, a canal: Panama”
输出: true

示例 2:

输入: “race a car”
输出: false

解法:

public class Solution {
    public boolean isPalindrome(String s) {
        int i=0,j=s.length()-1;
        while(i<j){
            //跳过非字母和数字的字符
            while(i<j && !Character.isLetterOrDigit(s.charAt(i))) i++;
            while(i<j && !Character.isLetterOrDigit(s.charAt(j))) j--;
            //转换为大写再比较
            if(Character.toUpperCase(s.charAt(i++))!=Character.toUpperCase(s.charAt(j--))) 
                return false;
        }
        return true;
    }
}

2. Z 字形变换

将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “LEETCODEISHIRING” 行数为 3 时,排列如下:
在这里插入图片描述
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“LCIRETOESIIGEDHN”。
示例 1:

输入: s = “LEETCODEISHIRING”, numRows = 3
输出: “LCIRETOESIIGEDHN”

示例 2:

输入: s = “LEETCODEISHIRING”, numRows = 4
输出: “LDREOEIIECIHNTSG”
解释:
在这里插入图片描述

解法:
通过从左向右迭代字符串,我们可以轻松地确定字符位于 Z 字形图案中的哪一行。

我们可以使用 min(numRows,len(s)) 个列表来表示 Z 字形图案中的非空行。

从左到右迭代 ss,将每个字符添加到合适的行。可以使用当前行和当前方向这两个变量对合适的行进行跟踪。

只有当我们向上移动到最上面的行或向下移动到最下面的行时,当前方向才会发生改变。

import java.util.*;
public class Solution {
    public String convert(String s, int nRows) {
        if(nRows == 1) return s;
        List<StringBuilder> list = new ArrayList<>();
        for(int i = 0;i < Math.min(s.length(),nRows);i++){
            list.add(new StringBuilder());
        }
        int curRow = 0;
        //转向标志
        boolean flag = false;
        for(char item : s.toCharArray()){
            list.get(curRow).append(item);
            //如果是第一行或最后一行,curRow 的移动方向要变
            if(curRow == 0 || curRow == nRows - 1){
                flag = !flag;
            }
            curRow += flag ? 1 : -1;
        }
        StringBuilder res = new StringBuilder();
        for(StringBuilder item : list){
            res.append(item);
        }
        return res.toString();
    }
}

3. 在字符串中找出连续最长的数字串

输入描述:

输入一个字符串。

输出描述:

输出字符串中最长的数字字符串和它的长度。如果有相同长度的串,则要一块儿输出,但是长度还是一串的长度

示例:

输入:

abcd12345ed125ss123058789

输出:

123058789,9

解法:

import java.util.*;
public class Main{
    public static void main(String[] args) {
        Scanner scan=new Scanner(System.in);
        while(scan.hasNext()){
            String str1="";
            String str=scan.nextLine();
            for(char ch:str.toCharArray()){
                //将不是数字的字符全部变成a
                if(ch>='0' && ch<='9'){
                    str1+=ch;
                }else{
                    str1+="a";
                }
            }
            //按a分割
            String[] strs=str1.split("a");
            int max=0;//记录最长的连续数字串的长度
            for(int i=0;i<strs.length;i++){
                max=strs[i].length()>max?strs[i].length():max;
            }
            for(int i=0;i<strs.length;i++){
                if(strs[i].length()==max)
                    System.out.print(strs[i]);
            }
            System.out.println(","+max);
        }
    }
}

4. 替换空格

请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

解法:

从后往前插入。

public class Solution {
    public String replaceSpace(StringBuffer str) {
        int spacenum=0;//空格数
        for(int i=0;i<str.length();i++){
            if(str.charAt(i)==' ')
                spacenum++;
        }
        int indexold=str.length()-1;//替换前str的下标
        int newlength=str.length()+2*spacenum;//替换后字符串长度
        int indexnew=newlength-1;//替换后str下标
        str.setLength(newlength);//扩大str的长度,防止下标越界
        for(int i=indexold;i>=0 && i<indexnew;i--){
            if(str.charAt(i) == ' '){
                str.setCharAt(indexnew--, '0');
                str.setCharAt(indexnew--, '2');
                str.setCharAt(indexnew--, '%');
            }else{
                str.setCharAt(indexnew--, str.charAt(i));
            }
        }
        return str.toString();
    }
}

5. 无重复字符的最长子串

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。

示例 2:

输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。

示例 3:

输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

解法:

https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/wu-zhong-fu-zi-fu-de-zui-chang-zi-chuan-by-leetcod/

public class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n = s.length();
        Set<Character> set = new HashSet<>();
        int ans = 0, i = 0, j = 0;
        while (i < n && j < n) {
            // try to extend the range [i, j]
            if (!set.contains(s.charAt(j))){
                set.add(s.charAt(j++));
                ans = Math.max(ans, j - i);
            }
            else {
                set.remove(s.charAt(i++));
            }
        }
        return ans;
    }
}

使用 HashMap 优化

public class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n = s.length(), ans = 0;
        Map<Character, Integer> map = new HashMap<>(); // current index of character
        // try to extend the range [i, j]
        for (int j = 0, i = 0; j < n; j++) {
            if (map.containsKey(s.charAt(j))) {
                i = Math.max(map.get(s.charAt(j)), i);
            }
            ans = Math.max(ans, j - i + 1);
            map.put(s.charAt(j), j + 1);
        }
        return ans;
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值