From 3997009620af02419a1781bbbbe1540a7cc6e58e Mon Sep 17 00:00:00 2001 From: algorithmzuo Date: Wed, 5 Apr 2023 20:27:38 +0800 Subject: [PATCH] modify code --- .../class24/Code03_GasStation.java | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/体系学习班/class24/Code03_GasStation.java b/体系学习班/class24/Code03_GasStation.java index b80906f..d7b5e2c 100644 --- a/体系学习班/class24/Code03_GasStation.java +++ b/体系学习班/class24/Code03_GasStation.java @@ -27,6 +27,25 @@ public class Code03_GasStation { for (int i = 1; i < M; i++) { arr[i] += arr[i - 1]; } + // 举个例子说明一下 + // 比如纯能数组(也就是燃料 - 距离之后)的数组 : + // 纯能数组 = 3, 2,-6, 2, 3,-4, 6 + // 数组下标 = 0 1 2 3 4 5 6 + // 客观上说: + // 0位置不是良好出发点 + // 1位置不是良好出发点 + // 2位置不是良好出发点 + // 3位置是良好出发点 + // 4位置不是良好出发点 + // 5位置不是良好出发点 + // 6位置是良好出发点 + // 把数组增倍之后 : + // arr = 3, 2,-6, 2, 3,-4, 6, 3, 2,-6, 2, 3,-4, 6 + // 然后计算前缀和 : + // arr = 3, 5,-1, 1, 4, 0, 6, 9,11, 5, 7,10, 6,12 + // index = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 + // 这些就是上面发生的过程 + // 接下来生成长度为N的窗口 LinkedList w = new LinkedList<>(); for (int i = 0; i < N; i++) { while (!w.isEmpty() && arr[w.peekLast()] >= arr[i]) { @@ -34,6 +53,81 @@ public class Code03_GasStation { } w.addLast(i); } + // 上面的过程,就是先遍历N个数,然后建立窗口 + // arr =[3, 5,-1, 1, 4, 0, 6],9,11, 5, 7,10, 6,12 + // index = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 + // w中的内容如下: + // index: 2 5 6 + // value: -1 0 6 + // 左边是头,右边是尾,从左到右严格变大 + // 此时代表最原始的arr的这部分的数字: + // 原始的值 = [3, 2,-6, 2, 3,-4, 6],3, 2,-6, 2, 3,-4, 6 + // 原始下标 = 0 1 2 3 4 5 6 0 1 2 3 4 5 6 + // 上面这个窗口中,累加和最薄弱的点,就是w中最左信息 + // 也就是会累加出,-1这个值,所以会走不下去。 + // 宣告了此时0位置不是良好出发点。 + // 接下来的代码,就是依次考察每个点是不是良好出发点。 + // 目前的信息是: + // 计算的前缀和 : + // arr =[3, 5,-1, 1, 4, 0, 6],9,11, 5, 7,10, 6,12 + // index = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 + // w中的内容如下: + // index: 2 5 6 + // value: -1 0 6 + // 此时代表最原始的arr的这部分的数字: + // 原始的值 = [3, 2,-6, 2, 3,-4, 6],3, 2,-6, 2, 3,-4, 6 + // 原始下标 = 0 1 2 3 4 5 6 0 1 2 3 4 5 6 + // 现在让窗口往下移动 + // 计算的前缀和 : + // arr = 3,[5,-1, 1, 4, 0, 6, 9],11, 5, 7,10, 6,12 + // index = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 + // w中的内容如下: + // index: 2 5 6 7 + // value: -1 0 6 9 + // 此时代表最原始的arr的这部分的数字: + // 原始的值 = 3,[2,-6, 2, 3,-4, 6, 3],2,-6, 2, 3,-4, 6 + // 原始下标 = 0 1 2 3 4 5 6 0 1 2 3 4 5 6 + // 上面这个窗口中,累加和最薄弱的点,就是w中最左信息 + // 但是w最左的值是-1啊!而这个窗口中最薄弱的累加和是-4啊。 + // 对!所以最薄弱信息 = 窗口中的最左信息 - 窗口左侧刚出去的数(代码中的offset!) + // 所以,最薄弱信息 = -1 - 0位置的3(窗口左侧刚出去的数) = -4 + // 看到了吗?最薄弱信息,依靠这种方式,加工出来了! + // 宣告了此时1位置不是良好出发点。 + // 我们继续,让窗口往下移动 + // 计算的前缀和 : + // arr = 3, 5,[-1, 1, 4, 0, 6, 9,11], 5, 7,10, 6,12 + // index = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 + // w中的内容如下: + // index: 2 5 6 7 8 + // value: -1 0 6 9 11 + // 此时代表最原始的arr的这部分的数字: + // 原始的值 = 3, 2,[-6, 2, 3,-4, 6, 3, 2],-6, 2, 3,-4, 6 + // 原始下标 = 0 1 2 3 4 5 6 0 1 2 3 4 5 6 + // 上面这个窗口中,累加和最薄弱的点,就是w中最左信息 + // 但是w最左的值是-1啊!而这个窗口中最薄弱的累加和是-6啊。 + // 对!所以最薄弱信息 = 窗口中的最左信息 - 窗口左侧刚出去的数(代码中的offset!) + // 所以,最薄弱信息 = -1 - 1位置的5(窗口左侧刚出去的数) = -6 + // 看到了吗?最薄弱信息,依靠这种方式,加工出来了! + // 宣告了此时2位置不是良好出发点。 + // 我们继续,让窗口往下移动 + // 计算的前缀和 : + // arr = 3, 5, -1,[1, 4, 0, 6, 9,11, 5], 7,10, 6,12 + // index = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 + // w中的内容如下: + // index: 5 9 + // value: 0 5 + // 没错,9位置的5进来,让6、7、8位置从w的尾部弹出了, + // 同时原来在w中的2位置已经过期了,所以也弹出了,因为窗口左边界已经划过2位置了 + // 此时代表最原始的arr的这部分的数字: + // 原始的值 = 3, 2, -6,[2, 3,-4, 6, 3, 2, -6],2, 3,-4, 6 + // 原始下标 = 0 1 2 3 4 5 6 0 1 2 3 4 5 6 + // 上面这个窗口中,累加和最薄弱的点,就是w中最左信息 + // 但是w最左的值是0啊!而这个窗口中最薄弱的累加和是1啊 + // 对!所以最薄弱信息 = 窗口中的最左信息 - 窗口左侧刚出去的数(代码中的offset!) + // 所以,最薄弱信息 = 0 - 2位置的-1(窗口左侧刚出去的数) = 1 + // 看到了吗?最薄弱信息,依靠这种方式,加工出来了! + // 宣告了此时3位置是良好出发点。 + // 往下同理 boolean[] ans = new boolean[N]; for (int offset = 0, i = 0, j = N; j < M; offset = arr[i++], j++) { if (arr[w.peekFirst()] - offset >= 0) {