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

Vẫn phải nhập manual Result type chứ không tự deduce bằng invoke_result_t được ví lúc đó 2 type bị phụ thuộc vòng: lambda phụ thuộc Cache, Cache lại phụ thuộc lambda.

C++:
namespace std {
namespace {

template <typename T>
inline size_t hash_combine(size_t seed, T&& v)
{
    return seed ^= hash<remove_cv_t<remove_reference_t<T>>>()(forward<T>(v)) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}

template <typename Tuple, size_t Index = tuple_size<Tuple>::value - 1>
struct TupleHash
{
    static size_t calculate(size_t seed, Tuple const &t)
    {
        seed = TupleHash<Tuple, Index - 1>::calculate(seed, t);
        return hash_combine(seed, std::get<Index>(t));
    }
};

template <typename Tuple>
struct TupleHash<Tuple, 0>
{
    static size_t calculate(size_t seed, Tuple const &t)
    {
        return hash_combine(seed, std::get<0>(t));
    }
};

} // namespace

template <typename... Args>
struct hash<tuple<Args...>>
{
    size_t operator()(tuple<Args...> const &tt) const
    {
        return TupleHash<tuple<Args...>>::calculate(0, tt);
    }
};

} // namespace std

template <typename RecursiveFunc, typename Result, typename... Args>
class Cache {
    using Params = std::tuple<Args...>;
    // using Result = std::invoke_result_t<RecursiveFunc, Cache&, Args...>;
public:
    Cache(RecursiveFunc&& f) : f{std::move(f)} {}

    void set(Result value, Args&&... args) {
        data[std::make_tuple(std::forward<Args>(args)...)] = value;
    }

    Result operator[](Args&&... args) {
        auto t = std::make_tuple(std::forward<Args>(args)...);
        if (auto it = data.find(t); it != data.end())
            return it->second;

        return data[t] = f(*this, std::forward<Args>(args)...);
    }

private:
    std::unordered_map<Params, Result> data;
    RecursiveFunc f;
};

using namespace std;

class Solution {
public:
    int combinationSum4(vector<int>& nums, int target) {
        auto f = [&](auto& cache, uint32_t target){
            uint32_t res = 0;
            for (uint32_t n : nums) if (target >= n) res += cache[target - n];
            return res;
        };
        Cache<decltype(f), uint32_t, uint32_t> m{std::move(f)};
        m.set(1, 0);
        return m[target];
    }
};
[/spoler]

