前言
刷5月16日的老题,简单题是出现次数一半的数字,因为刷过就换成leetcode第28题了。今天刷的是28.实现 strStr()、面试题63.股票的最大利润、233.数字 1 的个数。
28.实现 strStr()(容易):
题目描述:
实现 strStr() 函数。
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。
当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。
对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/implement-strstr
题解:
官方给的常规的解法是,对所有的子串进行逐一比较,用needle长度的窗口,寻找第一个符合条件的子串。
时间复杂度为O((N-L)*L),L是needle的长度,N是haystack的长度。
我采用的官方解法里的第二个,双指针法。优点是不需要对每个子串进行比较,只有当子串的第一位跟needle字符串的第一位相等是,才会开始比较。最优情况O(N),最坏情况O((N-L)*L),会更省时间。
看到讨论区里面各种KMP,有点没看懂,感觉双指针法应该是挺快的解法了,如果有更快更好理解的算法,还希望有大佬评论指点哈哈。
Code
var strStr = function(haystack, needle) {
if(needle=="") return 0;
if(needle.length>haystack.length) return -1;
for(let i=0;i<=haystack.length-needle.length;i++){
let index=0;
if(haystack[i]==needle[index]){
index++;
for(let j=i+1;j-i<needle.length;j++){
if(haystack[j]==needle[index]){
index++;
}else{
index=0;
}
}
if(index==needle.length)
return i;
else if(index==0)
continue;
}else
continue;
}
return -1;
};
面试题63.股票的最大利润(中等):
题目描述:
假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少?
示例 1:
输入: [7,1,5,3,6,4]
输出: 5
解释:
在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。
示例 2:
输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
限制:
0 <= 数组长度 <= 10^5
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/gu-piao-de-zui-da-li-run-lcof
题解:
看到这道题还以为是动态规划,不过仔细想想其实就是寻找一个买入点和卖出点之差足够大的序列。可以从头遍历,记录一个较小数的下标,然后向右搜索:如果是遇到比较小数大的数字,就更新卖出价格。遇到比较小数更小的数字,就更新较小数的下标。
时间复杂度为O(n)。
Code
//第一次AC(95%,100%)
var maxProfit = function(prices) {
if(prices.length==1) return 0;
let pre=0;
let max=0;
for(let i=1;i<prices.length;i++){
if(prices[i]>prices[pre])
max=Math.max(max,prices[i]-prices[pre]);
else{
pre=i;
}
}
return max;
};
233.数字 1 的个数(困难):
题目描述:
给定一个整数 n,计算所有小于等于 n 的非负整数中数字 1 出现的个数。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-digit-one/solution/shu-zi-1-de-ge-shu-by-leetcode
题解:
数学归纳,每个位及它的后一位上(比如说个位和十位),1的个数可以用公式
(
n
/
(
i
∗
10
)
)
∗
i
+
min
(
max
(
(
n mod (i*10)
)
−
i
+
1
,
0
)
,
i
)
(n/(i*10))*i+{\min(\max((\text{n mod (i*10)} )-i+1,0),i)}
(n/(i∗10))∗i+min(max((n mod (i*10))−i+1,0),i) 来表示。
Code
var countDigitOne = function(n) {
let count=0;
for(let i=1;i<=n;i*=10){
let divide=i*10;
count+=Math.floor(n/divide)*i+Math.min(Math.max(n%divide-i+1,0),i);
}
return count;
};