目录
如果你从本文中学习到丝毫知识,那么请您点点关注、点赞、评论和收藏
大家好,我是爱做梦的鱼,我是东北大学大数据实验班大三的小菜鸡,非常渴望优秀,羡慕优秀的人,个人博客为:爱做梦的鱼https://zihao.blog.csdn.net/
欢迎大家关注微信公众号【程序猿干货铺】
一群热爱技术并且向往优秀的程序猿同学,不喜欢水文,不喜欢贩卖焦虑,只喜欢谈技术,分享的都是技术干货。Talk is cheap. Show me the code
5460. 好数对的数目
给你一个整数数组 nums 。
如果一组数字 (i,j) 满足 nums[i] == nums[j] 且 i < j ,就可以认为这是一组 好数对 。
返回好数对的数目。
示例 1:
输入:nums = [1,2,3,1,1,3]
输出:4
解释:有 4 组好数对,分别是 (0,3), (0,4), (3,4), (2,5) ,下标从 0 开始
示例 2:
输入:nums = [1,1,1,1]
输出:6
解释:数组中的每组数字都是好数对
示例 3:
输入:nums = [1,2,3]
输出:0
提示:
1 <= nums.length <= 100
1 <= nums[i] <= 100
解题锦囊
Count how many times each number appears. If a number appears n times, then n * (n – 1) // 2 good pairs can be made with this number.
思路一:常规(未用解题锦囊)
代码
public class GoodNumber {
public static void main(String[] args) {
int[] a = {1, 2, 3, 1, 1, 3};
System.out.print(new GoodNumber().numIdenticalPairs(a));
}
public int numIdenticalPairs(int[] nums) {
int count = 0;
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
if (nums[i] == nums[j]) {
count++;
}
}
}
return count;
}
}
思路二:使用解题锦囊
5461. 仅含 1 的子串数
给你一个二进制字符串 s(仅由 ‘0’ 和 ‘1’ 组成的字符串)。
返回所有字符都为 1 的子字符串的数目。
由于答案可能很大,请你将它对 10^9 + 7 取模后返回。
示例 1:
输入:s = “0110111”
输出:9
解释:共有 9 个子字符串仅由 ‘1’ 组成
“1” -> 5 次
“11” -> 3 次
“111” -> 1 次
示例 2:
输入:s = “101”
输出:2
解释:子字符串 “1” 在 s 中共出现 2 次
示例 3:
输入:s = “111111”
输出:21
解释:每个子字符串都仅由 ‘1’ 组成
示例 4:
输入:s = “000”
输出:0
提示:
s[i] == ‘0’ 或 s[i] == ‘1’
1 <= s.length <= 10^5
解题锦囊
Count number of 1s in each consecutive-1 group. For a group with n consecutive 1s, the total contribution of it to the final answer is (n + 1) * n // 2.
代码
public class Only1s_2 {
public static void main(String[] args) {
System.out.println(new Only1s_2().numSub("0110111"));
System.out.println(new Only1s_2().numSub("101"));
System.out.println(new Only1s_2().numSub("111111"));
System.out.println(new Only1s_2().numSub("000"));
System.out.println(new Only1s_2().numSub("1111111111011010011"));
}
public int numSub(String s) {
long count = 0;
long sum = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '1') {
count++;
} else {
sum = (sum + count * (count + 1) / 2) % 1000000007;
count = 0;
}
}
sum = (sum + count * (count + 1) / 2) % 1000000007;
return (int) sum;
}
}
错误点
public int numSub(String s) {
int count = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '1') {
count++;
for (int j = i + 1; j < s.length(); j++) {
if (s.charAt(j) != '1') {
break;
} else {
count++;
}
}
}
}
return (int) (count % (1e9+ 7));
}
5211. 概率最大的路径
给你一个由 n 个节点(下标从 0 开始)组成的无向加权图,该图由一个描述边的列表组成,其中 edges[i] = [a, b] 表示连接节点 a 和 b 的一条无向边,且该边遍历成功的概率为 succProb[i] 。
指定两个节点分别作为起点 start 和终点 end ,请你找出从起点到终点成功概率最大的路径,并返回其成功概率。
如果不存在从 start 到 end 的路径,请 返回 0 。只要答案与标准答案的误差不超过 1e-5 ,就会被视作正确答案。
示例 1:
输入:n = 3, edges = [[0,1],[1,2],[0,2]], succProb = [0.5,0.5,0.2], start = 0, end = 2
输出:0.25000
解释:从起点到终点有两条路径,其中一条的成功概率为 0.2 ,而另一条为 0.5 * 0.5 = 0.25
示例 2:
输入:n = 3, edges = [[0,1],[1,2],[0,2]], succProb = [0.5,0.5,0.3], start = 0, end = 2
输出:0.30000
示例 3:
输入:n = 3, edges = [[0,1]], succProb = [0.5], start = 0, end = 2
输出:0.00000
解释:节点 0 和 节点 2 之间不存在路径
提示:
2 <= n <= 10^4
0 <= start, end < n
start != end
0 <= a, b < n
a != b
0 <= succProb.length == edges.length <= 2*10^4
0 <= succProb[i] <= 1
每两个节点之间最多有一条边
解题锦囊
- Multiplying probabilities will result in precision errors.
- Take log probabilities to sum up numbers instead of multiplying them.
- Use Dijkstra’s algorithm to find the minimum path between the two nodes after negating all costs.
代码
public class Path {
public double maxProbability(int n, int[][] edges, double[] succProb, int start, int end) {
ArrayList<double[]>[] graph = new ArrayList[n];
for (int i = 0; i < n; i++) {
graph[i] = new ArrayList<>();
}
for (int i = 0; i < edges.length; i++) {
graph[edges[i][0]].add(new double[] { edges[i][1], succProb[i] });
graph[edges[i][1]].add(new double[] { edges[i][0], succProb[i] });
}
PriorityQueue<double[]> queue = new PriorityQueue<>((a, b) -> Double.compare(b[1], a[1]));
boolean[] visited = new boolean[n];
queue.add(new double[] { start, 1 });
while (!queue.isEmpty()) {
double[] head = queue.remove();
if (head[0] == end) {
return head[1];
} else if (!visited[(int) head[0]]) {
visited[(int) head[0]] = true;
for (double[] next : graph[(int) head[0]]) {
queue.add(new double[] { next[0], head[1] * next[1] });
}
}
}
return 0;
}
}
5463. 服务中心的最佳位置
一家快递公司希望在新城市建立新的服务中心。公司统计了该城市所有客户在二维地图上的坐标,并希望能够以此为依据为新的服务中心选址:使服务中心 到所有客户的欧几里得距离的总和最小 。
给你一个数组 positions ,其中 positions[i] = [xi, yi] 表示第 i 个客户在二维地图上的位置,返回到所有客户的 欧几里得距离的最小总和 。
换句话说,请你为服务中心选址,该位置的坐标 [xcentre, ycentre] 需要使下面的公式取到最小值:
与真实值误差在 10^-5 之内的答案将被视作正确答案。
示例 1:
输入:positions = [[0,1],[1,0],[1,2],[2,1]]
输出:4.00000
解释:如图所示,你可以选 [xcentre, ycentre] = [1, 1] 作为新中心的位置,这样一来到每个客户的距离就都是 1,所有距离之和为 4 ,这也是可以找到的最小值。
示例 2:
输入:positions = [[1,1],[3,3]]
输出:2.82843
解释:欧几里得距离可能的最小总和为 sqrt(2) + sqrt(2) = 2.82843
示例 3:
输入:positions = [[1,1]]
输出:0.00000
示例 4:
输入:positions = [[1,1],[0,0],[2,0]]
输出:2.73205
解释:乍一看,你可能会将中心定在 [1, 0] 并期待能够得到最小总和,但是如果选址在 [1, 0] 距离总和为 3
如果将位置选在 [1.0, 0.5773502711] ,距离总和将会变为 2.73205
当心精度问题!
示例 5:
输入:positions = [[0,1],[3,2],[4,5],[7,6],[8,9],[11,1],[2,12]]
输出:32.94036
解释:你可以用 [4.3460852395, 4.9813795505] 作为新中心的位置
提示:
1 <= positions.length <= 50
positions[i].length == 2
0 <= positions[i][0], positions[i][1] <= 100
解题锦囊
- The problem can be reworded as, giving a set of points on a 2d-plane, return the geometric median.
- Loop over each triplet of points (positions[i], positions[j], positions[k]) where i < j < k, get the centre of the circle which goes throw the 3 points, check if all other points lie in this circle.
代码:
public class BestPosition {
public double getMinDistSum(int[][] positions) {
double[] current_point = new double[2];
for (int[] position : positions) {
current_point[0] += position[0];
current_point[1] += position[1];
}
current_point[0] /= positions.length;
current_point[1] /= positions.length;
double minimum_distance = distSum(current_point, positions, positions.length);
int k = 0;
while (k < positions.length) {
for (int i = 0; i < positions.length && i != k; i++) {
double[] newpoint = new double[2];
newpoint[0] = positions[i][0];
newpoint[1] = positions[i][1];
double newd = distSum(newpoint, positions, positions.length);
if (newd < minimum_distance) {
minimum_distance = newd;
current_point[0] = newpoint[0];
current_point[1] = newpoint[1];
}
}
k++;
}
double test_distance = 1000;
int flag = 0;
double[][] test_point = {{-1.0, 0.0}, {0.0, 1.0}, {1.0, 0.0}, {0.0, -1.0}};
while (test_distance > 0.0001) {
flag = 0;
for (int i = 0; i < 4; i++) {
double[] newpoint = new double[2];
newpoint[0] = current_point[0] + test_distance * test_point[i][0];
newpoint[1] = current_point[1] + test_distance * test_point[i][1];
double newd = distSum(newpoint, positions, positions.length);
if (newd < minimum_distance) {
minimum_distance = newd;
current_point[0] = newpoint[0];
current_point[1] = newpoint[1];
flag = 1;
break;
}
}
if (flag == 0)
test_distance /= 2;
}
return minimum_distance;
}
private double distSum(double[] p, int[][] arr, int n) {
double sum = 0;
for (int i = 0; i < n; i++) {
double distx = Math.abs(arr[i][0] - p[0]);
double disty = Math.abs(arr[i][1] - p[1]);
sum += Math.sqrt((distx * distx) + (disty * disty));
}
return sum;
}
}
来源:oschina
链接:https://my.oschina.net/u/4321646/blog/4371793