thảo luận Leetcode mỗi ngày

  • Người tạo chủ đề Người tạo chủ đề _Gia_Cat_Luong_
  • Ngày bắt đầu Ngày bắt đầu
Trạng thái
Không mở để trả lời thêm.
Thím thử tiếp cận theo hướng dùng queue BFS xem, bắt đầu duyệt tại vị trí best view sau đó lan dần ra xung quanh khi gặp ghế đầu tiên thỏa thì tính lại distance (d1), khi nào vị trí đầu tiên trong queue có distance vs best view > d1 thì dừng

vâng, e dc gợi ý như vậy nhưng k biết triển khai như nào để có thể tìm dc vị trí của những ghế xung quanh bestview mà k dùng 2 vòng for loop HxW
 
vâng, e dc gợi ý như vậy nhưng k biết triển khai như nào để có thể tìm dc vị trí của những ghế xung quanh bestview mà k dùng 2 vòng for loop HxW
nếu bestview có tọa dộ là (i)(j) thì 4 vị trí xung quanh sẽ là
  • (i-1)(j)
  • (i+1)(j)
  • (i)(j-1)
    (i)(j+1)
 
nếu bestview có tọa dộ là (i)(j) thì 4 vị trí xung quanh sẽ là
  • (i-1)(j)
  • (i+1)(j)
  • (i)(j-1)
    (i)(j+1)
nhũng với những ghế xung quanh bestview với distance bằng 2 thì sẽ thế nào, e bị vướng,làm sao để triển khai dc tiếp chỗ này
(i-2)(j)
(i+2)(j)
(i)(j-2)
(i)(j+2)
(i+1)(j+1)
(i-1)(j-1)
(i-1)(j+1)
(i+1)(j-1)
 
Ai giải thích hộ e cái số k trong đề bài daily hôm nay nó đóng vai trò như thế nào, e chưa hiểu lắm:

https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/

1662782257557.png


Số k là số max transactions ko được vượt nhưng thằng Example 2 nó có tới tận 4 transactions liền
 
Cách giải O(nnk), nhanh hơn 5.8% =))
Gọi F(i, j) là lợi nhuận lớn nhất có thể đạt được khi ta đã duyệt qua i ngày (từ ngày 0 đến ngày i-1), và đã thực hiện j transactions.
F(i, j) = max ( F(t, j-1) + prices[i-1] - min(prices[t...i-2]))
Ý nghĩa là giả sử ta bán cổ phiếu vào ngày i-1, và cho tới ngày t-1 ta đã thực hiện j transactions rồi, thì trong khoảng từ ngày t tới ngày i-2 ta chọn ngày có giá cổ phiếu bé nhất để mua

Java:
class Solution {
    public int maxProfit(int k, int[] prices) {
        int n=prices.length;
        int[][] F=new int[n+1][k+1];
        int res=0;
        for(int i=0;i<=n;i++){
            for(int j=0;j<=k;j++){
                F[i][j]=Integer.MIN_VALUE;
                if(j==0) F[i][j]=0;
                else{
                    int curMin=Integer.MAX_VALUE;
                    for(int t=i-1;t-1>=0;t--){
                        curMin=Math.min(curMin, prices[t-1]);
                        // System.out.println(curMin);
                        if(curMin>=0 && curMin<=prices[i-1]) F[i][j]=Math.max(F[t-1][j-1]+prices[i-1]-curMin, F[i][j]);
                    }
                }
                // System.out.println(i+" "+j+" "+F[i][j]);
                res=Math.max(res, F[i][j]);
            }
        }
        return res;
    }
}
 
cuối tuần cho bài khó vại
fHLK4F6.png

Mã:
defmodule Solution do
  @default_min -1001

  def max_profit(k, prices) do
    n = Enum.count(prices)

    cond do
      k == 0 -> 0

      k >= n - 1 ->
        prices
        |> Stream.chunk_every(2, 1, :discard)
        |> Stream.map(fn [a, b] -> max(0, b - a) end)
        |> Enum.sum()

      true ->
        prices =
          prices
          |> Stream.with_index()
          |> Stream.map(fn {v, i} -> {i, v} end)
          |> Map.new()

        for trans <- 1..k, reduce: %{} do
          dp ->
            for day <- 1..(n - 1), reduce: {@default_min, dp} do
              {prev_max_profit, dp} ->
                max_profit =
                  max(prev_max_profit, get(dp, {trans - 1, day - 1}) - get(prices, day - 1))

                {max_profit,
                 Map.put(
                   dp,
                   {trans, day},
                   max(get(dp, {trans, day - 1}), get(prices, day) + max_profit)
                 )}
            end
            |> elem(1)
        end
        |> get({k, n - 1})
    end
  end

  defp get(map, key), do: Map.get(map, key, 0)
