LeetCode28. 实现 strStr()
#字符串
题目描述
实现 strStr() 函数。
给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串出现的第一个位置(下标从 0 开始)。如果不存在,则返回 -1 。
说明:
当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。
对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与 C 语言的 strstr() 以及 Java 的 indexOf() 定义相符。
1 | 示例 1: |
解题思路
直接一次遍历比对即可
时间复杂度
$O(M-N)$
解题代码
1 | func strStr(haystack string, needle string) int { |
LeetCode1442. 形成两个异或相等数组的三元组数目
#位运算 #前缀异或
题目描述
给你一个整数数组 arr 。
现需要从数组中取三个下标 i、j 和 k ,其中 (0 <= i < j <= k < arr.length) 。
a 和 b 定义如下:
a = arr[i] ^ arr[i + 1] ^ … ^ arr[j - 1]
b = arr[j] ^ arr[j + 1] ^ … ^ arr[k]
注意:^ 表示 按位异或 操作。
请返回能够令 a == b 成立的三元组 (i, j , k) 的数目。
1 | 示例 1: |
解题思路
(1). 一开始很直观想到枚举全部三元组,然后再根据规则,从 i
遍历到 j-1
,再从 j
遍历到 k
来判断是否是合法三元组,但是时间复杂度是 $O(N^4)$;
(2). 然后思考优化的思路,那么在哪里可以简化呢?其实可以从异或的过程入手,我们可能比较熟悉 前缀和
了,那么同样可以思考到 前缀异或
:
1 | 假设我们有数组 arr: [1, 2, 3, 4, 7, 9]; |
这样可以有效节省时间开销,此时时间复杂度是 $O(N^3)$;
(3). 再考虑进行优化,利用异或的性质 题目让我们找到满足 a == b
的坐标,那么当 a
等于 b
时满足什么性质? a ⊕ b = 0
! 我们就可以得到 arr[i] ^...^ arr[j-1]^ arr[j] ^...^ arr[k] = 0
。因此在 i
之前的前缀异或值到 k
时不会变。因为[i,k]
的区间异或值为0,可以得到: xor[i] == preXor[k+1]
。其另一点重点在于在区间 [i, k]
内 j
在哪并不重要, 因为无论 j
在哪,i
到 k
的异或值都等于 0,不影响结果。此时时间复杂度是 O(N^2)
(4). 对于下标 k
,若下标 i=$i_1$,$i_2$,…,$i_m$ 时均满足 $xor_i$ = $xor_{k+1}$,根据之前方法,这些二元组 $(i_1,k),(i_2,k),…,(i_m,k)$对答案的贡献之和为:
$\left(k-i_{1}\right)+\left(k-i_{2}\right)+\cdots+\left(k-i_{m}\right)=m \cdot k-\left(i_{1}+i_{2}+\cdots+i_{m}\right)$
也就是说,当遍历下标 k
时,我们需要知道所有满足$xor_i$ = $xor_{k+1}$ 的
- 下标
i
的出现次数m
- 下标
i
之和
我们可以在计算异或前缀和的同时计算答案,从而做到仅遍历arr
一次就计算出答案。此时时间复杂度可以压缩到 $O(N)$
解题代码
暴力:
1 | func countTriplets(arr []int) int { |
暴力+前缀和优化:
1 | func countTriplets(arr []int) int { |
利用异或性质两次遍历
1 | func countTriplets(arr []int) int { |
一次遍历
1 | func countTriplets(arr []int) (ans int) { |
- Post title:早起刷题(Day 10)
- Post author:洪笳淏
- Create time:2022-04-11 06:00:00
- Post link:https://jiahaohong1997.github.io/2022/04/11/早起刷题(Day 10)/
- Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.