LeetCode - 字符串基础问题
字符串基础问题
709. 转换成小写字母
实现函数 ToLowerCase(),该函数接收一个字符串参数 str,并将该字符串中的大写字母转换成小写字母,之后返回新的字符串。
示例 1:
输入: “Hello”
输出: “hello”
示例 2:
输入: “here”
输出: “here”
示例 3:
输入: “LOVELY”
输出: “lovely”
方法一:
通过 ASCII 码表操作字符串即可。
a-z:97-122
A-Z:65-90
0-9:48-57
class Solution_709 {
public String toLowerCase(String str) {
if (str == null || str.length() == 0) return str;
int len = str.length();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (c >= 'A' && c <= 'Z'){
sb.append((char)(c + 32));
}else {
sb.append(c);
}
}
return sb.toString();
}
public String toLowerCase2(String str) {
if (str == null || str.length() == 0) {
return str;
}
char[] ch = str.toCharArray();
for (int i = 0; i < str.length(); i++) {
if (ch[i] >= 'A' && ch[i] <= 'Z') {
ch[i] += 32;
}
}
return String.valueOf(ch);
}
}
方法2:位运算
思路:
用位运算的技巧:
大写变小写、小写变大写:字符 ^= 32;
大写变小写、小写变小写:字符 |= 32;
大写变大写、小写变大写:字符 &= 33;
class Solution {
public String toLowerCase(String str) {
if (str == null || str.length() == 0) {
return str;
}
char[] ch = str.toCharArray();
for (int i = 0; i < str.length(); i++) {
ch[i] |= 32;
}
return String.valueOf(ch);
}
}
58. 最后一个单词的长度
给定一个仅包含大小写字母和空格 ’ ’ 的字符串 s,返回其最后一个单词的长度。如果字符串从左向右滚动显示,那么最后一个单词就是最后出现的单词。
如果不存在最后一个单词,请返回 0 。
说明:一个单词是指仅由字母组成、不包含任何空格字符的 最大子字符串。
示例:
输入: “Hello World”
输出: 5
思路:
标签:字符串遍历
从字符串末尾开始向前遍历,其中主要有两种情况
第一种情况,以字符串 “Hello World” 为例,从后向前遍历直到遍历到头或者遇到空格为止,即为最后一个单词 “World” 的长度5
第二种情况,以字符串 "Hello World " 为例,需要先将末尾的空格过滤掉,再进行第一种情况的操作,即认为最后一个单词为 “World”,长度为5
所以完整过程为先从后过滤掉空格找到单词尾部,再从尾部向前遍历,找到单词头部,最后两者相减,即为单词的长度
时间复杂度:O(n),n为结尾空格和结尾单词总体长度
class Solution_58 {
public int lengthOfLastWord(String s) {
String y =s.trim();
if (y.length() == 0) return 0;
if (y.equals(" ")) return 0;
StringBuilder sb = new StringBuilder();
char[] c = y.toCharArray();
int count = 0;
for (int i = c.length - 1; i >= 0; i--) {
if (c[i] != ' '){
sb.append(c[i]);
}
if (c[i] == ' '){
break;
}
}
String m = sb.toString();
return m.length();
}
public int lengthOfLastWord2(String s){
if (s.length() == 0) return 0;
int count = 0;
for (int i = s.length() - 1; i >= 0; i--) {
char c = s.charAt(i);
if (c == ' ' && count == 0) continue;//如果当前count为0,证明后面都是空格‘ ’
if (c != ' '){
count++;
}else { //当count!= 0且不是空格,退出
break;
}
}
return count;
}
public int lengthOfLastWord3(String s) {
String y =s.trim();
if (y.length() == 0) return 0;
if (y.equals(" ")) return 0;
char[] c = y.toCharArray();
int count = 0;
for (int i = c.length - 1; i >= 0; i--) {
if (c[i] == ' ' && count == 0) continue; //如果当前count为0,证明后面都是空格‘ ’
if (c[i] != ' '){
count++;
}else {
break;
}
}
return count;
}
}
771. 宝石与石头
给定字符串J 代表石头中宝石的类型,和字符串 S代表你拥有的石头。 S 中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石。
J 中的字母不重复,J 和 S中的所有字符都是字母。字母区分大小写,因此"a"和"A"是不同类型的石头。
示例 1:
输入: J = “aA”, S = “aAAbbbb”
输出: 3
示例 2:
输入: J = “z”, S = “ZZ”
输出: 0
注意:
S 和 J 最多含有50个字母。
J 中的字符不重复。
解题思路
标签:字符串
首先对J进行遍历,将字符分别存到HashSet中,以便之后遍历S的时候查找
遍历S,并将每个字符与HashSet中的进行比对,如果存在,则结果ans++,遍历结束,返回ans
时间复杂度:O(m+n),m为J的长度,n为S的长度
暴力:
class Solution {
public int numJewelsInStones(String J, String S) {
int jewelsCount = 0;
int jewelsLength = J.length(), stonesLength = S.length();
for (int i = 0; i < stonesLength; i++) {
char stone = S.charAt(i);
for (int j = 0; j < jewelsLength; j++) {
char jewel = J.charAt(j);
if (stone == jewel) {
jewelsCount++;
break;
}
}
}
return jewelsCount;
}
}
哈希表:
class Solution_771 {
public int numJewelsInStones(String J, String S) {
Set<Character> set = new HashSet<>();
for (int i = 0; i < J.length(); i++) {
set.add(J.charAt(i));
}
int ans = 0;
for (int i = 0; i < S.length(); i++) {
if (set.contains(S.charAt(i))){
ans++;
}
}
return ans;
}
}
387. 字符串中的第一个唯一字符
给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。
示例:
s = “leetcode”
返回 0
s = “loveleetcode”
返回 2
思路:
哈希表统计频率返回第一个频率为1字符的下标即可
class Solution {
public int firstUniqChar(String s) {
HashMap<Character,Integer> hm = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
hm.put(s.charAt(i),hm.getOrDefault(s.charAt(i),0) + 1);
}
for (int i = 0; i < s.length(); i++) {
if (hm.get(s.charAt(i)) == 1){
return i;
}
}
return -1;
}
}
8. 字符串转换整数 (atoi)——重点
自动机
class Solution {
public int myAtoi(String str) {
//去掉str前后的空格
str = str.trim();
//如果字符串的长度为否为0
if (str.length() == 0){
return 0;
}
//输入种类(+, -, 0-9以及其他)
if (!Character.isDigit(str.charAt(0))
&& str.charAt(0) != '-' && str.charAt(0) != '+')
return 0;
/**
* 把字符串转换成字符数组
*/
Character[] arr = new Character[str.length()];
//定义应该输出的答案,ans
long ans = 0L;
//把字符串分成字符存到数组中
for (int i = 0; i < str.length(); i++) {
char kk = str.charAt(i);
arr[i] = kk;
//System.out.print(arr[i]);
//判断数组中元素的类型
//System.out.println( " 类型:" + arr[i].getClass().toString());
}
//判断数组的第一个字符是否是‘-’,定义一个flag,之后可以用三元表达式进行正负数的反转
boolean neg = arr[0].equals('-');
//不是‘-’开头,则判断之后的数字是否是数字
//判断第一个数数字是否是数字,是数字则返回0 ,不是数字则为1
int i = !Character.isDigit(str.charAt(0))? 1 : 0;
while (i < str.length() && Character.isDigit(str.charAt(i))) {
//把字符的数字转换成integer类型的数字,可以减去‘0’;
ans = ans * 10 + (str.charAt(i++) - '0');
//不是负数,数值比int大,则返回int的最长长度
if (!arr[0].equals('-') && ans > Integer.MAX_VALUE) {
ans = Integer.MAX_VALUE;
break;
}
//是负数,并且超过范围了,返回 INT_MAX (2^31 − 1) 或 INT_MIN (−2^31)
if (arr[0].equals('-') && ans > 1L + Integer.MAX_VALUE) {
//Integer.MAX_VALUE == 2^31 - 1,加1是因为负数则返回最小值-2^31(INT_MIN),最大值+1取反则为最小取值
ans = 1L + Integer.MAX_VALUE;
break;
}
}
if (arr[0].equals('-')){
ans = ans * (-1);
}
return (int) ans;
}
}
public int myAtoi(String str) {
int index = 0, sign = 1, total = 0;
//1. Empty string
if(str.length() == 0) return 0;
//2. Remove Spaces
while(str.charAt(index) == ' ' && index < str.length())
index ++;
//3. Handle signs
if(str.charAt(index) == '+' || str.charAt(index) == '-'){
sign = str.charAt(index) == '+' ? 1 : -1;
index ++;
}
//4. Convert number and avoid overflow
while(index < str.length()){
int digit = str.charAt(index) - '0';
if(digit < 0 || digit > 9) break;
//check if total will be overflow after 10 times and add digit21
if(Integer.MAX_VALUE/10 < total ||
Integer.MAX_VALUE/10 == total && Integer.MAX_VALUE %10 < digit)
return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
total = 10 * total + digit;
index ++;
}
return total * sign;
}