题意:
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串
""
。
【输入样例】
strs = ["flower","flow","flight"]
【输出样例】
"fl"
解题思路:
横向扫描,依次遍历字符串数组中的每个字符串,对于每个遍历到的字符串,更新最长公共前缀,当遍历完所有的字符串后,即可得到字符数组中的最长公共前缀;
class Solution {
public String longestCommonPrefix(String[] strs) {
if(strs == null || strs.length == 0){
return "";
}
String strPre = strs[0];
int count = strs.length;
for(int i=1;i
时间: 击败了100.00%
内存: 击败了97.06%
解题思路:
二分查找,最长公共前缀的长度不会超过字符串数组中的最短字符串的长度。用minLength表示字符串数组中的最短字符串的长度,则可以在[0,minLength]的范围内通过二分查找得到最长公共前缀的长度。
class Solution {
public String longestCommonPrefix(String[] strs) {
if(strs == null || strs.length == 0){
return "";
}
int minLength = Integer.MAX_VALUE;
for(String str:strs){
minLength = Math.min(minLength,str.length());
}
int low = 0,high = minLength;
while(low < high){
int mid = (high - low + 1)/2 +low;
if(longPre(strs,mid)){
low = mid;
}else{
high = mid - 1;
}
}
return strs[0].substring(0,low);
}
private boolean longPre(String[] strs,int length){
String str0 = strs[0].substring(0,length);
int count = strs.length;
for(int i=1;i
时间: 击败了68.45%
内存: 击败了33.22%
题意:
给你一个字符串
s
,请你反转字符串中 单词 的顺序。单词 是由非空格字符组成的字符串。
s
中使用至少一个空格将字符串中的 单词 分隔开。返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意:输入字符串
s
中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
【输入样例】
s="the sky is blue "
【输出样例】
"blue is sky the"
解题思路:
1.遍历枚举,从字符串的最后一位开始遍历;
2.找到第一个非空字符,开始记录,当前索引end=i为找到单词的最后一位;
3. 继续遍历,直到找到下一个空格,当前索引start = ++i为找到的单词的上一位;
4.将单词截取,添加到新字符串中,注意单词后面要加一个空格;
5.遍历结束后,因为每个单词后面都加了一个空格,所以要把最后一位单词后的空格删了。
class Solution {
public String reverseWords(String s) {
StringBuffer str = new StringBuffer();
int start,end;//每个单词的开始和结束索引
for (int i = s.length() - 1; i >= 0; --i) {
//当遍历到不是空格的时候,开始记录单词
if(s.charAt(i) == ' '){
//不做任何处理,继续遍历下一位
continue;
}
//走到这一步,证明找到了不是空格的字符
end = i;
//继续遍历,找到下一个空格,证明找到了一个单词
while(i>=0 && s.charAt(i) != ' '){
--i;//不是空格且索引没越界,继续遍历
}
//跳出上述的while循环,证明i<0或者找到了空格了,把单词的开始索引记录一下
start = ++i;//因为while里执行了--i,这里要加上
str.append(s.substring(start,end+1)+" ");//每个单词后面有一个空格
}
//遍历结束了,要删掉最后一个单词后面的空格
str.deleteCharAt(str.length()-1);
return str.toString();
}
}
时间:击败了81.92%
内存:击败了44.08%
题意:
将一个给定字符串
s
根据给定的行数numRows
,以从上往下、从左到右进行 Z 字形排列。比如输入字符串为
"PAYPALISHIRING"
行数为3
时,排列如下:P A H N A P L S I I G Y I R之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:
"PAHNAPLSIIGYIR"
。
【输入样例】
s="PAYPALISHIRING",numRows =3
【输出样例】
"PAHNAPLSIIGYIR"
解题思路:
想用压缩二维矩阵解决,先打个地基,直接用二维矩阵实现,其实二维矩阵最难的就是根据numRows的值判断每一列填入的行号,因为每一列都有数,但是除了0,n-1,(n-1)*2等列数是全部填满(字符足够的情况下),其余是斜着填充的。
1. 当numRows=1时,只有一行,直接return;当numRows>=s.length()时,字符串只填入第一列,读取结果也一样,直接return;
2. 在矩阵上写字符,先向下写numRows个,然后向右上继续填写numRows-2个字符(占numRows-2列),-2是因为第一行和最后一行都不写入,因此,Z字形变换的周期T=numRows+numRows-2=2numRows-2,每个周期占用1+numRows-2=numRows-1列。
3. 共有s.length()/T个周期,向上取整,矩阵共有s.length()/T*(numRows-1)列
class Solution {
public String convert(String s, int numRows) {
int n = s.length(),r = numRows;
if(r == 1 || r >= n){
return s;
}
int t = 2*r-2;
int c = ((n-1)/t + 1) * (r-1);
char[][] mat = new char[r][c];
for(int i=0,x=0,y=0;i
时间:击败了14.23%
内存:击败了9.66%
解题思路:压缩二维矩阵
因为每次读取都是按行读取,将矩阵每一行初始化为空列表,每次往列表末尾添加字符
class Solution {
public String convert(String s, int numRows) {
int n = s.length(),r = numRows;
if(r == 1 || r >= n){
return s;
}
StringBuffer[] mat = new StringBuffer[r];
for(int i=0;i
时间:击败了45.67%
内存:击败了72.19%
题意:
给你两个字符串
haystack
和needle
,请你在haystack
字符串中找出needle
字符串的第一个匹配项的下标(下标从 0 开始)。如果needle
不是haystack
的一部分,则返回-1
。
【输入样例】
haystack="sadbutsad",needle="sad"
【输出样例】
0
解题思路:
emmmmm,先暴力枚举哈哈哈。
class Solution {
public int strStr(String haystack, String needle) {
int i,j,start;//分别指向haystack和needle字符串
for(i = 0;i
class Solution {
public int strStr(String haystack, String needle) {
//更简洁的代码,参考官方
int n = haystack.length(), m = needle.length();
for (int i = 0; i + m <= n; i++) {
boolean flag = true;
for (int j = 0; j < m; j++) {
if (haystack.charAt(i + j) != needle.charAt(j)) {
flag = false;
break;
}
}
if (flag) {
return i;
}
}
return -1;
}
}
/*作者:力扣官方题解
链接:https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/solutions/732236/shi-xian-strstr-by-leetcode-solution-ds6y/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*/
时间:击败了43.29%
内存:击败了34.26%
解题思路:KMP算法
哈哈哈我写不明白,参考b站代码随想录Carl的讲解
帮你把KMP算法学个通透!(理论篇)_哔哩哔哩_bilibili
int n = haystack.length(),m=needle.length();
int[] next = new int[m];//前缀数组
for(int i = 1, j = 0;i 0 && needle.charAt(i) != needle.charAt(j)){
j = next[j - 1];
}
if(needle.charAt(i) == needle.charAt(j)){
++j;
}
next[i] = j;
}
for(int i = 0, j= 0; i < n; ++i){
while(j > 0 && haystack.charAt(i) != needle.charAt(j)){
j = next[j-1];
}
if(haystack.charAt(i) == needle.charAt(j)){
++j;
}
if(j == m){
return i - m + 1;
}
}
时间:击败了100.00%
内存:击败了14.82%
题意:
如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。
字母和数字都属于字母数字字符。
给你一个字符串
s
,如果它是 回文串 ,返回true
;否则,返回false
。
【输入样例】
s="A man, a plan, a canal:Panama"
【输出样例】
true
解题思路:
双指针判断,记得遇到非字母数字字符跳过。
class Solution {
public boolean isPalindrome(String s) {
if(s == null){
return true;
}
s = s.toLowerCase();
int i=0,j=s.length()-1,flag=1;
while(i<=j){
while(i
时间:击败67.53%
内存:击败69.62%