LeetCode 003 字符串系列

Posted Al_tair

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 003 字符串系列相关的知识,希望对你有一定的参考价值。

字符串(一)

大家好!我是小笙!我们即将开始探索的是字符串(一)系列的题型,刷题一开始刷起来感觉很难,但是一直刷题一直爽,我们可以从中享受到刷题的快乐!加油!坚持下去

字符串(一)系列题型如下

字符(520)

520题:检测大写字母

给定一个单词,你需要判断单词的大写使用是否正确。
我们定义,在以下情况时,单词的大写用法是正确的:
全部字母都是大写,比如"USA"。
单词中所有字母都不是大写,比如"leetcode"。
如果单词不只含有一个字母,只有首字母大写, 比如 “Google”。
否则,我们定义这个单词没有正确使用大写字母。
示例 1:
输入: “USA”
输出: True
示例 2:
输入: “FlaG”
输出: False

暴力解法(MyCode)

此题我觉得比较看重的是字符串函数的运用
解题步骤如下:
1.先判断第一个字符是否是大写字母
2.如果是大写字符,则判断接下来的全部字符是否全等于该字符的小写字符或者大写字符 是则返回true 反之为false
3.如果是小写字符,则只需要判断接下来的全部字符是否等于该字符的小写字符,是则返回true 反之为false

/*
char   charAt​(int index)   返回char指定索引处的值。
int	    length()           返回此字符串的长度。
String   substring​(int beginIndex, int endIndex)  返回一个字符串,该字符串是此字符串的子字符串。
String   toLowerCase()     String使用默认语言环境的规则将此中的所有字符转换为小写。
String   toUpperCase()     String使用默认语言环境的规则将此中的所有字符转换为大写。
*/
class Solution {
    public boolean detectCapitalUse(String word) {
        String str = word.substring(1,word.length());
        if(word.length()==1) return true;
        if(word.charAt(0)>='A' && word.charAt(0)<='Z'){
            if(str.toLowerCase() == str || str.toUpperCase() == str){
                return true;
            }else{
                return false;
            }
        }else{
             if(str.toLowerCase() == str){
                return true;
            }else{
                return false;
            }
        }
    }
}

执行用时:1 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:36.9 MB, 在所有 Java 提交中击败了33.97%的用户

回文串的定义(125)

125题:验证回文串

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。
示例 1:
输入: “A man, a plan, a canal: Panama”
输出: true
解释:“amanaplanacanalpanama” 是回文串
示例 2:
输入: “race a car”
输出: false
解释:“raceacar” 不是回文串
提示:
1 <= s.length <= 2 * 105
字符串 s 由 ASCII 字符组成

方法一:暴力解法(MyCode)

这道题的核心思想
1.整合,提取有用信息如大小字母和数字
2.归一化,将大小字母全变成小写字母
3.遍历数组,判断是否为回文字符

// char  charAt​(int index)   返回char指定索引处的值
// String   concat​(String str)   将指定的字符串连接到此字符串的末尾。
// String   toLowerCase()   String使用默认语言环境的规则将此中的所有字符转换为小写
class Solution {
    public boolean isPalindrome(String s) {
        String sum = "";
        if(s.length() == 1) return true;
        for(int i=0;i<s.length();i++){
            if((s.charAt(i) >= 'a' && s.charAt(i) <= 'z') || (s.charAt(i) >= 'A' && s.charAt(i) <= 'Z') || (s.charAt(i) >= '0' && s.charAt(i) <= '9')){
                sum = sum+s.charAt(i) ;
                // sum = sum.concat​(s.substring​(i,i));
            }
        }
        sum = sum.toLowerCase();
        for(int i=0;i<(sum.length()/2);i++){
            if(sum.charAt(i) != sum.charAt(sum.length()-i-1)){
                return false;
            }
        }
        return true;
    }
}
执行用时:211 ms, 在所有 Java 提交中击败了5.02%的用户
内存消耗:39.3 MB, 在所有 Java 提交中击败了12.51%的用户

方法二:筛选 + 判断(Other’s Code)

最大的特点是函数的调用,真的灵活!

// java.lang.Character.isLetterOrDigit(char ch) 确定指定的字符是否为字母或数字。
// StringBuffer 可变字符串  
// public StringBuffer append(String s)  将指定的字符串追加到此字符序列。
// public StringBuffer reverse()  将此字符序列用其反转形式取代。
// String toString()  返回此序列中数据的字符串表示形式。
class Solution {
    public boolean isPalindrome(String s) {
        StringBuffer sgood = new StringBuffer();
        int length = s.length();
        for (int i = 0; i < length; i++) {
            char ch = s.charAt(i);
            if (Character.isLetterOrDigit(ch)) {
                sgood.append(Character.toLowerCase(ch));
            }
        }
        StringBuffer sgood_rev = new StringBuffer(sgood).reverse();
        return sgood.toString().equals(sgood_rev.toString());
    }
}

方法三:双指针(Other’s Code)

第二种是使用双指针。初始时,左右指针分别指向sgood 的两侧,随后我们不断地将这两个指针相向移动,每次移动一步,并判断这两个指针指向的字符是否相同。当这两个指针相遇时,就说明 sgood 是回文串。

