560 题目地址: leetcode.com/problems/su…
给定一个数组,再给定一个数k,问这个数组中有多少个子数组其和为k。
容易想到用前缀和。遍历前缀和的同时可以用一个哈希表记录每个前缀和出现了多少次,同时做计数即可。代码如下:
import java.util.HashMap;
import java.util.Map;
public class Solution {
public int subarraySum(int[] nums, int k) {
if (nums == null || nums.length == 0) {
return 0;
}
int[] preSum = new int[nums.length + 1];
for (int i = 0; i < nums.length; i++) {
preSum[i + 1] = preSum[i] + nums[i];
}
int res = 0;
// key代表前缀和,value代表该前缀和出现的次数
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < preSum.length; i++) {
// 如果前缀和preSum[i] - k出现过,说明存在子数组和为k,就累加进res
if (map.containsKey(preSum[i] - k)) {
res += map.get(preSum[i] - k);
}
// 更新前缀和出现的次数
map.put(preSum[i], map.getOrDefault(preSum[i], 0) + 1);
}
return res;
}
}
题目地址: leetcode.com/problems/mi…
给定一个正整数数组,再给定一个正数s ,求数组的最短子数组的和大于等于s ,返回其长度。
思路是,开快慢双指针i 和j ,并开一个变量来维护[ i : j ] 这个区间内的和(包括端点)。如果这个区间和大于等于s ,则更新最短长度,并让i 后移,同时区间和减去A [ i ] ;如果这个区间和小于s ,则右移j 。代码如下:
public class Solution {
public int minSubArrayLen(int s, int[] nums) {
int res = nums.length + 1, sum = 0;
for (int i = 0, j = 0; j < nums.length; ) {
// sum维护nums[i, ..., j]的和
sum += nums[j];
// 如果和大于等于s,说明区间[i : j]满足条件,更新长度,并让i后移
while (sum >= s) {
res = Math.min(res, j - i + 1);
sum -= nums[i];
i++;
}
// 上面的循环已经把以nums[j]结尾的满足条件的子数组都算过了,则让j后移
j++;
}
// res未得到更新,则说明不存在解,返回0;否则返回res
return res == nums.length + 1 ? 0 : res;
}
}
题目地址: leetcode.com/problems/va…
给定平面三个点的坐标,问其是否不在一条直线上。如果不在一条直线上则返回true。
两个向量( x 1 , y 1 ) , ( x 2 , y 2 ) 共线等价于行列式
public class Solution {
public boolean isBoomerang(int[][] points) {
int[] x = new int[2], y = new int[2];
for (int i = 1; i < points.length; i++) {
x[i - 1] = points[i][0] - points[0][0];
y[i - 1] = points[i][1] - points[0][1];
}
return x[0] * y[1] != x[1] * y[0];
}
}