diff --git a/src/main/java/cn/whaifree/interview/HS/HS.java b/src/main/java/cn/whaifree/interview/HS/HS.java new file mode 100644 index 0000000..ab22078 --- /dev/null +++ b/src/main/java/cn/whaifree/interview/HS/HS.java @@ -0,0 +1,97 @@ +package cn.whaifree.interview.HS; + +import java.util.Scanner; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/11 17:54 + * @注释 + */ +public class HS { + + public static void main1(String[] args) { + + Scanner in = new Scanner(System.in); + // 注意 hasNext 和 hasNextLine 的区别 + int n = in.nextInt(); + // 大于10 小于该n + + for (int i = n; i > 10; i--) { + get(i); + } + } + + /** + * 列举出小于小于max,且长度为n的所有满足的数 + * @param n + */ + public static void get(int n) { + // 获取n的长度 + int length = 0; + int newN = n; + while (newN != 0) { + length++; + newN /= 10; + } + newN = n; + int res = 0; + while (newN > 0) { + int c = newN % 10; + newN /= 10; + res += Math.pow(c, length); + } + if (res == n) { + System.out.println(res); + } + } + + public static void main(String[] args) { + double[] doubles = {3, 2, 6, 5, 1, 3}; + System.out.println(get_max_profit(10000, 6, doubles, 2)); + + } + + /** + * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 + * + * 根据输入计算最大收益 + * @param M double浮点型 初始资金 + * @param N int整型 历史价格天数 + * @param historyPrices double浮点型一维数组 N天历史价格 + * @param K int整型 最大允许交易次数 + * @return double浮点型 + */ + public static double get_max_profit (double M, int N, double[] historyPrices, int K) { + // write code here + // dp[0] 表示当天手里没有股票的手里的钱 + // - 没有钱有两种 + // dp[1] 表示手里有股票手里的钱 + double[] buy = new double[K + 1]; + double[] cell = new double[K + 1]; + buy[0] = -historyPrices[0]; + cell[0] = 0; + for (int i = 1; i <= K; i++) { + buy[i] = cell[i] = Integer.MIN_VALUE / 2; + } + for (int i = 1; i < N; i++) { + buy[0] = Math.max(buy[0], cell[0] - historyPrices[i]); + for (int j = 1; j <= K; j++) { + buy[j] = Math.max(buy[j], cell[j] - historyPrices[i]); + cell[j] = Math.max(cell[j], buy[j - 1] + historyPrices[i]); + } + } + + // 不持有股票的最大利润 cell 累乘后扣除初始值 + double res = 1; + for (double v : cell) { + if (v != 0) { + res *= v; + } + } + res *= M; + res -= M; + return res; + } + +} diff --git a/src/main/java/cn/whaifree/leetCode/Dynamic/Stock.java b/src/main/java/cn/whaifree/leetCode/Dynamic/Stock.java new file mode 100644 index 0000000..5d97066 --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/Dynamic/Stock.java @@ -0,0 +1,206 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * + * 买卖股票的最佳时机 四题+变形 + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/12 11:46 + * @注释 + */ +public class Stock { + + @Test + public void test() + { +// int[] prices = {7,1,5,3,6,4}; + int[] prices = {1,2,3,4,5}; + System.out.println(new LeetCode123_.Solution().maxProfit(prices)); + } +} + +class LeetCode188_{ + + class Solution { + public int maxProfit(int k, int[] prices) { + // dp[i][j] 表示第i天交易第k次的最大收益 + // dp[i][0] 表示第i天第 0/2 +1 次持有的最大手头 + // dp[i][1] 表示第i天第 1/2 +1次未持有的最大手头 + + int[][] dp = new int[prices.length][k * 2]; + // 未持有 初始化 + for (int i = 0; i < prices.length; i += 2) { + dp[i][0] = -prices[0]; + } + for (int i = 0; i < prices.length; i++) { + for (int j = 0; j < k * 2; j++) { + + } + } + return 1; + } + } +} + +class LeetCode123_ { + + static class Solution { + /** + * 最多可以完成 两笔 交易。 + * 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 + * + * dp[i][j] 表示第i天 状态j的最大手头有的钱 + * 一天一共就有五个状态, + * 0. 没有操作 (其实我们也可以不设置这个状态) + * + * 1. 第一次持有股票(第i天持有第一次股票) + * - 第i-1天就持有这个第一次股票 dp[i][1] = dp[i-1][1] + * - 第i天买入这个股票 dp[i][1] = dp[i-1][0] - prices[i] + * 2. 第一次不持有股票 + * - 第i天卖出 dp[i][2] = dp[i-1][1]+price[i] + * - 第i-1天就不持有第一支 dp[i][2] = dp[i-1][2] + * 3. 第二次持有股票 + * - 第i天买入第二支 dp[i][3] = dp[i-1][2] - price[i] + * - i-1天就持有 dp[i][3] = dp[i-1][3] + * 4. 第二次不持有股票 + * - 第i天卖出第二支 dp[i][4] = dp[i-1][3] + price[i] + * - 第i-1天就没有 dp[i][4] = dp[i-1][4] + * + * @param prices + * @return + */ + public int maxProfit(int[] prices) { + int[][] dp = new int[prices.length][5]; + dp[0][1] = -prices[0]; + dp[0][3] = -prices[0]; + for (int i = 1; i < prices.length; i++) { + // 没有操作,手上的现金自然就是0 + // dp[i][1] = Math.max(dp[i - 1][1], 0 - prices[i]); + dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]); + dp[i][2] = Math.max(dp[i - 1][2], dp[i - 1][1] + prices[i]); + dp[i][3] = Math.max(dp[i - 1][3], dp[i - 1][2] - prices[i]); + dp[i][4] = Math.max(dp[i - 1][4], dp[i - 1][3] + prices[i]); + } + return dp[prices.length - 1][4]; + } + + public int maxProfit1(int[] prices) { + int[] dp = new int[5]; + dp[1] = -prices[0]; + dp[3] = -prices[0]; + for (int i = 1; i < prices.length; i++) { + dp[1] = Math.max(dp[1], dp[0] - prices[i]); + dp[2] = Math.max(dp[2], dp[1] + prices[i]); + dp[3] = Math.max(dp[3], dp[2] - prices[i]); + dp[4] = Math.max(dp[4], dp[3] + prices[i]); + } + return dp[4]; + } + } + +} + +class LeetCode122_{ + + static class Solution { + public int maxProfit(int[] prices) { + // 只要递增就买入 + + int left = 0; + int right = 1; + int profit = 0; + while (right < prices.length) { + while (left < right && prices[left] > prices[right]) { + left++; + } + if (prices[left] < prices[right]) { + profit += (prices[right] - prices[left]); + left = right; + } + right++; + } + return profit; + } + + } + + static class Solution1 { + public int maxProfit(int[] prices) { + /** + * dp + * dp[i][0] 表示 i天没有股票的时候 手头的现金 + * - i-1就没有 dp[i-1][0] + * - i天刚刚卖 dp[i-1][1]+price[i] + * dp[i][1] 表示 i天有股票的时候 手头的现金 + * - i-1就有 dp[i-1][1] + * - 刚刚买入 dp[i-1][0] - price[i] + */ + int[][] dp = new int[prices.length][2]; + dp[0][1] = -prices[0]; + for (int i = 1; i < prices.length; i++) { + dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]); + dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]); + } + return dp[prices.length - 1][0]; + } + } +} + +class LeetCode121_ { + static class Solution { + public int maxProfit(int[] prices) { + // 最低点买入,最高点卖出 + int min = Integer.MAX_VALUE; + int res = 0; + for (int price : prices) { + min = Math.min(min, price); + res = Math.max(res, price - min); + } + return res; + } + } + + + static class Solution2 { + public int maxProfit(int[] prices) { + int[][] dp = new int[prices.length][2]; + // 本题只能交易一次 + // dp[i][0] 表示第i天手里没有股票的 手里的现金 + // - 第i天卖出 dp[i][0]=dp[i-1][1]+prices[i] + // - 第i-1天就没有股票 dp[i][0]=dp[i-1][0] + // dp[i][1] 表示第i天手里有股票的 手里的现金 + // - 第i天买入 dp[i][1] = - prices[i] + // - 第i-1天就有 dp[i][1] = dp[i-1][1] + dp[0][1] = -prices[0]; + for (int i = 1; i < prices.length; i++) { + dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]); + dp[i][1] = Math.max(dp[i - 1][1], - prices[i]); + } + + return dp[prices.length - 1][0]; + } + } + + static class Solution3 { + public int maxProfit(int[] prices) { + int[] dp = new int[2]; + // 本题只能交易一次 + // dp[i][0] 表示第i天手里没有股票的 手里的现金 + // - 第i天卖出 dp[i][0]=dp[i-1][1]+prices[i] + // - 第i-1天就没有股票 dp[i][0]=dp[i-1][0] + // dp[i][1] 表示第i天手里有股票的 手里的现金 + // - 第i天买入 dp[i][1] = - prices[i] + // - 第i-1天就有 dp[i][1] = dp[i-1][1] + dp[1] = -prices[0]; + for (int i = 1; i < prices.length; i++) { + dp[0] = Math.max(dp[0], dp[1] + prices[i]); + dp[1] = Math.max(dp[1], - prices[i]); + } + + return dp[0]; + } + } +} + diff --git a/src/main/java/cn/whaifree/leetCode/LeetCode/LeetCode503.java b/src/main/java/cn/whaifree/leetCode/LeetCode/LeetCode503.java index 235f7e6..077a323 100644 --- a/src/main/java/cn/whaifree/leetCode/LeetCode/LeetCode503.java +++ b/src/main/java/cn/whaifree/leetCode/LeetCode/LeetCode503.java @@ -1,5 +1,11 @@ package cn.whaifree.leetCode.LeetCode; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Deque; +import java.util.LinkedList; + /** * @version 1.0 * @Author whai文海 @@ -7,4 +13,65 @@ package cn.whaifree.leetCode.LeetCode; * @注释 */ public class LeetCode503 { + + @Test + public void test() + { + int[] nums = {1,2,3,4,3}; + Solution solution = new Solution(); + int[] res = solution.nextGreaterElements(nums); + for (int i = 0; i < res.length; i++) { + System.out.println(res[i]); + } + } + + class Solution { + /** + * 循环 + * 1. 两倍拼接 + * 2. 模拟走两遍 + * @param nums + * @return + */ + public int[] nextGreaterElements(int[] nums) { + + Deque stack = new LinkedList<>(); + stack.push(0); + int[] res = new int[nums.length]; + Arrays.fill(res, -1); + for (int i = 1; i < nums.length * 2; i++) { + if (nums[stack.peek()] < nums[i % nums.length]) { + // 找到了栈顶比他大的值 + while (!stack.isEmpty() && nums[stack.peek()] < nums[i % nums.length]) { + res[stack.peek()] = nums[i % nums.length]; + stack.pop(); + } + stack.push(i % nums.length); + } else if (nums[stack.peek()] > nums[i % nums.length]) { + stack.push(i % nums.length); + } else { + stack.push(i % nums.length); + } + } + return res; + } + + public int[] nextGreaterElements1(int[] nums) { + + Deque stack = new LinkedList<>(); + stack.push(0); + int[] res = new int[nums.length]; + Arrays.fill(res, -1); + for (int i = 1; i < nums.length * 2; i++) { + // 找到了栈顶比他大的值 + int h = i % nums.length; + while (!stack.isEmpty() && nums[stack.peek()] < nums[h]) { + res[stack.peek()] = nums[h]; + stack.pop(); + } + stack.push(h); + } + return res; + } + } } diff --git a/src/main/java/cn/whaifree/leetCode/LeetCode/LeetCode84.java b/src/main/java/cn/whaifree/leetCode/LeetCode/LeetCode84.java new file mode 100644 index 0000000..84480bb --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/LeetCode/LeetCode84.java @@ -0,0 +1,111 @@ +package cn.whaifree.leetCode.LeetCode; + +import org.junit.Test; + +import java.util.Deque; +import java.util.LinkedList; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/11 13:42 + * @注释 + */ +public class LeetCode84 { + + @Test + public void test() + { + int[] heights = {0}; + int i = new Solution1().largestRectangleArea(heights); + System.out.println(i); + } + + class Solution { + public int largestRectangleArea(int[] heights) { + int[] left = new int[heights.length]; + int[] right = new int[heights.length]; + + // 记录左右第一个小于i的坐标,这样就能计算以heights[i]为高的面积 + left[0] = -1; + for (int i = 1; i < heights.length; i++) { + int index = i - 1; + while (index >= 0 && heights[index] >= heights[i]) { + // index--; 这样会超时 + index = left[index]; + } + left[i] = index; + } + + right[right.length - 1] = right.length; + for (int i = right.length - 2; i >= 0; i--) { + int index = i + 1; + while (index < right.length && heights[index] >= heights[i]) { + index = right[index]; + } + right[i] = index; + } + + // 获得左边右边比他小的第一个数,就能计算最大面积 + int max = Integer.MIN_VALUE; + for (int i = 0; i < left.length; i++) { + int sum = (right[i] - left[i] - 1) * heights[i]; + max = Math.max(max, sum); + } + + return max; + } + + } + + class Solution1 { + /** + * 找每个柱子左右两边第一个小于该柱子的柱子 + * + * 找到凸的地方 + * + * @param heights + * @return + */ + public int largestRectangleArea(int[] heights) { + // 数组扩容,在头和尾各加入一个元素,因为要计算以i为高的最大面积 + int [] newHeights = new int[heights.length + 2]; + newHeights[0] = 0; + newHeights[newHeights.length - 1] = 0; + for (int index = 0; index < heights.length; index++){ + newHeights[index + 1] = heights[index]; + } + heights = newHeights; + // 扩容是为了在计算最大矩形面积时能处理以下两种特殊情况: + // 包含第一个柱子的最大矩形: + // 包含最后一个柱子的最大矩形: + + Deque stack = new LinkedList<>(); + stack.push(0); + int res = 0; + for (int i = 1; i < heights.length; i++) { + if (heights[i] == heights[stack.peek()]) { + // 如果 栈顶 比 i 小 + stack.push(i); + } else if (heights[i] < heights[stack.peek()]) { + // 4 栈顶[6 3...] + while (!stack.isEmpty() && heights[i] < heights[stack.peek()]) { + // 顶和栈顶的下一个元素以及要入栈的三个元素组成了我们要求最大面积的高度和宽度 + Integer mid = stack.pop(); // 凸的中间 + if (!stack.isEmpty()) { + Integer left = stack.peek(); + Integer right = i; + res = Math.max(res, (right - left - 1) * heights[mid]); + } + } + + stack.push(i); + } else { + stack.push(i); + } + } + return res; + } + + } +} diff --git a/src/main/java/cn/whaifree/test/ThreadLocalExample.java b/src/main/java/cn/whaifree/test/ThreadLocalExample.java new file mode 100644 index 0000000..bf17879 --- /dev/null +++ b/src/main/java/cn/whaifree/test/ThreadLocalExample.java @@ -0,0 +1,31 @@ +package cn.whaifree.test; + +public class ThreadLocalExample { + + public static void main(String[] args) throws InterruptedException { + for(int i=0 ; i<3; i++){ + new Thread(new MyThread()).start(); + } + } +} + +class MyThread implements Runnable{ + + private static ThreadLocal localVariable = new ThreadLocal() { + @Override + protected Integer initialValue() { + return 100; + } + }; + + @Override + public void run() { + System.out.println("Thread Name= " + Thread.currentThread().getName() + " default value = " + localVariable.get()); + //formatter pattern is changed here by thread, but it won't reflect to other threads + localVariable.set(localVariable.get() + 1); + + System.out.println("Thread Name= " + Thread.currentThread().getName() + " localVariable = " + localVariable.get()); + + } +} +