💯✅ JAVA 8 STREAMS || EXPLAINED || 8 LINES || Intuition ||  Approach 🆙🆙⬆️⬆️
\n# Intuition: \n\nFor each task in nums1 and nums2, we can clear it at most once. If we clear a task twice, we are just wasting time by setting it to zero agai
\n# Intuition: \n\nFor each task in nums1 and nums2, we can clear it at most once. If we clear a task twice, we are just wasting time by setting it to zero again. Therefore, we should choose which tasks to clear carefully.\n\nTasks in the nums2 list with larger duration per operation should be cleared later than tasks with smaller duration per operation. That way, we can maximize the time we spend on the tasks with smaller duration per operation.\n\nIf we sort the tasks by their duration per operation, we can greedily choose the first k tasks to clear, where k <= n, and still meet the time requirement. However, some tasks with smaller duration per operation may not get chosen, even if clearing them does not cause us to exceed the time requirement.\n\n# Approach:\n\nWe create a 2D array nums of size n x 2, where each row i contains the pair (nums1[i], nums2[i]), which represent the time required for the ith task and the duration per operation of the ith task, respectively.\n\nWe sort the array nums in ascending order by the duration per operation. We use a two-dimensional dp array of size (n+1) x (n+1), where dp[i][j] represents the maximum total time we can spend by selecting j tasks from the first i tasks of nums, subject to the time constraint.\n\nWe fill the dp array using the following recurrence relation:\n\ndp[i][j] = max { dp[i-1][j], dp[i-1][j-1] + nums[i-1][0] + j * nums[i-1][1] }\n\nWe return the largest value of j for which dp[n][j] <= x.\n\n\n\n# Code:\n\n```JAVA []\npublic int minimumTime(List<Integer> nums1, List<Integer> nums2, int x) {\n\t\tint nums[][] = new int[nums1.size()][], sum1 = 0, sum2 = 0, dp[][] = new int[nums.length + 1][nums.length + 1];\n\t\tfor (int i = 0; i < nums1.size(); sum1 += nums1.get(i), sum2 += nums2.get(i), i++) {\n\t\t\tnums[i] = new int[] { nums1.get(i), nums2.get(i) };\n\t\t}\n\t\tArrays.sort(nums, (o, p) -> o[1] - p[1]);\n\t\tfor (int i = 0; i < nums1.size(); i++) {\n\t\t\tfor (int j = 1; j <= i + 1; j++) {\n\t\t\t\tdp[i + 1][j] = Math.max(dp[i][j], dp[i][j - 1] + nums[i][0] + j * nums[i][1]);\n\t\t\t}\n\t\t}\n\t\tfor (int i = 0; i <= nums2.size(); i++) {\n\t\t\tif (sum1 + sum2 * (long) i - dp[nums1.size()][i] <= x) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t}\n```\n\n# using Java 8 streams\n```java [] \npublic int minimumTime(List<Integer> nums1, List<Integer> nums2, int x) {\n    int size = nums1.size(),nums[][] = new int[size][],length = nums.length, dp[][] = new int[length + 1][length + 1];;\n    AtomicInteger sum1 = new AtomicInteger(0),sum2 = new AtomicInteger(0),ans = new AtomicInteger(-1);\n    IntStream.range(0,size).forEach(i->{\n        nums[i] = new int[] { nums1.get(i), nums2.get(i) };\n        sum1.addAndGet(nums1.get(i)); sum2.addAndGet(nums2.get(i));\n    });\n    Arrays.sort(nums, Comparator.comparingInt(o -> o[1]));\n    IntStream.range(0,size).forEach(i->{\n        IntStream.rangeClosed(1,i+1).forEach(j->{\n            dp[i + 1][j] = Math.max(dp[i][j], dp[i][j - 1] + nums[i][0] + j * nums[i][1]);\n        });\n    });\n    IntStream.range(0, nums2.size() + 1)\n            .filter(i -> sum1.get() + sum2.get() * (long) i - dp[size][i] <= x)\n            .findFirst()\n            .ifPresent(ans::set);\n    return ans.get();\n}\n```\n\uD83C\uDD99\u2B06\uFE0F\uD83C\uDD99\uD83C\uDD99\u2705\uD83D\uDCAF\n```\npublic int minimumTime(List<Integer> nums1, List<Integer> nums2, int x) {\n    int size = nums1.size(),nums[][] = new int[size][],length = nums.length, dp[][] = new int[length + 1][length + 1];;\n    AtomicInteger sum1 = new AtomicInteger(0),sum2 = new AtomicInteger(0);\n    IntStream.range(0,size).forEach(i->{\n        nums[i] = new int[] { nums1.get(i), nums2.get(i) };\n        sum1.addAndGet(nums1.get(i)); sum2.addAndGet(nums2.get(i));\n    });\n    Arrays.sort(nums, Comparator.comparingInt(o -> o[1]));\n    IntStream.range(0,size).forEach(i->IntStream.rangeClosed(1,i+1).forEach(j->dp[i + 1][j] = Math.max(dp[i][j], dp[i][j - 1] + nums[i][0] + j * nums[i][1])));\n    return IntStream.range(0, nums2.size() + 1).filter(i -> sum1.get() + sum2.get() * (long) i - dp[size][i] <= x).findFirst().orElse(-1); \n}\n```\nC++:\n\n```\nint minimumTime(vector<int>& nums1, vector<int>& nums2, int x) {\n    int n = nums1.size();\n    vector<vector<int>> nums(n, vector<int>(2));\n    for (int i = 0; i < n; i++) {\n        nums[i][0] = nums1[i];\n        nums[i][1] = nums2[i];\n    }\n    sort(nums.begin(), nums.end(), [](auto& a, auto& b) { return a[1] < b[1]; });\n    vector<vector<int>> dp(n+1, vector<int>(n+1));\n    for (int i = 1; i <= n; i++) {\n        for (int j = 1; j <= i && j <= n; j++) {\n            dp[i][j] = max(dp[i-1][j], dp[i-1][j-1] + nums[i-1][0] + j * nums[i-1][1]);\n        }\n    }\n    for (int j = n; j >= 0; j--) {\n        if (dp[n][j] <= x) {\n            return j;\n        }\n    }\n    return -1;\n}\n```\n\nPython:\n\n```\ndef minimumTime(nums1: List[int], nums2: List[int], x: int) -> int:\n    n = len(nums1)\n    nums = [[nums1[i], nums2[i]] for i in range(n)]\n    nums.sort(key=lambda a: a[1])\n    dp = [[0]*(n+1) for _ in range(n+1)]\n    for i in range(1, n+1):\n        for j in range(1, i+1):\n            dp[i][j] = max(dp[i-1][j], dp[i-1][j-1] + nums[i-1][0] + j * nums[i-1][1])\n    for j in range(n, -1, -1):\n        if dp[n][j] <= x:\n            return j\n    return -1\n```\n\n# Complexity\n- Time complexity:o(n^2)\n<!-- Add your time complexity here, e.g. $$O(n)$$ -->\n\n- Space complexity:o(n^2)\n<!-- Add your space complexity here, e.g. $$O(n)$$ -->
['Dynamic Programming', 'Data Stream', 'Python', 'C++', 'Java', 'Python3']