写在前面
对于字符串数组,我们一般会为他们分配两个长度为12字节的空间,并把"Hello world"的内容分复制到数组中去,因此它们是两个初始地址不同的数组,因此这两个字符串数组的值也不同。
对于字符串来说,我们无需给他们分配内存,只要这两个常量的值相同,那么他们就是相同的。
面试题5 替换空格
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
示例 1:
输入:s = “We are happy.”
输出:“We%20are%20happy.”
class Solution {
public String replaceSpace(String s) {
StringBuilder builder = new StringBuilder();
for(char c : s.toCharArray()){
if(c == ' ') builder.append("%20");
//append函数相当于+
else builder.append(c);
}
return builder.toString();
}
}
class Solution {
public String replaceSpace(String s) {
return s.replace(" ","%20");
}
}
class Solution {
public String replaceSpace(String s) {
int length = s.length();
char[] array = new char[length * 3];
int size = 0;
for (int i = 0; i < length; i++) {
char c = s.charAt(i);
if (c == ' ') {
array[size++] = '%';
array[size++] = '2';
array[size++] = '0';
} else {
array[size++] = c;
}
}
String newStr = new String(array, 0, size);
//把array数组从0取到size,然后变为String
return newStr;
}
}
242. 有效的字母异位词
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
示例 1:
输入: s = “anagram”, t = “nagaram”
输出: true
示例 2:
输入: s = “rat”, t = “car”
输出: false
class Solution {
public boolean isAnagram(String s, String t) {
if(s.length()!= t.length()) return false;
int[] counter = new int[26];
for(int i = 0; i<s.length(); i++){
counter[s.charAt(i)-'a']++;
counter[t.charAt(i)-'a']--;
}
for(int count : counter){
if(count !=0) return false;
}
return true;
}
}
class Solution {
public boolean isAnagram(String s, String t) {
if(s.length() != t.length()) return false;
char[] S = s.toCharArray();
char[] T = t.toCharArray();
Arrays.sort(S);
Arrays.sort(T);
for(int i = 0; i < S.length; i++){
if(S[i] != T[i]) return false;
}
return true;
}
}
409. 最长回文串
给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。
在构造过程中,请注意区分大小写。比如 “Aa” 不能当做一个回文字符串。
注意:
假设字符串的长度不会超过 1010。
示例 1:
输入:
“abccccdd”
输出:
7
解释:
我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。
class Solution {
//在字符串中有重复的字符,如果重复的字符是奇数,就对称放
//如果是偶数的话就放中间
//因此这道题就转变成了求重复字符的数量
public int longestPalindrome(String s) {
//ASCII表 a-z:97-122,A-Z:65-90,0-9:48-57。
// 将每个字母都放在不同的位置上,如果该位置有字母则加1
int[] counter = new int[58];
for(int i = 0; i< s.length(); i++){
counter[s.charAt(i)-'A']++;
}
// a 1 b 1 c 4 d 2 1142
int result = 0;
int mark = 0;//记录奇数字母的位置
for(int count : counter){
if(count % 2 ==1){
//说明是奇数个
mark+=1;
}
result += count/2; //0021
}
if(mark>0) return result*2+1;
return result*2;
}
}
class Solution {
//在字符串中有重复的字符,如果重复的字符是奇数,就对称放
//如果是偶数的话就放中间
//因此这道题就转变成了求重复字符的数量
public int longestPalindrome(String s) {
//hashmap
Map<Character, Integer> map = new HashMap<>();
for(Character c : s.toCharArray()){
map.put(c, map.getOrDefault(c,0)+1);
//getOrDefalut()意为map中有指定的key就返回对应的value,如果没有就返回默认值
//而默认值就是第二个参数的值
//上题的意思就是如果有c变量这个字母就输出其对应的value值,没有就输出0
}
int mark =0; int res=0;
for(Integer count : map.values()){
if(count %2 == 1) mark++;
res += count/2;
}
if(mark > 0) return res*2+1;
return res*2;
}
}
205. 同构字符串
给定两个字符串 s 和 t,判断它们是否是同构的。
如果 s 中的字符可以被替换得到 t ,那么这两个字符串是同构的。
所有出现的字符都必须用另一个字符替换,同时保留字符的顺序。两个字符不能映射到同一个字符上,但字符可以映射自己本身。
示例 1:
输入: s = “egg”, t = “add”
输出: true
示例 2:
输入: s = “foo”, t = “bar”
输出: false
示例 3:
输入: s = “paper”, t = “title”
输出: true
class Solution {
public boolean isIsomorphic(String s, String t) {
return isIso(s,t) && isIso(t,s);
}
public boolean isIso(String s, String t){
if(s.length() != t.length()) return false;
HashMap<Character,Character> map = new HashMap<>();
for(int i = 0 ; i < s.length(); i++){
char c1 = s.charAt(i);
char c2 = t.charAt(i);
if(map.containsKey(c1)){
if(map.get(c1) != c2) return false;
}else{
map.put(c1,c2);
}
}
return true;
}
}
696. 计数二进制子串
给定一个字符串 s,计算具有相同数量0和1的非空(连续)子字符串的数量,并且这些子字符串中的所有0和所有1都是组合在一起的。
重复出现的子串要计算它们出现的次数。
示例 1 :
输入: “00110011”
输出: 6
解释: 有6个子串具有相同数量的连续1和0:“0011”,“01”,“1100”,“10”,“0011” 和 “01”。
请注意,一些重复出现的子串要计算它们出现的次数。
另外,“00110011”不是有效的子串,因为所有的0(和1)没有组合在一起。
示例 2 :
输入: “10101”
输出: 4
解释: 有4个子串:“10”,“01”,“10”,“01”,它们具有相同数量的连续1和0。
class Solution {
public int countBinarySubstrings(String s) {
int i = 0;
int j = s.length();
int pre = 0, cur =0;
char[] S = s.toCharArray();
int res =0;
while(i<j){
pre = cur;//把cur记录到的数字传给pre
cur =1;//cur继续从1开始计数
i+=1;
while(i<j && S[i] == S[i-1]){
cur++;//记录连续0或者连续1的值
i++;
}
res += Math.min(cur, pre);
}
return res;
}
}
392.判断子序列
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
你可以认为 s 和 t 中仅包含英文小写字母。字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符串(长度 <=100)。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。
示例 1:
s = “abc”, t = “ahbgdc”
返回 true.
示例 2:
s = “axc”, t = “ahbgdc”
返回 false.
class Solution {
public boolean isSubsequence(String s, String t) {
int i=0;
int j=0;
while(i < s.length()&& j<t.length()){
if(s.charAt(i)== t.charAt(j)){
i++;
j++;
}else{
j++;
}
}
return i==s.length();
}
}
8. 字符串转数组
请你来实现一个 atoi 函数,使其能将字符串转换成整数。
首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。
当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。
该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。
注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。
在任何情况下,若函数不能进行有效的转换时,请返回 0。
说明:
假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,请返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。
示例 1:
输入: “42”
输出: 42
示例 2:
输入: " -42"
输出: -42
解释: 第一个非空白字符为 ‘-’, 它是一个负号。
我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。
示例 3:
输入: “4193 with words”
输出: 4193
解释: 转换截止于数字 ‘3’ ,因为它的下一个字符不为数字。
示例 4:
输入: “words and 987”
输出: 0
解释: 第一个非空字符是 ‘w’, 但它不是数字或正、负号。
因此无法执行有效的转换。
示例 5:
输入: “-91283472332”
输出: -2147483648
解释: 数字 “-91283472332” 超过 32 位有符号整数范围。
因此返回 INT_MIN (−231) 。
class Solution {
public int myAtoi(String str) {
//将题目分成两部分:数字之前 和 数字之后
//数字之前需要考虑:1.跳过所有空格;2.非数字字符直接返回0;3.保留正负号信息
//数字之后的字符:如果不是数字,停止转换
//总体考虑转换之后的数字是否越界--为了避免用long
//1.跳过所有空格
str = str.trim();//trim函数去掉字符串两端的空格
if(str == null || str.length()==0) return 0;
int sign = 1;//用sign来记录正负符号
int index = 0;//用一个index指针挨个查找当前的character
char c = str.charAt(0);
if(c=='+'){
sign = 1;
index++;
}else if(c=='-'){
sign = -1;
index++;
}
long ans = 0;//用long防止越界,long是int类型长度的二倍`在这里插入代码片`
// ans初始为0,如果数字之前出现字符直接返回0;数字之后也是0.
for(int i = index ; i<str.length(); i++){
//非数字字符
if(!Character.isDigit(str.charAt(i))){
return (int)ans*sign;
}
ans = ans*10+ str.charAt(i)-'0';
//讨论数字是否越界
if(sign == 1 && ans>Integer.MAX_VALUE){
return Integer.MAX_VALUE;
}
if(sign == -1 && (-1)*ans<Integer.MIN_VALUE){
return Integer.MIN_VALUE;
}
}
return (int) ans*sign;//return 的时候进行一个强转
}
}