提交 b38124a8 编写于 作者: GreyZeng's avatar GreyZeng

all less num sub array

上级 fc0c2777
//There are N network nodes, labelled 1 to N.
//
// Given times, a list of travel times as directed edges times[i] = (u, v, w),
// where u is the source node, v is the target node,
// and w is the time it takes for a signal to travel from source to target.
//
// Now, we send a signal from a certain node K. How long will it take for all nodes to receive the signal?
// If it is impossible, return -1.
// 有 n 个网络节点,标记为 1 到 n。
// 给你一个列表 times,表示信号经过 有向 边的传递时间。 times[i] = (ui, vi, wi),其中 ui 是源节点,vi 是目标节点, wi
// 是一个信号从源节点传递到目标节点的时间。
// 现在,从某个节点 K 发出一个信号。需要多久才能使所有节点都收到信号?如果不能使所有节点收到信号,返回 -1 。
package leetcode.medium;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
// https://leetcode.cn/problems/network-delay-time/
// 笔记:
public class LeetCode_0743_NetworkDelayTime {
public static void main(String[] args) {
int[][] times = new int[][]{{1, 2, 1}, {2, 3, 2}, {1, 3, 1}};
int N = 3;
int K = 2;
System.out.println(networkDelayTime(times, N, K));
public static int networkDelayTime(int[][] times, int N, int K) {
// 转换成图结构
Graph graph = generate(times);
Node from = null;
// 找到开始节点
for (Node n : graph.nodes.values()) {
if (n.value == K) {
from = n;
}
}
public static int networkDelayTime(int[][] times, int N, int K) {
Graph graph = generate(times);
Node from = null;
for (Node n : graph.nodes.values()) {
if (n.value == K) {
from = n;
}
}
HashMap<Node, Integer> map = dijkstra2(from, N);
int sum = -1;
for (Map.Entry<Node, Integer> entry : map.entrySet()) {
if (entry.getValue() == 0) {
N--;
continue;
}
N--;
if (entry.getValue() == Integer.MAX_VALUE) {
return -1;
} else {
sum = Math.max(entry.getValue(), sum);
}
}
// 防止出现环的形状
// int[][] times = new int[][]{{1, 2, 1}, {2, 3, 2}, {1, 3, 1}};
// int N = 3;
// int K = 2;
if (N != 0) {
return -1;
}
return sum;
HashMap<Node, Integer> map = dijkstra2(from, N);
int sum = -1;
for (Map.Entry<Node, Integer> entry : map.entrySet()) {
if (entry.getValue() == 0) {
N--;
continue;
}
N--;
if (entry.getValue() == Integer.MAX_VALUE) {
return -1;
} else {
sum = Math.max(entry.getValue(), sum);
}
}
public static Graph generate(int[][] times) {
Graph graph = new Graph();
for (int[] time : times) {
int from = time[0];
int to = time[1];
int weight = time[2];
if (!graph.nodes.containsKey(from)) {
graph.nodes.put(from, new Node(from));
}
if (!graph.nodes.containsKey(to)) {
graph.nodes.put(to, new Node(to));
}
Node fromNode = graph.nodes.get(from);
Node toNode = graph.nodes.get(to);
Edge fromToEdge = new Edge(weight, fromNode, toNode);
//Edge toFromEdge = new Edge(weight, toNode, fromNode);
fromNode.nexts.add(toNode);
fromNode.out++;
//fromNode.in++;
//toNode.out++;
toNode.in++;
fromNode.edges.add(fromToEdge);
//toNode.edges.add(toFromEdge);
graph.edges.add(fromToEdge);
//graph.edges.add(toFromEdge);
}
return graph;
// 防止出现环的形状
// int[][] times = new int[][]{{1, 2, 1}, {2, 3, 2}, {1, 3, 1}};
// int N = 3;
// int K = 2;
if (N != 0) {
return -1;
}
return sum;
}
// 二维数组转换成自己熟悉的图结构
public static Graph generate(int[][] times) {
Graph graph = new Graph();
for (int[] time : times) {
int from = time[0];
int to = time[1];
int weight = time[2];
if (!graph.nodes.containsKey(from)) {
graph.nodes.put(from, new Node(from));
}
if (!graph.nodes.containsKey(to)) {
graph.nodes.put(to, new Node(to));
}
Node fromNode = graph.nodes.get(from);
Node toNode = graph.nodes.get(to);
Edge fromToEdge = new Edge(weight, fromNode, toNode);
// Edge toFromEdge = new Edge(weight, toNode, fromNode);
fromNode.nexts.add(toNode);
fromNode.out++;
// fromNode.in++;
// toNode.out++;
toNode.in++;
fromNode.edges.add(fromToEdge);
// toNode.edges.add(toFromEdge);
graph.edges.add(fromToEdge);
// graph.edges.add(toFromEdge);
}
public static class Graph {
public HashMap<Integer, Node> nodes;
public HashSet<Edge> edges;
return graph;
}
public Graph() {
nodes = new HashMap<>();
edges = new HashSet<>();
}
public static class Graph {
public HashMap<Integer, Node> nodes;
public HashSet<Edge> edges;
public Graph() {
nodes = new HashMap<>();
edges = new HashSet<>();
}
}
public static class Edge {
public int weight;
public Node from;
public Node to;
public static class Edge {
public int weight;
public Node from;
public Node to;
public Edge(int weight, Node from, Node to) {
this.weight = weight;
this.from = from;
this.to = to;
}
public Edge(int weight, Node from, Node to) {
this.weight = weight;
this.from = from;
this.to = to;
}
}
public static class Node {
public int value;
public int in;
public int out;
public ArrayList<Node> nexts;
public ArrayList<Edge> edges;
public static class Node {
public int value;
public int in;
public int out;
public ArrayList<Node> nexts;
public ArrayList<Edge> edges;
public Node(int value) {
this.value = value;
in = 0;
out = 0;
nexts = new ArrayList<>();
edges = new ArrayList<>();
}
public Node(int value) {
this.value = value;
in = 0;
out = 0;
nexts = new ArrayList<>();
edges = new ArrayList<>();
}
}
public static HashMap<Node, Integer> dijkstra(Node from) {
HashMap<Node, Integer> distanceMap = new HashMap<>();
distanceMap.put(from, 0);
HashSet<Node> selectedNodes = new HashSet<>();
Node minNode = getMinNode(distanceMap, selectedNodes);
while (minNode != null) {
int distance = distanceMap.get(minNode);
for (Edge neighbor : minNode.edges) {
Node to = neighbor.to;
if (!distanceMap.containsKey(to)) {
distanceMap.put(to, distance + neighbor.weight);
} else {
distanceMap.put(to, Math.min(distance + neighbor.weight, distanceMap.get(to)));
}
}
selectedNodes.add(minNode);
minNode = getMinNode(distanceMap, selectedNodes);
public static HashMap<Node, Integer> dijkstra(Node from) {
HashMap<Node, Integer> distanceMap = new HashMap<>();
distanceMap.put(from, 0);
HashSet<Node> selectedNodes = new HashSet<>();
Node minNode = getMinNode(distanceMap, selectedNodes);
while (minNode != null) {
int distance = distanceMap.get(minNode);
for (Edge neighbor : minNode.edges) {
Node to = neighbor.to;
if (!distanceMap.containsKey(to)) {
distanceMap.put(to, distance + neighbor.weight);
} else {
distanceMap.put(to, Math.min(distance + neighbor.weight, distanceMap.get(to)));
}
return distanceMap;
}
selectedNodes.add(minNode);
minNode = getMinNode(distanceMap, selectedNodes);
}
return distanceMap;
}
public static Node getMinNode(HashMap<Node, Integer> distanceMap, HashSet<Node> selectedNodes) {
int minDistance = Integer.MAX_VALUE;
Node minNode = null;
for (Map.Entry<Node, Integer> entry : distanceMap.entrySet()) {
Node n = entry.getKey();
int distance = entry.getValue();
if (!selectedNodes.contains(n) && distance < minDistance) {
minDistance = distance;
minNode = n;
}
}
return minNode;
public static Node getMinNode(HashMap<Node, Integer> distanceMap, HashSet<Node> selectedNodes) {
int minDistance = Integer.MAX_VALUE;
Node minNode = null;
for (Map.Entry<Node, Integer> entry : distanceMap.entrySet()) {
Node n = entry.getKey();
int distance = entry.getValue();
if (!selectedNodes.contains(n) && distance < minDistance) {
minDistance = distance;
minNode = n;
}
}
return minNode;
}
public static class NodeRecord {
public Node node;
public int distance;
public static class NodeRecord {
public Node node;
public int distance;
public NodeRecord(Node node, int distance) {
this.node = node;
this.distance = distance;
}
public NodeRecord(Node node, int distance) {
this.node = node;
this.distance = distance;
}
}
public static class NodeHeap {
private Node[] nodes; // 实际的堆结构
// key 某一个node, value 上面堆中的位置
private HashMap<Node, Integer> heapIndexMap;
// key 某一个节点, value 从源节点出发到该节点的目前最小距离
private HashMap<Node, Integer> distanceMap;
private int size; // 堆上有多少个点
public static class NodeHeap {
private Node[] nodes; // 实际的堆结构
// key 某一个node, value 上面堆中的位置
private HashMap<Node, Integer> heapIndexMap;
// key 某一个节点, value 从源节点出发到该节点的目前最小距离
private HashMap<Node, Integer> distanceMap;
private int size; // 堆上有多少个点
public NodeHeap(int size) {
nodes = new Node[size];
heapIndexMap = new HashMap<>();
distanceMap = new HashMap<>();
size = 0;
}
public NodeHeap(int size) {
nodes = new Node[size];
heapIndexMap = new HashMap<>();
distanceMap = new HashMap<>();
}
public boolean isEmpty() {
return size == 0;
}
public boolean isEmpty() {
return size == 0;
}
// 有一个点叫node,现在发现了一个从源节点出发到达node的距离为distance
// 判断要不要更新,如果需要的话,就更新
public void addOrUpdateOrIgnore(Node node, int distance) {
if (inHeap(node)) {
distanceMap.put(node, Math.min(distanceMap.get(node), distance));
insertHeapify(node, heapIndexMap.get(node));
}
if (!isEntered(node)) {
nodes[size] = node;
heapIndexMap.put(node, size);
distanceMap.put(node, distance);
insertHeapify(node, size++);
}
}
// 有一个点叫node,现在发现了一个从源节点出发到达node的距离为distance
// 判断要不要更新,如果需要的话,就更新
public void addOrUpdateOrIgnore(Node node, int distance) {
if (inHeap(node)) {
distanceMap.put(node, Math.min(distanceMap.get(node), distance));
insertHeapify(node, heapIndexMap.get(node));
}
if (!isEntered(node)) {
nodes[size] = node;
heapIndexMap.put(node, size);
distanceMap.put(node, distance);
insertHeapify(node, size++);
}
}
public NodeRecord pop() {
NodeRecord nodeRecord = new NodeRecord(nodes[0], distanceMap.get(nodes[0]));
swap(0, size - 1);
heapIndexMap.put(nodes[size - 1], -1);
distanceMap.remove(nodes[size - 1]);
// free C++同学还要把原本堆顶节点析构,对java同学不必
nodes[size - 1] = null;
heapify(0, --size);
return nodeRecord;
}
public NodeRecord pop() {
NodeRecord nodeRecord = new NodeRecord(nodes[0], distanceMap.get(nodes[0]));
swap(0, size - 1);
heapIndexMap.put(nodes[size - 1], -1);
distanceMap.remove(nodes[size - 1]);
// free C++同学还要把原本堆顶节点析构,对java同学不必
nodes[size - 1] = null;
heapify(0, --size);
return nodeRecord;
}
private void insertHeapify(Node node, int index) {
while (distanceMap.get(nodes[index])
< distanceMap.get(nodes[(index - 1) / 2])) {
swap(index, (index - 1) / 2);
index = (index - 1) / 2;
}
}
private void insertHeapify(Node node, int index) {
while (distanceMap.get(nodes[index]) < distanceMap.get(nodes[(index - 1) / 2])) {
swap(index, (index - 1) / 2);
index = (index - 1) / 2;
}
}
private void heapify(int index, int size) {
int left = index * 2 + 1;
while (left < size) {
int smallest = left + 1 < size && distanceMap.get(nodes[left + 1]) < distanceMap.get(nodes[left])
? left + 1
: left;
smallest = distanceMap.get(nodes[smallest])
< distanceMap.get(nodes[index]) ? smallest : index;
if (smallest == index) {
break;
}
swap(smallest, index);
index = smallest;
left = index * 2 + 1;
}
private void heapify(int index, int size) {
int left = index * 2 + 1;
while (left < size) {
int smallest =
left + 1 < size && distanceMap.get(nodes[left + 1]) < distanceMap.get(nodes[left])
? left + 1
: left;
smallest =
distanceMap.get(nodes[smallest]) < distanceMap.get(nodes[index]) ? smallest : index;
if (smallest == index) {
break;
}
swap(smallest, index);
index = smallest;
left = index * 2 + 1;
}
}
private boolean isEntered(Node node) {
return heapIndexMap.containsKey(node);
}
private boolean isEntered(Node node) {
return heapIndexMap.containsKey(node);
}
private boolean inHeap(Node node) {
return isEntered(node) && heapIndexMap.get(node) != -1;
}
private boolean inHeap(Node node) {
return isEntered(node) && heapIndexMap.get(node) != -1;
}
private void swap(int index1, int index2) {
heapIndexMap.put(nodes[index1], index2);
heapIndexMap.put(nodes[index2], index1);
Node tmp = nodes[index1];
nodes[index1] = nodes[index2];
nodes[index2] = tmp;
}
private void swap(int index1, int index2) {
heapIndexMap.put(nodes[index1], index2);
heapIndexMap.put(nodes[index2], index1);
Node tmp = nodes[index1];
nodes[index1] = nodes[index2];
nodes[index2] = tmp;
}
}
// 改进后的dijkstra算法
// 从head出发,所有head能到达的节点,生成到达每个节点的最小路径记录并返回
public static HashMap<Node, Integer> dijkstra2(Node head, int size) {
NodeHeap nodeHeap = new NodeHeap(size);
nodeHeap.addOrUpdateOrIgnore(head, 0);
HashMap<Node, Integer> result = new HashMap<>();
while (!nodeHeap.isEmpty()) {
NodeRecord record = nodeHeap.pop();
Node cur = record.node;
int distance = record.distance;
for (Edge edge : cur.edges) {
nodeHeap.addOrUpdateOrIgnore(edge.to, edge.weight + distance);
}
result.put(cur, distance);
}
return result;
// 改进后的dijkstra算法
// 从head出发,所有head能到达的节点,生成到达每个节点的最小路径记录并返回
public static HashMap<Node, Integer> dijkstra2(Node head, int size) {
NodeHeap nodeHeap = new NodeHeap(size);
nodeHeap.addOrUpdateOrIgnore(head, 0);
HashMap<Node, Integer> result = new HashMap<>();
while (!nodeHeap.isEmpty()) {
NodeRecord record = nodeHeap.pop();
Node cur = record.node;
int distance = record.distance;
for (Edge edge : cur.edges) {
nodeHeap.addOrUpdateOrIgnore(edge.to, edge.weight + distance);
}
result.put(cur, distance);
}
return result;
}
}
// 链接:https://www.nowcoder.com/questionTerminal/5fe02eb175974e18b9a546812a17428e
// 来源:牛客网
//
// 给定数组 arr 和整数 num,共返回有多少个子数组满足如下情况:
// max(arr[i...j]) - min(arr[i...j]) <= num
// max(arr[i...j])表示子数组arr[i...j]中的最大值,min[arr[i...j])表示子数组arr[i...j]中的最小值。
package nowcoder;
import java.util.LinkedList;
import java.util.Scanner;
// 笔记:https://www.cnblogs.com/greyzeng/p/16966417.html
// arr[L..R]达标,则arr中内部的任何一个子数组都达标
// arr[L..R]不达标,则arr扩充后肯定也不达标
// L...R 范围如果达标,其子数组个数为:R - L
public class NowCoder_AllLessNumSubArray {
// 必须以l位置作为左边界的情况下,有多少达标的数组
public static int getNum(int[] arr, int num) {
LinkedList<Integer> qMax = new LinkedList<>();
LinkedList<Integer> qMin = new LinkedList<>();
int ans = 0;
int l = 0;
int r = 0;
while (l < arr.length) {
while (r < arr.length) {
while (!qMax.isEmpty() && arr[qMax.peekLast()] <= arr[r]) {
qMax.pollLast();
}
qMax.addLast(r);
while (!qMin.isEmpty() && arr[qMin.peekLast()] >= arr[r]) {
qMin.pollLast();
}
qMin.addLast(r);
if (arr[qMax.peekFirst()] - arr[qMin.peekFirst()] > num) {
break;
}
r++;
}
// r是以l作为左边界,第一个不满足条件的位置
ans += (r - l);
// 弹出过期位置
if (!qMax.isEmpty() && qMax.peekFirst() == l) {
qMax.pollFirst();
}
// 弹出过期位置
if (!qMin.isEmpty() && qMin.peekFirst() == l) {
qMin.pollFirst();
}
l++;
}
return ans;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int m = in.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = in.nextInt();
}
System.out.println(getNum(arr,m));
in.close();
}
}
//链接:https://www.nowcoder.com/questionTerminal/5fe02eb175974e18b9a546812a17428e
// 来源:牛客网
//
// 给定数组 arr 和整数 num,共返回有多少个子数组满足如下情况:
// max(arr[i...j]) - min(arr[i...j]) <= num
// max(arr[i...j])表示子数组arr[i...j]中的最大值,min[arr[i...j])表示子数组arr[i...j]中的最小值。
//
//
// 输入描述:
//
// 第一行输入两个数 n 和 num,其中 n 表示数组 arr 的长度
// 第二行输入n个整数XiX_iXi​,表示数组arr中的每个元素
//
//
//
// 输出描述:
//
// 输出给定数组中满足条件的子数组个数
//
// 示例1
// 输入
//
// 5 2
// 1 2 3 4 5
//
// 输出
//
// 12
//
//
// 备注:
//
// 1≤n≤1000000
// −1000000≤arri≤1000000
// 0≤num≤20000000
package snippet;
import java.util.LinkedList;
// arr[L..R]达标,则arr中内部的任何一个子数组都达标
// arr[L..R]不达标,则arr扩充后肯定也不达标
// L...R 范围如果达标,其子数组个数为:R - L
public class Code_0087_AllLessNumSubArray {
// 必须以l位置作为左边界的情况下,有多少达标的数组
public static int getNum(int[] arr, int num) {
LinkedList<Integer> qMax = new LinkedList<>();
LinkedList<Integer> qMin = new LinkedList<>();
int ans = 0;
int l = 0;
int r = 0;
while (l < arr.length) {
while (r < arr.length) {
while (!qMax.isEmpty() && arr[qMax.peekLast()] <= arr[r]) {
qMax.pollLast();
}
qMax.addLast(r);
while (!qMin.isEmpty() && arr[qMin.peekLast()] >= arr[r]) {
qMin.pollLast();
}
qMin.addLast(r);
if (arr[qMax.peekFirst()] - arr[qMin.peekFirst()] > num) {
break;
}
r++;
}
// r是以l作为左边界,第一个不满足条件的位置
ans += (r - l);
// 弹出过期位置
if (!qMax.isEmpty() && qMax.peekFirst() == l) {
qMax.pollFirst();
}
// 弹出过期位置
if (!qMin.isEmpty() && qMin.peekFirst() == l) {
qMin.pollFirst();
}
l++;
}
return ans;
}
// 暴力的对数器方法
public static int right(int[] arr, int sum) {
if (arr == null || arr.length == 0 || sum < 0) {
return 0;
}
int N = arr.length;
int count = 0;
for (int L = 0; L < N; L++) {
for (int R = L; R < N; R++) {
int max = arr[L];
int min = arr[L];
for (int i = L + 1; i <= R; i++) {
max = Math.max(max, arr[i]);
min = Math.min(min, arr[i]);
}
if (max - min <= sum) {
count++;
}
}
}
return count;
}
// for test
public static int[] generateRandomArray(int maxLen, int maxValue) {
int len = (int) (Math.random() * (maxLen + 1));
int[] arr = new int[len];
for (int i = 0; i < len; i++) {
arr[i] = (int) (Math.random() * (maxValue + 1)) - (int) (Math.random() * (maxValue + 1));
}
return arr;
}
// for test
public static void printArray(int[] arr) {
if (arr != null) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
}
public static void main(String[] args) {
int maxLen = 100;
int maxValue = 200;
int testTime = 100000;
System.out.println("测试开始");
for (int i = 0; i < testTime; i++) {
int[] arr = generateRandomArray(maxLen, maxValue);
int sum = (int) (Math.random() * (maxValue + 1));
int ans1 = right(arr, sum);
int ans2 = getNum(arr, sum);
if (ans1 != ans2) {
System.out.println("Oops!");
printArray(arr);
System.out.println(sum);
System.out.println(ans1);
System.out.println(ans2);
break;
}
}
System.out.println("测试结束");
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册