sửa lại cho ngắn hơn
C++:
namespace std {
namespace {
template <class T>
size_t hash_combine(size_t seed, const T& v) {
    return seed ^= hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
} // namespace

template <class... Args>
struct hash<tuple<Args...>> {
    template <size_t Index = sizeof...(Args) - 1>
    size_t operator()(const tuple<Args...>& t, size_t seed = 0) const {
        if constexpr (Index == 0) {
            return hash_combine(seed, get<0>(t));
        } else {
            seed = operator()<Index - 1>(t, seed);
            return hash_combine(seed, get<Index>(t));
        }
    }
};
} // namespace std


template <class RecursiveFunc, class Result, class... Args>
class Memo {
    using Params = std::tuple<Args...>;
public:
    explicit Memo(RecursiveFunc&& f) : f{move(f)} {}
    Result operator()(Args... args) {
        Params t = std::forward_as_tuple(args...);
        auto it = cache.find(t);
        if (it == end(cache))
            std::tie(it, std::ignore) = cache.emplace(std::move(t), f(*this, std::forward<Args>(args)...));
        return it->second;
    }
private:
    RecursiveFunc f;
    std::unordered_map<Params, Result> cache;
};

class Solution {
public:
    int combinationSum4(vector<int>& nums, int target) {
        auto f = [&](auto& f, int target) -> uint32_t {
            if (target == 0) return 1;
            uint32_t res = 0;
            for (int n : nums) if (target >= n) res += f(target - n);
            return res;
        };
        return Memo<decltype(f), uint32_t, int>{move(f)}(target);
    }
};

ko cần cái hàm set kia làm gì nữa
C++:
if (target == 0) return 1;
uint32_t res = 0;
for (int n : nums) if (target >= n) res += f(target - n);
return res;
thân hàm thế này ko khác gì đệ quy bình thường
JiZo9zf.png


dòng
C++:
return Memo<decltype(f), uint32_t, int>{move(f)}(target);
ko sửa được thành make_memo(f)(target) được, tại bị lệ thuộc vòng
4gmOAMB.png


có lẽ CRTP làm được nhưng phải viết class kế thừa vào, phải lấy cái nums kia qua ctor, ko gọn bằng [&]

---

edit: lấy ResultType được kìa
qZV215Z.png


C++:
namespace std {
namespace {
template <class T>
size_t hash_combine(size_t seed, const T& v) {
    return seed ^= hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
} // namespace
 
template <class... Args>
struct hash<tuple<Args...>> {
    template <size_t Index = sizeof...(Args) - 1>
    size_t operator()(const tuple<Args...>& t, size_t seed = 0) const {
        if constexpr (Index == 0) {
            return hash_combine(seed, get<0>(t));
        } else {
            seed = operator()<Index - 1>(t, seed);
            return hash_combine(seed, get<Index>(t));
        }
    }
};
} // namespace std

template <class RecursiveFunc, class... Args>
class Memo {
    using Params = std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...>;
    using Result = std::result_of_t<RecursiveFunc(Memo<RecursiveFunc, Args...>&, Args...)>;
public:
    explicit Memo(RecursiveFunc&& f) : f{std::move(f)} {}
    Result operator()(Args... args) {
        Params t = std::forward_as_tuple(args...);
        auto it = cache.find(t);
        if (it == end(cache))
            std::tie(it, std::ignore) = cache.emplace(std::move(t), f(*this, std::forward<Args>(args)...));
        return it->second;
    }
private:
    RecursiveFunc f;
    std::unordered_map<Params, Result> cache;
};

template <class RecursiveFunc, class... Args>
auto memoize(RecursiveFunc/*&&*/ f, Args/*&&*/... args) {
    return Memo<RecursiveFunc, Args...>{std::move(f)}(std::forward<Args>(args)...);
}

cgE9MkI.gif

C++:
class Solution {
public:
    int combinationSum4(vector<int>& nums, int target) {
        auto f = [&](auto& f, int i) -> uint32_t {
            if (i == 0) return 1;
            uint32_t res = 0;
            for (int n : nums) if (i >= n) res += f(i - n);
            return res;
        };
        return memoize(f, target);
    }
};

