diff --git a/src/main/java/com/dota/binarySearch/_2071/Solution.java b/src/main/java/com/dota/binarySearch/_2071/Solution.java new file mode 100644 index 0000000..005e005 --- /dev/null +++ b/src/main/java/com/dota/binarySearch/_2071/Solution.java @@ -0,0 +1,55 @@ +package com.dota.binarySearch._2071; + +import java.util.ArrayDeque; +import java.util.Arrays; +import java.util.Deque; + +class Solution { + public static void main(String[] args) { + new Solution().maxTaskAssign(new int[]{15, 10, 30}, new int[]{10, 10, 10}, 3, 10); + } + + public int maxTaskAssign(int[] tasks, int[] workers, int pills, int strength) { + Arrays.sort(tasks); + Arrays.sort(workers); + + int left = 0; + int right = Math.min(tasks.length, workers.length) + 1; + while (left + 1 < right) { + int mid = (left + right) >>> 1; + if (check(tasks, workers, pills, strength, mid)) { + left = mid; + } else { + right = mid; + } + } + return left; + } + + private boolean check(int[] tasks, int[] workers, int pills, int strength, int k) { + int i = 0; + Deque stack = new ArrayDeque<>(); + for (int j = workers.length - k; j < workers.length; j++) { + int w = workers[j]; + while(i < k && w + strength >= tasks[i]) { + stack.add(tasks[i]); + i++; + } + + if (stack.isEmpty()) { + return false; + } + if (w >= stack.peekFirst()) { + stack.pollFirst(); + continue; + } + if (pills ==0) { + return false; + } + pills--; + stack.pollLast(); + } + + return true; + } +} \ No newline at end of file diff --git a/src/main/java/com/dota/binarySearch/_3007/Solution.java b/src/main/java/com/dota/binarySearch/_3007/Solution.java new file mode 100644 index 0000000..e2bb728 --- /dev/null +++ b/src/main/java/com/dota/binarySearch/_3007/Solution.java @@ -0,0 +1,43 @@ +package com.dota.binarySearch._3007; + +import java.util.HashMap; +import java.util.Map; + +class Solution { + Map map ; + public long findMaximumNumber(long k, int x) { + map = new HashMap<>(); + long l = 1, r = (k + 1) << x; + while(l + 1 < r) { + long mid = l + (r - l) / 2; + if (check(k, x, mid)) { + l = mid; + } else { + r = mid; + } + } + return l; + } + boolean check(long k, int x, long num) { + long res = 0; + for (long i = 1; i <= num ; i++) { + res += df(i, x); + } + return res <= k; + } + + // 计算n的价值 + long df(long n ,int x) { + if (map.containsKey(n)) { + return map.get(n); + } + long res = 0; + n >>>= x-1; + while(n != 0) { + res += n&1; + n >>>= x; + } + map.put(n, res); + return res; + } +} \ No newline at end of file diff --git a/src/main/java/com/dota/binarySearch/_78/Solution.java b/src/main/java/com/dota/binarySearch/_78/Solution.java new file mode 100644 index 0000000..4c3a51c --- /dev/null +++ b/src/main/java/com/dota/binarySearch/_78/Solution.java @@ -0,0 +1,38 @@ +package com.dota.binarySearch._78; + +class Solution { + public static void main(String[] args) { + new Solution().rampartDefensiveLine(new int[][]{{0,3},{4,5},{7,9}}); + } + public int rampartDefensiveLine(int[][] rampart) { + int n = rampart.length; + int l = 0, r = rampart[n - 1][1] + 1; + while(l+1= k) { + l = r; + continue; + } + r -= (k-l); + if (r < 0) { + return false; + } + l = r; + } + return true; + } +} \ No newline at end of file diff --git a/src/main/java/com/dota/deep/_386/Solution.java b/src/main/java/com/dota/deep/_386/Solution.java new file mode 100644 index 0000000..d86d4da --- /dev/null +++ b/src/main/java/com/dota/deep/_386/Solution.java @@ -0,0 +1,25 @@ +package com.dota.deep._386; + +import java.util.ArrayList; +import java.util.List; + +class Solution { + public List lexicalOrder(int n) { + var res = new ArrayList(); + for (int i = 1; i < 10; i++) { + df(res, i, n); + } + return res; + } + + void df(List list, int num, int n) { + if (num > n) return; + list.add(num); + num *= 10; + for (int i = 0; i < 10; i++) { + num += i; + df(list, num, n); + num -= i; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/dota/week/_158/Solution.java b/src/main/java/com/dota/week/_158/Solution.java new file mode 100644 index 0000000..d21d21a --- /dev/null +++ b/src/main/java/com/dota/week/_158/Solution.java @@ -0,0 +1,98 @@ +package com.dota.week._158; + +import java.util.Arrays; + +class Solution { + public int maximumProfit(int[] prices, int k) { + int n = prices.length; + + // 处理边缘情况:如果没有价格数据或 k 为 0,则无法进行交易,利润为 0。 + if (n == 0 || k == 0) { + return 0; + } + + // 当 k 足够大时(例如 k >= n - 1),意味着我们可以进行任意多次交易。 + // 由于允许普通交易和做空交易,我们可以抓住任何价格波动来盈利。 + // 例如,如果 prices[i+1] > prices[i],可以通过买入 prices[i] 卖出 prices[i+1] 赚取 prices[i+1] - prices[i]。 + // 如果 prices[i+1] < prices[i],可以通过做空 prices[i] 买回 prices[i+1] 赚取 prices[i] - prices[i+1]。 + // 两种情况下的利润都是 |prices[i+1] - prices[i]|。 + // 因此,当 k 足够大时,最大利润是所有相邻价格绝对差的总和。 + // 理论上,n-1 是最大可能利用的“单步”价格变动机会。 + if (k >= n - 1) { + int maxProfit = 0; + for (int i = 1; i < n; i++) { + maxProfit += Math.abs(prices[i] - prices[i - 1]); + } + return maxProfit; + } + + // k 不够大,使用动态规划。 + // 状态定义: + // noPos[j]: 完成 j 笔交易后,当前没有持仓的最大利润。 + // hasLong[j]: 完成 j 笔交易后,当前持有多头仓位(即为第 j+1 笔普通交易买入)的最大利润。 + // hasShort[j]: 完成 j 笔交易后,当前持有空头仓位(即为第 j+1 笔做空交易卖出)的最大利润。 + + // 初始化为极小的负数,表示不可达状态。 + // 使用 Integer.MIN_VALUE / 2 来避免在加减价格时发生溢出。 + final long INF = Long.MIN_VALUE / 2; + + long[] noPos = new long[k + 1]; + long[] hasLong = new long[k + 1]; + long[] hasShort = new long[k + 1]; + + // 将所有状态初始化为不可达(负无穷大),除了初始基准状态。 + Arrays.fill(noPos, INF); + Arrays.fill(hasLong, INF); + Arrays.fill(hasShort, INF); + + // 第 0 天的初始状态: + noPos[0] = 0; // 完成 0 笔交易,无持仓,利润 0。 + hasLong[0] = -prices[0]; // 完成 0 笔交易,买入第一支股票(开启第 1 笔普通交易),利润为 -prices[0]。 + hasShort[0] = prices[0]; // 完成 0 笔交易,做空第一支股票(开启第 1 笔做空交易),利润为 prices[0]。 + + // 遍历每一天(从第 1 天开始到最后一天) + for (int i = 1; i < n; i++) { + int currentPrice = prices[i]; + + // 更新完成 0 笔交易的状态: + // noPos[0] 保持 0,因为在没有交易的情况下无法产生利润。 + // hasLong[0]: 保持原有长仓利润,或者在当前价格买入(开启第一笔交易)。 + hasLong[0] = Math.max(hasLong[0], noPos[0] - currentPrice); + // hasShort[0]: 保持原有短仓利润,或者在当前价格做空(开启第一笔交易)。 + hasShort[0] = Math.max(hasShort[0], noPos[0] + currentPrice); + + // 遍历已完成的交易数 j(从 1 到 k) + for (int j = 1; j <= k; j++) { + // 保存当前 noPos[j] 的值,它代表了前一天的状态。 + // 这一点很重要,因为 hasLong[j] 和 hasShort[j] 的计算需要基于前一天的 noPos[j]。 + long prevNoPos_j = noPos[j]; + + // 更新 noPos[j]: 完成 j 笔交易,无持仓。 + // 1. 保持不变(从前一天的 noPos[j] 保持)。 + // 2. 从持有长仓状态(hasLong[j-1])卖出,完成第 j 笔交易。 + // 3. 从持有短仓状态(hasShort[j-1])买回,完成第 j 笔交易。 + // 注意:hasLong[j-1] 和 hasShort[j-1] 在当前 j 的迭代中尚未被更新,因此它们代表的是前一天的状态。 + noPos[j] = Math.max(noPos[j], hasLong[j-1] != INF ? hasLong[j-1] + currentPrice : INF); + noPos[j] = Math.max(noPos[j], hasShort[j-1] != INF ? hasShort[j-1] - currentPrice : INF); + + // 更新 hasLong[j]: 完成 j 笔交易,当前持有长仓。 + // 1. 保持不变(从前一天的 hasLong[j] 保持)。 + // 2. 从无持仓状态(prevNoPos_j,即前一天的 noPos[j])买入,开始第 j+1 笔普通交易。 + hasLong[j] = Math.max(hasLong[j], prevNoPos_j != INF ? prevNoPos_j - currentPrice : INF); + + // 更新 hasShort[j]: 完成 j 笔交易,当前持有短仓。 + // 1. 保持不变(从前一天的 hasShort[j] 保持)。 + // 2. 从无持仓状态(prevNoPos_j,即前一天的 noPos[j])做空,开始第 j+1 笔做空交易。 + hasShort[j] = Math.max(hasShort[j], prevNoPos_j != INF ? prevNoPos_j + currentPrice : INF); + } + } + + // 最终结果是所有 noPos[j] 中的最大值,因为我们希望最终不持有任何仓位以获得最大利润。 + long maxTotalProfit = 0; // 利润可以为 0(不交易)或负数(所有交易都亏损)。 + for (int j = 0; j <= k; j++) { + maxTotalProfit = Math.max(maxTotalProfit, noPos[j]); + } + + return (int)maxTotalProfit; + } +} \ No newline at end of file