Leetcode算法题

一:力扣第14题 编写一个函数来查找字符串数组中的最长公共前缀
官方解法:
##方法一:横向扫描

如果在尚未遍历完所有的字符串时,最长公共前缀已经是空串,则最长公共前缀一定是空串,因此不需要继续遍历剩下的字符串,直接返回空串即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Solution {
public String longestCommonPrefix(String[] strs) {
if (strs == null || strs.length == 0) {
return "";
}
String prefix = strs[0];
int count = strs.length;
for (int i = 1; i < count; i++) {
prefix = longestCommonPrefix(prefix, strs[i]);
if (prefix.length() == 0) {
break;
}
}
return prefix;
}

public String longestCommonPrefix(String str1, String str2) {
int length = Math.min(str1.length(), str2.length());
int index = 0;
while (index < length && str1.charAt(index) == str2.charAt(index)) {
index++;
}
return str1.substring(0, index);
}
}
复杂度分析
时间复杂度:O(mn)O(mn),其中 mm 是字符串数组中的字符串的平均长度,nn 是字符串的数量。最坏情况下,字符串数组中的每个字符串的每个字符都会被比较一次。
空间复杂度:O(1)O(1)。使用的额外空间复杂度为常数。
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/longest-common-prefix/solution/zui-chang-gong-gong-qian-zhui-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

#leetcode 用户灵魂画手
思路
标签:链表
当字符串数组长度为 0 时则公共前缀为空,直接返回
令最长公共前缀 ans 的值为第一个字符串,进行初始化
遍历后面的字符串,依次将其与 ans 进行比较,两两找出公共前缀,最终结果即为最长公共前缀
如果查找过程中出现了 ans 为空的情况,则公共前缀不存在直接返回
时间复杂度:O(s)O(s),s 为所有字符串的长度之和
代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public String longestCommonPrefix(String[] strs) {
if(strs.length == 0)
return "";
String ans = strs[0];
for(int i =1;i<strs.length;i++) {
int j=0;
for(;j<ans.length() && j < strs[i].length();j++) {
if(ans.charAt(j) != strs[i].charAt(j))
break;
}
ans = ans.substring(0, j);
if(ans.equals(""))
return ans;
}
return ans;
}
}
作者:guanpengchn
链接:https://leetcode-cn.com/problems/longest-common-prefix/solution/hua-jie-suan-fa-14-zui-chang-gong-gong-qian-zhui-b/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

#最易理解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Solution {
public String longestCommonPrefix(String[] strs) {
String s="";
int judge=1;
if(strs.length==0){//数组为空直接返回""
return s;
}
for(int i=0;i<strs[0].length();i++){
char a=strs[0].charAt(i);//直接选择第一个数组元素,依次取这个字符串的字符

for(int j=0;j<strs.length;j++){

if(i>=strs[j].length()){//因为每个字符串长度不同,防止溢出
judge=0;
break;
}

if(a!=strs[j].charAt(i)){
judge=0;//只要存在不同,直接退出
break;
}

else{
if(j==strs.length-1){
s=s+a;
}
}

}
if(judge==0){
break;
}
}

return s;
}
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/shancx/article/details/82746264

二:未排序正整数数组中累加和为给定值的最长子数组长度
给定一个数组arr,该数组无序,每个数正数,给定一个K,求arr的所有子数组中所有元素相加和为k的最长子数组的长度。

例如:arr=[1,2,1,1,1],k=3

结果是3,[1,1,1]的长度。

思路:

首先用两个位置来标记子数组左右两头,记为left与right,开始的时候都在数组的最左边即left=right=0,过程如下:

1,开始变量left=0,right=0,代表子数组arr[left,right];

2,变量sum始终表示子数组arr[left,right]的和,开始的时候sum= arr[0],即是arr[0,0]的和;

3,变量len一直记录累加和为k的所有子数组中最大子数组的长度,开始的时候len=0;

4,根据sum与k的比较结果决定是left移动还right移动。若干sum==K,说明arr[left,right]累加和为k,如果长度大于len,更新len

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package Array;

import java.util.Scanner;

/**
* Created by wuxiaosi on 2017/9/24.
*/
public class getMaxLength {
public static void main(String[] args){
int k=3;
int[] arr={1,2,1,1,1};
System.out.println(getMaxLengthK(arr,k));
}
public static int getMaxLengthK(int[] arr,int k){
if(arr==null||arr.length==0||k<=0){
return 0;
}
int left=0;
int right=0;
int sum=arr[0];
int len=0;
while(right<arr.length){
if(sum==k){
len = Math.max(len,right-left+1);
sum=sum-arr[left++];
}
else if(sum<k){
right++;//向右移动
if(right==arr.length){//right到数组边界长度,就break
break;
}
sum=sum+arr[right];
}else{
sum=sum-arr[left++];
}
}
return len;

}
}
————————————————
版权声明:本文为CSDN博主「wuxiaosi808」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wuxiaosi808/article/details/78079574