  • xài using Params = std::tuple<Args...>; thì nó chạy sai: https://rextester.com/QTC87092 với lvalue/const/volatile gì tùm lum
    ghXpJrI.png
    chắc là do dangling ref, phải sửa lại remove ref/cv hết
  • xài perfect forwarding Args&& cho memoize thì gọi memoize(f, target) ko được vì f nhận int, mà perfect forwarding nó forward int& target
    aVgiONl.png
    khi xài phải viết lại 1 là memoize(f, target + 0) 2 là memoize(f, int(target)) đều xấu

vì Params luôn là tuple<T1, T2, ... Tn> ko có ref/cv gì hết nên xài Args cho ròi, xài Args&& thì viết t1 + 0 t2 + 0 gì chắc
LTT2cUR.png
nên toy quyết định bỏ Args&& xài Args thoy, Hàm đệ quy thì chắc đâu có ai xài &/cv đâu
EB2RUU6.gif



test thử bài unique path bữa trước: https://leetcode.com/submissions/detail/766251301/
08XwbpM.gif
 
Last edited:
Vật vã hết một ngày cuối cùng cũng qua được bài này nhưng chỉ hơn 14%.

Có bác nào muốn thử làm không? Hiện là bài có tỉ lệ accept thấp thứ 2 lc, chỉ có 15%.
https://leetcode.com/problems/booking-concert-tickets-in-groups/
Móa cuối tuần đang định nghỉ ngơi cho khỏe thì thấy bài này của bác.
Bài này em gặp 1 lần trong biweekly contest cách đây 2 3 tháng, đọc đề bài dài vl nên bỏ.
Bài này em dùng segment tree, mỗi node có lưu lại số ghế còn thừa trong tổng các rows để scatter và số ghế còn thừa max tại 1 row để gather.
Làm từ tối qua đến h ms xong, sai sml :D
1659756746510.png
 
Về bài hôm nay:
  • Xét trường hợp cơ bản chỉ có một lần test. Với n pigs P = {p1, p2, ..., pn} để xác định đúng bucket thì phải thử nói với một tập hợp các p sao cho tập này là unique. Tức tập các bucket có thể xác định được từ n pigs chính là powerset của P: B = 2^P ==> với B bucket cần log2(B) pigs,
  • Nếu được test thêm 1 lần. Với mỗi bucket có thêm một cách chọn p. Hiện giờ có 3 cách: không chọn pi, chọn pi ở lần 1, chọn pi ở lần 2. ==> cần log3(B) pigs

Công thức tổng quát: ceiling( ln(B) / ln(T+1) ).

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


Móa cuối tuần đang định nghỉ ngơi cho khỏe thì thấy bài này của bác.
Bài này em gặp 1 lần trong biweekly contest cách đây 2 3 tháng, đọc đề bài dài vl nên bỏ.
Bài này em dùng segment tree, mỗi node có lưu lại số ghế còn thừa trong tổng các rows để scatter và số ghế còn thừa max tại 1 row để gather.
Làm từ tối qua đến h ms xong, sai sml

Bài này thì chuẩn là segment tree rồi, nhưng dài nên dễ sai.
 
Về bài hôm nay:
  • Xét trường hợp cơ bản chỉ có một lần test. Với n pigs P = {p1, p2, ..., pn} để xác định đúng bucket thì phải thử nói với một tập hợp các p sao cho tập này là unique. Tức tập các bucket có thể xác định được từ n pigs chính là powerset của P: B = 2^P ==> với B bucket cần log2(B) pigs,
  • Nếu được test thêm 1 lần. Với mỗi bucket có thêm một cách chọn p. Hiện giờ có 3 cách: không chọn pi, chọn pi ở lần 1, chọn pi ở lần 2. ==> cần log3(B) pigs

Công thức tổng quát: ceiling( ln(B) / ln(T+1) ).

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




Bài này thì chuẩn là segment tree rồi, nhưng dài nên dễ sai.
Bài hnay e thấy đáp án ko hợp lý lắm. Sau mỗi lần thử có 1 con pig chết đi thì chỉ còn x-1 con pig thôi chứ.
Giả sử 1000 pig, chia 1000 ra thành x phần, cho x pig uống. phần nào độc thì con pig đó chết. Như vậy khoanh vùng đc còn 1000/x buckets, và còn x-1 con pig.
Tương tự vậy lại chia tiếp 1000/x/(x-1), ... đến khi nào số buckets < số pig còn lại thì dừng
 
Bài hnay e thấy đáp án ko hợp lý lắm. Sau mỗi lần thử có 1 con pig chết đi thì chỉ còn x-1 con pig thôi chứ.
Giả sử 1000 pig, chia 1000 ra thành x phần, cho x pig uống. phần nào độc thì con pig đó chết. Như vậy khoanh vùng đc còn 1000/x buckets, và còn x-1 con pig.
Tương tự vậy lại chia tiếp 1000/x/(x-1), ... đến khi nào số buckets < số pig còn lại thì dừng

Nếu ở lần test trước có 1 hoặc nhiều con chết đi thì lần sau không gian tìm kiếm sẽ thu hẹp lại, số lượng cần thực tế có khi còn thấp hơn.
Bài này y/c tìm minimum chắc là kiểu min ( max với mọi kết quả test ) thôi. Chứ nếu may mắn thì với mọi case chỉ cần 1 con là đủ.
 
Bài hôm nay có thể giải bằng 2 cách: quy hoạch động hoặc dùng công thức toán
uzQb2yt.png



* Nghĩ hoài không ra, toán không phải là thế mạnh của vozer
yBBewst.png
https://leetcode.com/submissions/detail/764265180/

Giả theo Toán thì có thể dùng Tổ Hợp.

Số step max luôn là (m-1) Down + (n-1) Right
Tìm tổ hợp chập m-1 của m+n-2
 
4 xô chỉ 1 lần thử làm xao chỉ cần 2 con heo nhỉ
uzQb2yt.png


hình như 1 xô có thể uống nhiều lần à? Con 1 sẽ uống xô 1 2, con 2 sẽ uống xô 1 3. Có 4 trường hợp, 1 chết 2 chết thì là xô 1, 1 sống 2 sống là xô 4, 1 sống 2 chết là xô 3, 1 chết 2 sống là xô 2
zQU2cJa.png


đáp án chúng nó đưa là kệ mẹ ko cần biết cách chọn mà chỉ cần xét số trường hợp mà 1 con heo có thể tạo ra là t+1 lần, ví dụ t=2 thì số th con heo tạo ra là 0, 10, 11, là chết lần thử đầu tiên, chết ở lần thử thứ 2, ko chết. n con heo có thể tạo ra (t+1)^n trường hợp, cần số trường hợp này >= số xô là được. Hư cấu vl, có tìm ra được cách chia ko mà phán vậy được
Dcnffay.png


---

à ờm toy nghĩ ra được cách chia ròi, đúng như bác bribnt nói là với n con có thể chia số xô thành 2^n phần. Như vậy sau 1 vòng từ x xô còn x / 2^n xô. Nhưng may mắn thì vòng sau mới còn n con heo thì mới chia tiếp cho 2^n được. TH xấu nhất là 1 con heo chết, nên vòng tiếp theo chỉ còn n-1 con nhiều trường hợp có 1 hoặc n con heo chết thì khác
zQU2cJa.png


ví dụ n=2 con heo, t=2 lần thử, x=9 xô nước. Đáp án chúng nó là được vì (t+1)^n = 3^2 >= 9. Đánh dấu 9 xô từ 1 tới 9 là 1 2 3 4 5 6 7 8 9. Sơ đồ Venn cho 2 con heo là [ vùng 1 { vùng 2 ] vùng 3 } vùng 4. Đặt 9 xô này vào 4 vùng một cách đều nhất có thể: [ 1 2 { 3 4 ] 5 6 } 7 8 9, hay cách chọn là con heo 1 uống xô 1 2 3 4, con heo 2 uống xô 3 4 5 6. Nếu ko con nào chết thì còn xô 7 8 9, 2 con trong 1 lần thử thì đã biết là làm được với 4 xô nên pass. Nhưng con 1 chết thì còn 4 xô 1 2 3 4, thế đéo nào mà 1 con còn lại thử được trong 4 xô
Dcnffay.png
Nếu vòng tiếp theo vẫn còn đúng n con heo thì còn 2 con trong 4 xô thì pass. Đề đéo nói 1 xô có thể uống vô tận lần, đéo nói số heo tối thiểu mỗi vòng chứ ko phải là số heo tổng cộng, chỉ nói "the minimum number of pigs needed" thì thằng lào hiểu được
Dcnffay.png


nếu đúng ra thì
1 con 1 lần thử có thể chia thành 2^1 vùng là tối đa 2 xô
2 con 2 lần thử có thể chia thành 2^2 vùng, th xấu nhất còn lại 1 con cho 1 lần thử thì tối đa lần này là 2 xô, vậy tối đa của 2 con 2 lần thử là 2 * 2^2 = 8 xô
vậy công thức đệ quy là x(n, t) = x(n - 1, t - 1) * 2^n, base case x(n, 1) = 2^n nhưng bài cần tìm n(x, t) chứ ko phải cần tìm x(n, t)


ế toy xai ròi
LTT2cUR.png
LTT2cUR.png
LTT2cUR.png

nếu con 1 chết con 2 sống thì chỉ còn xô 1 2 mới đúng chứ, 1 con 1 lần thử với 2 xô vẫn tìm được, vậy n=2 con heo, t=2 lần thử, x=9 xô nước vẫn đúng
0KSdPUp.png

phải xếp vào là [ 1 2 { 3 ] 4 5 } 6 7 8 9 mới đúng. Để 2 con cùng chết thì chỉ còn 1 xô là xô 3. 1 con chết thì còn 2 xô 1 2 hoặc 4 5. 2 con sống thì còn 4 xô. Như vậy xếp được đúng 9 xô thặc vi diệu
JSxuR2w.gif


sơ đồ ven 3 con, 2 lần thử (tối đa 27 xô):
1659791190122.png

số vùng k con chết là C(n, k) = C(n, n - k). Số xô tối đa đặt trong vùng có k con chết là x(n - k, t - 1).

vậy công thức tổng quát là
x(n, t) <= C(n, 0) * x(0, t - 1) + C(n, 1) * x(1, t - 1) + C(n, 2) * x(2, t - 1) + ... + C(n, k) * x(k, t - 1) + ... + C(n, n) * x(n, t - 1)
kH9BFd2.gif
kH9BFd2.gif
kH9BFd2.gif


dễ dàng
rl1Kgfo.gif
chứng minh vế phải <= (t+1)^n, xuy ra x <= (t+1)^n

để toy chứng minh biểu diễn cho
cgE9MkI.gif

giả sử x(n, t) <= (t+1)^n là đúng, ráp vào ta có x(k, t - 1) <= t^k, thế vào vế phải đống kia ta có
VP <= C(n, 0) * t^0 + C(n, 1) * t^1 + C(n, 2) * t^2 + ... + C(n, k) * t^k + ... + C(n, n) * t^n = (t+1)^n
đúng mọe luôn, thặc đéo thể tin nổi. Cm đàng quàng thì phải quy nạp gì đó nhưng ráp vô thấy khớp vậy được ròi
rl1Kgfo.gif
 
Last edited:
7/8/2022:
  • câu hard hôm nay khá dễ nhể.
  • gọi dp[n] là số lượng string kết thúc tại kí tự i có độ dài n.
  • dp[i.][n + 1] = dp[a.][n.] + ... + dp[z.][n.], a đến z là kí tự đằng sau của kí tự i.
  • như d['e'][n + 1] = dp['a'.][n.] + dp['i'][n.].
  • ra đáp án là tổng dp[các kí tự][n+ 1].
  • sau đó có thể tối ưu thành sapce O(1).
  • Code: https://leetcode.com/submissions/detail/767091654/
 
Bài hôm nay cứ tạo 5 biến a, e, i, o, u cho dễ nhìn. Chắc chỉ khó nếu muốn tìm cách không tạo thêm các biến tạm để lưu giá trị trước và sau thôi, chứ nếu tạo thêm biến tạm thì quá là đơn giản luôn.

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

C#:
public class Solution {
    public int CountVowelPermutation(int n) {
        long a = 1, e = 1, i = 1, o = 1, u = 1;
        long _a = 0, _e = 0, _i = 0, _o = 0, _u = 0;
       
        for (var num = 2; num <= n; num++)
        {
            _a = (e + i + u) % 1_000_000_007;
            _e = (a + i) % 1_000_000_007;
            _i = (e + o) % 1_000_000_007;
            _o = i;
            _u = (i + o) % 1_000_000_007;
           
            a = _a; e = _e; i = _i; o = _o; u = _u;
        }
       
        return (int)((a+e+i+o+u) % 1_000_000_007);
    }
}
 
Last edited:
Bài hôm nay là phiên bản dễ hơn của bài này:
https://leetcode.com/problems/number-of-distinct-roll-sequences/

toy làm đệ quy thoy vẫn được https://leetcode.com/submissions/detail/767113014/
JiZo9zf.png
JiZo9zf.png
JiZo9zf.png


thế lào mà mem tới 112MB chắc xai ở đâu đó
u3720e4.png

lưu đúng mà nó tính memory thế lào ko biết, chắc là tổng 43 test
g8XXj8u.gif