class Solution {
    public boolean isPalindrome(String s) {
        StringBuffer sgood = new StringBuffer();
        int length = s.length();
        for (int i = 0; i < length; i++) {
            char ch = s.charAt(i);
            if (Character.isLetterOrDigit(ch)) {
                sgood.append(Character.toLowerCase(ch));
            }
        }
        int n = sgood.length();
        int left = 0, right = n - 1;
        while (left < right) {
            if (Character.toLowerCase(sgood.charAt(left)) != Character.toLowerCase(sgood.charAt(right))) {
                return false;
            }
            ++left;
            --right;
        }
        return true;
    }
}

公共前缀(14)

14题:最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 “”。
示例 1
输入:strs = [“flower”,“flow”,“flight”]
输出:“fl”
示例 2:
输入:strs = [“dog”,“racecar”,“car”]
输出:""
解释:输入不存在公共前缀。
提示:
1 <= strs.length <= 200
0 <= strs[i].length <= 200
strs[i] 仅由小写英文字母组成

纵向扫描(MyCode)

解题思路:
1.整定,有多行多列的数组,我们对比只需把某一行的字符串中最短的字符长度作为全部行字符比较的长度
2.遍历数组,在每一列中,比较每一行的该列数的字符是否相等
3.通过比较返回相等的字符串sum

// strs[0].length() 表示第一行字符串的字符长度
class Solution {
    public String longestCommonPrefix(String[] strs) {
        if(strs==null||strs.length==0)   return "";
        int minString=strs[0].length();
        String sum="";
        for (int i = 1; i < strs.length ; i++) {
            if(strs[i].length()<minString)
                minString=strs[i].length();  // 某一行中最短的字符长度
        }
        for (int i = 0; i < minString; i++){
            for (int j = 0; j < strs.length-1;j++){
                if(strs[j].charAt(i)==strs[j+1].charAt(i)){}
                else
                    return sum;
            }
            sum=sum+strs[0].charAt(i);
        }
        return sum;
    }
}

单词(58)

58题:最后一个单词的长度

给你一个字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中最后一个单词的长度。
单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。
示例 1:
输入:s = “Hello World”
输出:5
示例 2:
输入:s = " fly me to the moon "
输出:4
示例 3:
输入:s = “luffy is still joyboy”
输出:6
提示:
1 <= s.length <= 104
s 仅有英文字母和空格 ’ ’ 组成
s 中至少存在一个单词

巧妙运用函数(MyCode)

该题目思路简单的不能再简单
无非就是从后向前取到的第一个单词的长度
但是困难的地方就是字符串结尾是什么是我们不能预料的
这个时候字符串的函数trim()就很好解决了这个问题

// trim() 方法用于删除字符串的头尾空白符,空白符包括:空格、制表符 tab、换行符等其他空白符等。
class Solution {
    public int lengthOfLastWord(String s) {
        String s1 = s.trim();
        int num = 0;
        for (int i = s1.length()-1; i >= 0; i--) {
            if(s1.charAt(i) == ' '){
                break;
            }
            num++;
        }
        return num;
    }
}

字符串遍历(Oher’s Code)

核心思路:
1.从后向前遍历s.charAt(end) == ’ ';该判断去掉尾部的空格,找到最后一个单词的尾部
2.在从单词尾部向前遍历,如果出现为空或者没有字符的时候,则知道了最后一个单词的单词头部
3.返回单词尾部-单词前部

class Solution {
    public int lengthOfLastWord(String s) {
        int end = s.length() - 1;
        while(end >= 0 && s.charAt(end) == ' ') end--;  // 从后向前遍历,找到单词尾部
        if(end < 0) return 0;
        int start = end;
        while(start >= 0 && s.charAt(start) != ' ') start--;  // 从单词尾部遍历,找到单词头部
        return end - start;
    }
}

字符串的反转(344)

344题:反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符
示例 1:
输入:[“h”,“e”,“l”,“l”,“o”]
输出:[“o”,“l”,“l”,“e”,“h”]
示例 2:
输入:[“H”,“a”,“n”,“n”,“a”,“h”]
输出:[“h”,“a”,“n”,“n”,“a”,“H”]

方法一:字符反转(MyCode)

这道题想法很简单,无非是将字符数组转换成字符串进行反转
然后赋值给字符数组
重点 public StringBuffer reverse() 将此字符序列用其反转形式取代。

class Solution {
    // 	public StringBuffer reverse() 将此字符序列用其反转形式取代。
    // 	String toString() 返回此序列中数据的字符串表示形式。
    public void reverseString(char[] s) {
        String sum = "";
        for(int i=0;i<s.length;i++){
            sum += s[i];
        }
        sum = new StringBuffer(sum).reverse().toString();
         for(int i=0;i<s.length;i++){
            s[i] = sum.charAt(i);
        }
    }
}
执行用时:114 ms, 在所有 Java 提交中击败了97.62%的用户
内存消耗:46 MB, 在所有 Java 提交中击败了5.00%的用户

方法二:双指针(Other’s Code)

思路与算法

class Solution {
    public void reverseString(char[] s) {
        int n = s.length;
        for (int left = 0, right = n - 1; left < right; ++left, --right) {
            char tmp = s[left];
            s[left] = s[right];
            s[right] = tmp;
        }
    }
}

以上是关于LeetCode 003 字符串系列的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 003 字符串系列

LeetCode刷题系列 - 003题Longest Substring Without Repeating Characters

003LeetCode--LongestSubstring

leetcode python 003

LeetCode-003-无重复字符的最长子串

LeetCode刷题--点滴记录003