三 有两个整数数组A1,A2,设计函数求其两个数组的最大值和第二大的值
思路一:

1.获取最值需要进行比较,每一次比较都会有一个较大的值,因为该值的不确定性,通过一个变量进行临时存储。

2.让数组中的每一个元素都和这个变量中的值进行比较,如果大于变量中的值,就用该变量记录较大值。

3.当所有的元素都比较完成,那么该变量中的存储就是数组中的最大值了。

步骤:

1.定义变量,初始化为数组中的任意一个元素。

2.通过循环语句对数组进行遍历。

3.在变量过程中定义判断条件,如果遍历到的元素比变量中的元素大,就赋值给该变量。

注意:

通过定义一个功能来完成,以便提高代码的复用性。该功能结果为数组中的最大元素,未知内容为数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Test
{
public static void main(String[] args)
{
int[] arr1 = {9,5,6,3,1,2,8,7};
int max1 = getMax(arr1);
System.out.println("max1="+max1);
double[] arr2 = {9.0,5.0,6.0,3.0,1.0,2.0,8.0,7.0};
double max2 = getMax(arr2);
System.out.println("max2="+max2);

}
//获取int类型数组最大值
public static int getMax(int[] arr)
{
int max = arr[0];
for(int i=0;i<arr.length;i++)
{
if(arr[i]>max)
max = arr[i];
}
return max;
}
//获取double类型数组最大值,功能相似,以重载的形式存在
public static double getMax(double[] arr)
{
double max = arr[0];
for(int i=0;i<arr.length;i++)
{
if(arr[i]>max)
max = arr[i];
}
return max;
}
}

思路二:

1.定义变量,初始化为数组角标0。

2.通过循环语句对数组进行遍历。

3.在变量过程中定义判断条件,如果遍历到的元素比角标所在的元素中的数值大,就将较大值的角标赋值给变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Test
{
public static void main(String[] args)
{
int[] arr1 = {9,5,6,3,1,2,8,7};
int max1 = getMax(arr1);
System.out.println("max1="+max1);
double[] arr2 = {9.0,5.0,6.0,3.0,1.0,2.0,8.0,7.0};
double max2 = getMax(arr2);
System.out.println("max2="+max2);
}
//获取int类型数组最大值
public static int getMax(int[] arr)
{
int max = 0;
for(int i=0;i<arr.length;i++)
{
if(arr[i]>arr[max])
max = i;
}
return arr[max];
}
//获取double类型数组最大值,功能相似,以重载的形式存在
public static double getMax(double[] arr)
{
double max = 0;
for(int i=0;i<arr.length;i++)
{
if(arr[i]>arr[max])
max = i;
}
return arr[max];
}
}
————————————————
版权声明:本文为CSDN博主「Destiny_lt」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ytu_lt/article/details/70160598

四 翻转单词顺序列(I am a student.->student. a am I)

输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串”I am a student. “,则输出”student. a am I”
方法一:双指针
算法解析:
倒序遍历字符串 ss ,记录单词左右索引边界 ii , jj ;
每确定一个单词的边界,则将其添加至单词列表 resres ;
最终,将单词列表拼接为字符串,并返回即可。
复杂度分析:
时间复杂度 O(N)O(N) : 其中 NN 为字符串 ss 的长度,线性遍历字符串。
空间复杂度 O(N)O(N) : 新建的 list(Python) 或 StringBuilder(Java) 中的字符串总长度 \leq N≤N ,占用 O(N)O(N) 大小的额外空间。
代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public String reverseWords(String s) {
s = s.trim(); // 删除首尾空格
int j = s.length() - 1, i = j;
StringBuilder res = new StringBuilder();
while(i >= 0) {
while(i >= 0 && s.charAt(i) != ' ') i--; // 搜索首个空格
res.append(s.substring(i + 1, j + 1) + " "); // 添加单词
while(i >= 0 && s.charAt(i) == ' ') i--; // 跳过单词间空格
j = i; // j 指向下个单词的尾字符
}
return res.toString().trim(); // 转化为字符串并返回
}
}

方法二:分割 + 倒序
利用 “字符串分割”、“列表倒序” 的内置函数 (面试时不建议使用) ,可简便地实现本题的字符串翻转要求
复杂度分析:
时间复杂度 O(N)O(N) : 总体为线性时间复杂度,各函数时间复杂度和参考资料链接如下。
split() 方法: 为 O(N)O(N) ;
trim() 和 strip() 方法: 最差情况下(当字符串全为空格时),为 O(N)O(N) ;
join() 方法: 为 O(N)O(N) ;
reverse() 方法: 为 O(N)O(N) ;
空间复杂度 O(N)O(N) : 单词列表 strsstrs 占用线性大小的额外空间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public String reverseWords(String s) {
String[] strs = s.trim().split(" "); // 删除首尾空格,分割字符串
StringBuilder res = new StringBuilder();
for(int i = strs.length - 1; i >= 0; i--) { // 倒序遍历单词列表
if(strs[i].equals("")) continue; // 遇到空单词则跳过
res.append(strs[i] + " "); // 将单词拼接至 StringBuilder
}
return res.toString().trim(); // 转化为字符串,删除尾部空格,并返回
}
}

