文章目录
[LeetCode]2020/11/10
LeetCode 209
题目描述
这是一道中等题,寻找长度最小且和为s的子数组
时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( 1 ) O(1) O(1)的解法
可以使用双指针,记录子数组开始处下标start和结尾处下标end。
public int minSubArrayLen(int s, int[] nums) {
int N = nums.length;
int start = 0, end = 0;
int ans = Integer.MAX_VALUE;
int sum = 0;
while(end < N){
sum += nums[end];
while(sum >= s){
ans = Math.min(ans, end-start+1);
sum -= nums[start];
start++;
}
end++;
}
return ans == Integer.MAX_VALUE?0:ans;
}
时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn),空间复杂度为 O ( n ) O(n) O(n)的解法
这个解法开辟了新空间来存储每一个位置的前缀和,形成一个递增的数组。对数组的每一个元素查找从其开始相加和大于s的最短长度。查找利用二分查找法,时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)
Java解题技巧
API
-
public static int binarySearch(Object[] a, Object key) // 如果数组中存在要查找对象,返回其所在下标 // 如果不存在则,计算当元素插入到数组的下标index,返回-(index+1)
public int minSubArrayLen(int s, int[] nums) {
int N = nums.length();
int [] sums = new int[N+1];
int ans = Integer.MAX_VALUE;
// 建立前缀和数组
for (int i = 1; i < N; i++){
sums[i] = sums[i-1] + nums[i-1];
}
for (int i = 1; i <= N; i++){
// 这里target的目的是,看从i开始到和大于s的数的bound在哪
int target = s + sums[i-1];
int bound = Arrays.binarySearch(sums, target);
if (bound < 0)
bound = -bound-1;
if (bound <= n){
ans = Math.min(ans, bound-i+1);
}
}
return ans == Integer.MAX_VALUE? 0:ans;
}
Python解题技巧
API
- bisect.bisect_left(a, x, lo=0, hi=len(a))
LeetCode 438
题目描述
这是一道中等题,找到字符串中所有字母异位词(anagrams)。
解题思路
这道题的一个解题思路是采用双指针的滑动窗口法。技巧是创建一个记录字符出现的数组。
public List<Integer> findAnagrams(String s, String p) {
int slen = s.length();
int plen = p.length();
List<Integer> res = new ArrayList<>();
int [] need = new int[26];
// 初始化need数组
for (int i = 0; i < plen; i++){
need[p.charAt(i)-'a'] += 1;
}
// 统计数组
int [] tmpneed = new int[26];
int l = 0, r = 0;
while( r < slen){
int curR = s.charAt(r)-'a';
tmpneed[curR]++;
r++;
while(tmpneed[curR] > need[curR]){
tmpneed[s.charAt(l) - 'a']--;
l++;
}
if (r-l == plen)
res.add(l);
}
return res;
}