end
 
hkNtitg.png
mới nhìn đọc không kỹ tưởng là bài sell stock easy

Ai ngờ là sell stock phần 4 hard ạ
janDexM.jpg
 
toy viết thế lày là O(nk) phải ko xao chậm quá vậy
LTT2cUR.png


https://leetcode.com/submissions/detail/796222837/

cái cache có key type là tuple<int, bool, int> trong đó int đầu tối đa là k, int cuối tối đa là n, nên cache size tối đa là 2nk nên thuật toán chỉ có O(nk) time space thoy xao mà chạy chậm rì
LTT2cUR.png


code đệ quy
C++:
    int maxProfit(int k, vector<int>& prices) {
        auto f = [&](auto& f, int j, bool buying, int i) -> int {
            if (j == 0 || i >= prices.size()) return 0;
            const int buyOrSell = (buying ? -prices[i] : prices[i]) + f(j - !buying, !buying, i + 1);
            const int ignore = f(j, buying, i + 1);
            return max(buyOrSell, ignore);
        };
        return memoize(f, k, true, 0);
    }
 
toy viết thế lày là O(nk) phải ko xao chậm quá vậy
LTT2cUR.png


https://leetcode.com/submissions/detail/796222837/

cái cache có key type là tuple<int, bool, int> trong đó int đầu tối đa là k, int cuối tối đa là n, nên cache size tối đa là 2nk nên thuật toán chỉ có O(nk) time space thoy xao mà chạy chậm rì
LTT2cUR.png


code đệ quy
C++:
    int maxProfit(int k, vector<int>& prices) {
        auto f = [&](auto& f, int j, bool buying, int i) -> int {
            if (j == 0 || i >= prices.size()) return 0;
            const int buyOrSell = (buying ? -prices[i] : prices[i]) + f(j - !buying, !buying, i + 1);
            const int ignore = f(j, buying, i + 1);
            return max(buyOrSell, ignore);
        };
        return memoize(f, k, true, 0);
    }
T làm memoi python chạy mất 6s đây, vẫn pass.
 
Python:
class Solution:
    def maxProfit(self, k: int, prices: List[int]) -> int:
        n, p = len(prices) - 1, -1
        profits, vp = [], []
        while p < n:
            v = p + 1
            while v < n and prices[v] >= prices[v + 1]: v += 1
            p = v
            while p < n and prices[p] <= prices[p + 1]: p += 1
         
            while vp and prices[v] < prices[vp[-1][0]]:
                pv, pp = vp.pop()
                profits.append(prices[pp] - prices[pv])
            while vp and prices[p] >= prices[vp[-1][1]]:
                pv, pp = vp.pop()
                profits.append(prices[pp] - prices[v])
                v = pv
            vp.append((v, p))
        else:
            profits.extend(prices[p] - prices[v] for v, p in vp)
         
        return sum(nlargest(k, profits))

https://leetcode.com/problems/best-...on-with-on-klgn-time-using-max-heap-and-stack

O(n+klog(n))
 
Sửa lần cuối:
Nếu viết công thức ra thì bài không quá khó.
O(nk) time, O(n) space

Gọi T(t, i) là profit tối ưu tại thời điểm i với t giao dịch đã thực hiện:
Mệnh đề: để tìm phương án tối ưu với lệnh bán tại i, ta cần tìm:
  • Phương án tốt nhất với t-1 giao dịch, T(t-1, j) với j <= i-2
  • Thực hiện thêm một giao dịch mới: mua tại thời điểm giá thấp nhật trong khoảng từ [j + 1, i - 1] và bán tại i,

Hoặc có thể dùng ngay phương án của T(t, i-1), tức là không bán tại i.

Chuyển về công thức như sau:

gif.download


Tính công thức trên thì cần độ phức tạp O(nnk), để giảm xuống thành O(nk) thì cần phải có cách tận dụng tính T(t, i) dựa trên T(t, i-1).

gif.download