作者:jyd
链接:https://leetcode-cn.com/problems/fan-zhuan-dan-ci-shun-xu-lcof/solution/mian-shi-ti-58-i-fan-zhuan-dan-ci-shun-xu-shuang-z/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

方法二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class Solution {
public String ReverseSentence(String str)
{
//先单个单词反转,再整体反转。I am a student.》》I ma a .tneduts 》》student. a am I
if(str.length()==0)
return str;

char[]chs=str.toCharArray();

//对单个字符数组元素进行反转
int i=0,j=0;//定义两个指针进行遍历
while(j<=str.length()){

//以空格作为区分,对每个单词进行反转
if(j==str.length()||chs[j]==' '){//j==str.length()不要忘记
reverse(chs,i,j-1);
i=j+1;
}
//如果chs[j]!=' '那么继续遍历直到找到空格
j++;
}

//整体字符串反转
reverse(chs,0,str.length()-1);

return new String(chs);//学习

}
private void reverse(char[]ch,int i,int j){
while(i<j){
//反转交换,代码是一样的
char temp=ch[i];
ch[i]=ch[j];
ch[j]=temp;
i++;
j--;
}
}
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/hefenglian/article/details/79932709

最牛逼的解法:JavaScript

解法:先用trim()把字符串两端空格去掉,split(‘ ‘)把字符串切割成以空格为界限的单词块,filter()过滤掉数组中的纯空格,reverse()进行数组反转,join(‘ ‘)把数组变成中间只带一个空格的字符串

1
2
3
4
5
6
7
8
    var reverseWords = function (s) {
var str = s.trim().split(' ').filter(item => item!='').reverse().join(' ')
console.log(str)
};
作者:CHH_
链接:https://leetcode-cn.com/problems/fan-zhuan-dan-ci-shun-xu-lcof/solution/yi-xing-dai-ma-jie-jue-suo-you-by-chen-1wz/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

暴力求解法(百度百科)

1
2
3
4
暴力求解法, 又名直接带入法(Directly Calculating)它是已知最古老的算法之一,与"直观目测法","心灵感应法"并称世界三大不可思议数学计算法则, 其可追溯至3200年前,古老的埃及人便开始使用象形文字进行复杂的数学演算。它首次的文本出现是欧几里德的《几何原本》(第V卷,命题i和ii)中,而在中国则可以追溯至宋朝末年出现的沈括《梦溪笔谈》
暴力求解法的由来

在汉高祖时期有一个有趣的小故事是这样的:

“高祖年间,大将军韩信征讨突厥得胜,七月七日凯旋而归,其时举国腾。信进宫,高祖曰:’淮阴侯乃真人也,战无不功克,朕三年尝闻智勇,招为爱卿,果其然,甚好甚慰。’信曰:’大王聪明仁惠,敬贤礼士,江表英豪贤归附,臣听闻蜀地龙光射牛斗之墟,人杰多地灵,又适王举兵招马,无怪骏才星驰。’高祖对曰:’今汝方成大业,且问卿求?’信:’乃望众亲赐匹布,以二渐累。’回:’善,明日使文库之卿,方得人数。’隔日使返,帝问:”需布甚许?”曰:”臣不才,方得淮阴侯亲友八十五者,食客则七百七十六人之众,臣斗胆以树枝编排数之方得须七三万千三百二十馀一匹”帝惊道:”甚许!乃至库之空不能所期,淮阴岂谋他意?”遂隔日将信斩之,不知了了。”
暴力求解法的演算
1.例题:在地面上的同一1地点分别以速率V1、V2先后竖直像上抛出两个可视为质点的小球。第二个小球抛出后经过T时间与第一个小球相遇

1
2
3
4
5
6
7
8
设第一小球抛出后t0时间与第二小球相遇 (此时第二小球已运动T,T<t0)
因为 h1 = h2
v1t0 - 1/2g(t0)^2 = v2T -1/2gT^2
所以 T = (v2+√(v2^2-2g(v1t0 - 1/2g(t0)^2))) / g
又 T < v2/g
根据复杂计算
可得 T = (v2-√v2^2-v1^2) / g
所以 Tmax = (v2-√v2^2-v1^2) / g
{% if post.top %} 置顶 | {% endif %}