  • Đệ quy: tốn stack frame O(n). Trừ khi áp dụng được tail call optimization
  • Hash table: cũng tốn bộ nhớ hơn nhiều so với array. Bản chất nó là một array of linked list, mà linked list thì phải cấp phát động nhiều lần.
 
Bài hôm nay là phiên bản dễ hơn của bài này:
https://leetcode.com/problems/number-of-distinct-roll-sequences/



  • Đệ quy: tốn stack frame O(n). Trừ khi áp dụng được tail call optimization
  • Hash table: cũng tốn bộ nhớ hơn nhiều so với array. Bản chất nó là một array of linked list, mà linked list thì phải cấp phát động nhiều lần.
chạy ở trang khác nó ra cpu time: 0.07 sec, memory peak: 10 Mb, in thử cache.size() với n=20k nó cũng in ra đúng 100001. Tụi leetcode tính mem dỏm, đáng lẽ phải lấy trung bình, min max gì đấy đằng này chắc nó tính tổng
Xv0BtTR.png


100k phần tử, mỗi phần tử là pair<tuple<int, char>, int> cho là 12 bytes, thêm cái node next là 20 bytes là 2MB. Cho cái hash map có load factor 0.25 đi thì số bucket là 400k, nhân 8 byte là con trỏ mỗi bucket là 3.2MB, tổng cộng có tầm 5MB nó tính 112MB hư cấu
aVgiONl.png


dòng "Maximum resident set size" có ~5.5MB thoy
cgE9MkI.gif
hình như max load factor của unordered_map mặc định là 1
ghXpJrI.png
mà mỗi bucket hình như là 1 std::list tới tận 24 bytes
ghXpJrI.png
vậy mỗi node có tới 12+8+8=28 bytes
edit: https://stackoverflow.com/questions/67435837/implementation-of-bucket-in-unordered-map bảo libstdc++ xài dslk đơn còn msvc xài dslk đôi
edit: sao nó return lỗi
LTT2cUR.png
mà cho n=10 nó cũng ra y hệt 5.5MB, hư cấu rồi
LTT2cUR.png

edit: là do stack overflow
0KSdPUp.png
leetcode stack nó chắc 8MB nên ko bị, còn mingw của toy có 2MB stack nên tràn
LTT2cUR.png
 
Last edited:
7/8/2022:
  • câu hard hôm nay khá dễ nhể.
  • gọi dp[n] là số lượng string kết thúc tại kí tự i có độ dài n.
  • dp[i.][n + 1] = dp[a.][n.] + ... + dp[z.][n.], a đến z là kí tự đằng sau của kí tự i.
  • như d['e'][n + 1] = dp['a'.][n.] + dp['i'][n.].
  • ra đáp án là tổng dp[các kí tự][n+ 1].
  • sau đó có thể tối ưu thành sapce O(1).
  • Code: https://leetcode.com/submissions/detail/767091654/
Em cũng làm y thế này, đi từ đệ quy lên nhưng không hề để ý nó có thể tối ưu lên O(1) space.
KAUdgHo.gif


via theNEXTvoz for iPhone
 
Tự dưng dạo này lại có hứng thú lướt voz làm LC. Nay không có nhiều tgian như trước nên mỗi ngày làm một bài daily của LC thôi. Ae cùng tham gia vào chém gió hằng ngày.

Leetcode Daily là gì ?
Đơn giản là mỗi ngày trên LC sẽ random ra một bài đặt lên đầu trang, cả thế giới đều thấy, đc xem như một challenge nho nhỏ của ngày hôm đấy. Topic này sẽ thảo luận về cách giải của bài đấy. Ví dụ hôm nay (20/06/2022):

View attachment 1220198

Link tổng hợp

Tháng 6:
https://voz.vn/t/leetcode-moi-ngay.568742/post-18710590
Tháng 7:

Update:
Vì thớt này bàn về thuật toán nên sẽ show code khá nhiều khiến việc lội trang của ae bất tiện. Nên anh em chú ý phần nào có code thì cần để vào SPOILER.

p/s: Trước mình toàn đăng bài trong topic thuật toán bên kia nhưng h nó nhiều trang quá rồi, lội mệt. Với bên đó nhiều chủ đề quá đăng cái này vào sợ loãng.
Thread bổ ích
 
Bài hôm nay thì quá kinh điển rồi, nên phải làm kiểu nguy hiểm 1 chút, :D.

C++:
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        return accumulate(nums.begin(), nums.end(), vector<int>(), [](auto &acc, auto x) {
                            auto it = lower_bound(acc.begin(), acc.end(), x);
                            if (it == acc.end()) acc.push_back(x);
                            else *it = x;
                            return move(acc);
                          }).size();
    }
};
 
xào nấu lại code của thuyduong007 O(1) mem
JEWoIdl.png

C++:
    int lengthOfLIS(vector<int>& nums) {
        auto endSortedIt = begin(nums) + 1;
        for (size_t i = 1; i < nums.size(); ++i) {
            auto it = lower_bound(begin(nums), endSortedIt, nums[i]);
            swap(*it, nums[i]); // *it = nums[i] lẹ hơn nhưng xóa mất phần tử trong mảng ban đầu
            if (it == endSortedIt) ++endSortedIt;
        }
        return distance(begin(nums), endSortedIt);
    }
 
Back
Top