So sánh phần tổng bên trong đoạn max
  1. công thức của i nhiều hơn của i-1 một phần tử, tại j = i-2. Tức là cần so thêm với
    1662824624171.png
    ,
  2. phần cộng thêm là p(i) thay vì p(i-1),
  3. phần bị trừ đi là min(p(m), j < m < i) thay cho min(p(m), j < m < i-1). Tức là sẽ chỉ khác nhau khi min = p(i-1). Trùng với trường hợp 1 nên có thể bỏ qua.

Tóm lại:
1662824713679.png


Có thể hiểu theo một cách khác: nhưng giải thích kiểu này không trực quan lắm, viết công thức ra dễ hiểu hơn:
  • T'(i) <- T'(i-1): phương án tối ưu giống như cũ, không liên quan gì đến giá tại thời điểm i,
  • T'(i) <- T'(i-1) + p(i) - p(i-1): phương án tối ưu gần giống như tại thời điểm i-1, chỉ khác là thay vì bán với giá p(i-1) thì bán với giá p(i)
  • T'i(i) <- T(i-2) + p(i) - p(i-1): thực hiện giao dịch giống như tại thời điểm i-2, sau đó thêm một giao dịch mới mua p(i-1) và bán p(i)

C++:
class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        int n = prices.size(), res = 0;
        if (n < 2) return 0;
        vector<int> T(n), tmp(n);
      
        for (int t = 1; t <= k; ++t) {
            int tt = tmp[1] = t == 1 ? max(prices[1] - prices[0], 0) : 0;
            for (int i = 2; i < n; ++i) {
                tt = max(tt + prices[i] - prices[i-1], T[i-2] + prices[i] - prices[i-1]);
                tmp[i] = max(tmp[i-1], tt);
            }
            T.swap(tmp);
            res = max(res, T.back());
        }
      
        return res;
    }
};
 
Sửa lần cuối:
G1uz9HC.png
bài khó vãi, trư chịu thua, lên kênh youtube xem lời giải cuối cùng vẫn éo hiểu gì
Qcg0oqw.jpg
suy nghĩ một hồi thì hóa ra lol kia giải sai
jXIRwTd.png


WawmAwM.png
đại khái là quy hoạch động, k giao dịch = 2k giao dịch mua + bán. Nested loop n * k để mò xem ngày giao dịch nào thì nhét vào thứ tự giao dịch nào cho phù hợp.
Untitled.png



Untitled.png
 
11 / 9 / 2022:
  • 1 câu hard nhẹ nhàng
    • Ý tưởng chung, để ý cái minimun efficiency và sum of speed, như vậy nếu sort theo efficiency thì efficiency[i.] là minimum của efficiency từ i đến efficiency cuối cùng
    • với mỗi efficiency[i.] thì cần tìm max tổng k phần tử speed từ i tới speed cuối (speed phải sort theo thứ tự efficiency)
    • đến đây thì khá dễ để nhận ra dùng priority queue rồi.
    • Time: O(n logn)
    • Space: O(n)
    • Code: https://leetcode.com/submissions/detail/796666621/
  • Câu hôm nay khá dễ 15p đã xong.
 
nhẹ nhàng đâu mà nhẹ nhàng toy tưởng dp mò cả tiếng ko ra tự dưng thấy sort theo efficiency giảm dần có lý nhưng tiếp theo ko biết làm xao phải xem lời giải
OANgL56.png
OANgL56.png
OANgL56.png

code dưỡng sinh mà nó cho cái tạ chăm ký dưỡng gì nổi
Qz8dGvJ.png


edit: có cái ispoiler ngon vậy
irGoYrZ.gif


C++:
struct Solution {
    int maxPerformance(int n, vector<int>& spd, vector<int>& eff, int k) {
        vector<pair<int, int>> engi(n);
        transform(begin(eff), end(eff), begin(spd), begin(engi), [](int e, int s){ return make_pair(e, s); });
        sort(engi.rbegin(), engi.rend());
        priority_queue<int, vector<int>, greater<int>> pq;
        int64_t pqSum = 0;
        int64_t res = 0;
        for (const auto& [e, s] : engi) {
            res = max(res, (pqSum += s) * e);
            pq.push(s);
            if (pq.size() > k - 1) pqSum -= pq.top(), pq.pop(); 
        }
        return res % 1'000'000'007;
    }
};
 
Sửa lần cuối:
Trạng thái
Không mở để trả lời thêm.

Thống kê chủ đề

Ngày tạo
_Gia_Cat_Luong_,
Người trả lời cuối
Vipluckystar,
Trả lời
17.755
Lượt xem
1.213.091
Quay lại
Lên đầu trang