一、字符串基础问题
1、LeetCode709:转换成小写字母
实现函数ToLowerCase()
,该函数接收一个字符串参数str,并将该字符串中的大写字母转换成小写字母,之后返回新的字符串
示例1:
输入: "Hello"
输出: "hello"
示例2:
输入: "here"
输出: "here"
示例3:
输入: "LOVELY"
输出: "lovely"
题解:
public String toLowerCase(String str) {
char[] charArray = new char[str.length()];
char c;
for (int i = 0; i < str.length(); ++i) {
c = str.charAt(i);
if (c >= 65 && c <= 90) {
c = (char) (c + 32);
}
charArray[i] = c;
}
return new String(charArray);
}
2、LeetCode58:最后一个单词的长度
给定一个仅包含大小写字母和空格的字符串,返回其最后一个单词的长度
如果不存在最后一个单词,请返回0
说明:一个单词是指由字母组成,但不包含任何空格的字符串
示例:
输入: "Hello World"
输出: 5
解析:
从字符串末尾开始向前遍历,其中主要有两种情况:
第一种情况,以字符串"Hello World"为例,从后向前遍历直到遍历到头或者遇到空格为止,即为最后一个单词"World"的长度5
第二种情况,以字符串"Hello World “为例,需要先将末尾的空格过滤掉,再进行第一种情况的操作,即认为最后一个单词为"World”,长度为5
转自:https://leetcode-cn.com/problems/length-of-last-word/solution/hua-jie-suan-fa-58-zui-hou-yi-ge-dan-ci-de-chang-d/
题解:
public int lengthOfLastWord(String s) {
s = s.trim();
int start = s.lastIndexOf(" ") + 1;
return s.substring(start).length();
}
3、LeetCode771:宝石与石头
给定字符串J代表石头中宝石的类型,和字符串S代表你拥有的石头。S中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石
J中的字母不重复,J和S中的所有字符都是字母。字母区分大小写,因此"a"和"A"是不同类型的石头
示例1:
输入: J = "aA", S = "aAAbbbb"
输出: 3
示例2:
输入: J = "z", S = "ZZ"
输出: 0
题解:
public int numJewelsInStones(String J, String S) {
Set<Character> set = new HashSet<>();
for (char j : J.toCharArray()) {
set.add(j);
}
int count = 0;
for (char s : S.toCharArray()) {
if (set.contains(s)) count++;
}
return count;
}
4、LeetCode387:字符串中的第一个唯一字符
给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回-1
案例:
s = "leetcode"
返回 0
s = "loveleetcode"
返回 2
题解:
public int firstUniqChar(String s) {
HashMap<Character, Integer> map = new HashMap<>();
for (int i = 0; i < s.length(); ++i) {
map.put(s.charAt(i), map.getOrDefault(s.charAt(i), 0) + 1);
}
for (int i = 0; i < s.length(); ++i) {
if (map.get(s.charAt(i)) == 1) {
return i;
}
}
return -1;
}
二、字符串操作问题
1、LeetCode14:最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀
如果不存在公共前缀,返回空字符串 “”
示例1:
输入: ["flower","flow","flight"]
输出: "fl"
示例2:
输入: ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀
题解:
public String longestCommonPrefix(String[] strs) {
if (strs == null || strs.length == 0) return "";
for (int i = 0; i < strs[0].length(); ++i) {
char c = strs[0].charAt(i);
for (int j = 1; j < strs.length; ++j) {
if (i == strs[j].length() || strs[j].charAt(i) != c) {
return strs[0].substring(0, i);
}
}
}
return strs[0];
}
2、LeetCode344:反转字符串
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组char[]的形式给出
示例1:
输入:["h","e","l","l","o"]
输出:["o","l","l","e","h"]
示例2:
输入:["H","a","n","n","a","h"]
输出:["h","a","n","n","a","H"]
题解:
public void reverseString(char[] s) {
if (s == null) return;
for (int i = 0, j = s.length - 1; i < j; ++i, --j) {
char tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
}
3、LeetCode541:反转字符串 II
给定一个字符串和一个整数k,你需要对从字符串开头算起的每隔2k个字符的前k个字符进行反转。如果剩余少于k 个字符,则将剩余的所有全部反转。如果有小于2k但大于或等于k个字符,则反转前k个字符,并将剩余的字符保持原样
示例:
输入: s = "abcdefg", k = 2
输出: "bacdfeg"
题解:
public String reverseStr(String s, int k) {
char[] chars = s.toCharArray();
for (int start = 0; start < chars.length; start += 2 * k) {
int i = start, j = Math.min(start + k - 1, chars.length - 1);
while (i < j) {
char tmp = chars[i];
chars[i++] = chars[j];
chars[j--] = tmp;
}
}
return new String(chars);
}
4、LeetCode151:翻转字符串里的单词
给定一个字符串,逐个翻转字符串中的每个单词
示例1:
输入: "the sky is blue"
输出: "blue is sky the"
示例 2:
输入: " hello world! "
输出: "world! hello"
解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括
示例3:
输入: "a good example"
输出: "example good a"
解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个
题解:
public String reverseWords(String s) {
String[] words = s.trim().split(" +");
Collections.reverse(Arrays.asList(words));
return String.join(" ", words);
}
5、LeetCode557:反转字符串中的单词 III
给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序
示例1:
输入: "Let's take LeetCode contest"
输出: "s'teL ekat edoCteeL tsetnoc"
题解:
public String reverseWords(String s) {
String[] words = s.split(" ");
StringBuilder result = new StringBuilder();
for (String word : words) {
result.append(new StringBuilder(word).reverse().toString() + " ");
}
return result.toString().trim();
}
6、LeetCode917:仅仅反转字母
给定一个字符串S,返回反转后的字符串,其中不是字母的字符都保留在原地,而所有字母的位置发生反转
示例1:
输入:"ab-cd"
输出:"dc-ba"
示例2:
输入:"a-bC-dEf-ghIj"
输出:"j-Ih-gfE-dCba"
示例3:
输入:"Test1ng-Leet=code-Q!"
输出:"Qedo1ct-eeLg=ntse-T!"
题解:
public String reverseOnlyLetters(String s) {
StringBuilder result = new StringBuilder();
int j = s.length() - 1;
for (int i = 0; i < s.length(); ++i) {
if (Character.isLetter(s.charAt(i))) {
while (!Character.isLetter(s.charAt(j)))
j--;
result.append(s.charAt(j--));
} else {
result.append(s.charAt(i));
}
}
return result.toString();
}
三、异位词问题
1、LeetCode242:有效的字母异位词
给定两个字符串s和t,编写一个函数来判断t是否是s的字母异位词
示例1:
输入: s = "anagram", t = "nagaram"
输出: true
示例2:
输入: s = "rat", t = "car"
输出: false
题解:
public boolean isAnagram(String s, String t) {
if (s.length() != t.length()) return false;
int[] array = new int[26];
for (int i = 0; i < s.length(); ++i) {
array[s.charAt(i) - 'a']++;
array[t.charAt(i) - 'a']--;
}
for (int i : array) {
if (i != 0) return false;
}
return true;
}
2、LeetCode49:字母异位词分组
给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串
示例:
输入: ["eat", "tea", "tan", "ate", "nat", "bat"],
输出:
[
["ate","eat","tea"],
["nat","tan"],
["bat"]
]
题解:
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> map = new HashMap<>();
for (String str : strs) {
char[] array = str.toCharArray();
Arrays.sort(array);
String key = String.valueOf(array);
if (map.containsKey(key)) {
map.get(key).add(str);
} else {
List<String> tmp = new ArrayList<>();
tmp.add(str);
map.put(key, tmp);
}
}
return new ArrayList<List<String>>(map.values());
}
3、LeetCode438:找到字符串中所有字母异位词
给定一个字符串s和一个非空字符串p,找到s中所有是p的字母异位词的子串,返回这些子串的起始索引
字符串只包含小写英文字母,并且字符串s和p的长度都不超过20100
说明:
字母异位词指字母相同,但排列不同的字符串
不考虑答案输出的顺序
示例1:
输入:
s: "cbaebabacd" p: "abc"
输出:
[0, 6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的字母异位词
起始索引等于 6 的子串是 "bac", 它是 "abc" 的字母异位词
示例2:
输入:
s: "abab" p: "ab"
输出:
[0, 1, 2]
解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的字母异位词
起始索引等于 1 的子串是 "ba", 它是 "ab" 的字母异位词
起始索引等于 2 的子串是 "ab", 它是 "ab" 的字母异位词
题解:
四、回文串问题
1、LeetCode125:验证回文串
给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写
示例1:
输入: "A man, a plan, a canal: Panama"
输出: true
示例2:
输入: "race a car"
输出: false
题解:
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.toLowerCase(s.charAt(i)) != Character.toLowerCase(s.charAt(j)))
return false;
i++;
j--;
}
return true;
}
2、LeetCode680:验证回文字符串 Ⅱ
给定一个非空字符串s,最多删除一个字符。判断是否能成为回文字符串
示例1:
输入: "aba"
输出: true
示例2:
输入: "abca"
输出: true
解释: 你可以删除c字符
题解:
public boolean validPalindrome(String s) {
char[] chars = s.toCharArray();
int i = 0;
int j = chars.length - 1;
//双指针循环找出不等于的字符索引
while (i < j && chars[i] == chars[j]) {
i++;
j--;
}
//删除左边循环判断
if (isValid(chars, i + 1, j)) return true;
//删除右边循环判断
if (isValid(chars, i, j - 1)) return true;
//如果上面都是false,那么结果肯定是false
return false;
}
//验证是否是回文
private boolean isValid(char[] chars, int i, int j) {
while (i < j) {
if (chars[i++] != chars[j--]) {
return false;
}
}
return true;
}
3、LeetCode5:最长回文子串
给定一个字符串s,找到s中最长的回文子串。你可以假设s的最大长度为1000
示例1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案
示例2:
输入: "cbbd"
输出: "bb"
题解:
public String longestPalindrome(String s) {
int n = s.length();
String result = "";
boolean[][] dp = new boolean[n][n];
for (int i = n - 1; i >= 0; --i) {
for (int j = i; j < n; ++j) {
dp[i][j] = s.charAt(i) == s.charAt(j) && (j - i < 2 || dp[i + 1][j - 1]);
if (dp[i][j] && j - i + 1 > result.length()) {
result = s.substring(i, j + 1);
}
}
}
return result;
}