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.
Méo ngủ được, ngồi tìm hiểu cái digit dp, rồi cũng xong bài cuối:
Python:
class Solution:
    def numberOfBeautifulIntegers(self, low: int, high: int, k: int) -> int:
        @lru_cache(maxsize=None)
        def solve(s: str, tight: bool = True, i: int = 0, odd: int = 0, even: int = 0, modk: int = 0, leading_zero: bool = True) -> int:
            if i == len(s):
                return odd == even and modk == 0
           
            res = 0
            limit = int(s[i]) if tight else 9
            for j in range(limit + 1):
                new_tight = tight and int(s[i]) == j
                new_odd = odd + (j % 2 == 1)
                new_even = even + (j % 2 == 0)
                new_modk = (10 * modk + j) % k
                if leading_zero and j == 0:
                    res += solve(s, False, i + 1, 0, 0, 0, True)
                else:
                    res += solve(s, new_tight, i + 1, new_odd, new_even, new_modk, False)
                               
            return res
        return solve(str(high)) - solve(str(low - 1))
 
Sửa lần cuối:
Thấy hint bảo có Kruskal + DSU là thôi té luôn. Khỏi phải làm. Thật chứ đi pv mà bị hỏi cái này thì mình nghỉ luôn chứ làm gì nữa
qZV215Z.png

Thực ra là chỉ cần Kruskal thôi, DSU chỉ là một cách để implement Kruskal không có cũng được nhưng chậm hơn.

Bài này ở chỗ pseudo-critical, khi force một cạnh vào kết quả thì nó không còn là thuật toán Kruskal nữa mà thành một cái gì đó khác rồi. Nên cũng cần phải chứng minh cách làm nữa mới chuẩn.
 
Bài hôm nay trước đã làm rồi.
Đầu tiên cần build 2 graph cho item và group:
  • Những item thuộc group -1 được gán một group id khác không trừng với group có sẵn,
  • Cách build graph: dựa vào quan hệ trong beforeItems:
+ Nếu hai item khác group thì tạo cạnh trong group graph,​
+ Nếu hai item cùng group thì tạo cạnh trong item graph.​

Phương pháp thì là sắp xếp topo. Có hai trường hợp:
  • Không thể tìm được một thứ tự topo do item graph hoặc group graph không phải là DAG ==> không có thứ tự của item thỏa mãn đề bài, trả về rỗng
  • Có thứ tự topo cho cả item và group. Khi đó thứ tự tương đối của hai item được xác định như sau:
+ Nếu cùng group: item nào đứng trước trong topo sort cho item thì ở trước,​
+ Khác group: item thuộc group đứng trước trong topo sort thì đứng trước​

Dùng hàm sort với toán tử so sánh là thứ tự item như trên để ra kết quả.

https://leetcode.com/problems/sort-items-by-groups-respecting-dependencies/submissions/1026209425/
 
Giải 2 bài đầu bằng đt, bài 3 chắc là sort theo start end rồi greedy pick thôi hoặc ko ra thì xài Dp
Thôi té, mai giải vậy. Type bằng đt mệt quá :sweat:
À bài 2 cũng xài math thôi các fence, sum từ 1 tới n + k - k/2 - 1 rồi loại ra item từ k/2 < item < k.
O(1) kaka, beats 100% là chắc.
Đang chở vợ đi xem ca nhạc ồn quá ko tập trung nổi :too_sad:


via theNEXTvoz for iPhone
 
Sửa lần cuối:
Giải 2 bài đầu bằng đt, bài 3 chắc là sort theo start end rồi greedy pick thôi hoặc ko ra thì xài Dp
Thôi té, mai giải vậy. Type bằng đt mệt quá :sweat:
À bài 2 cũng xài match thôi các fence, sum từ 1 tới n + k - k/2 - 1 rồi loại ra item từ k/2 < item < k.
O(1) kaka, beats 100% là chắc.
Đang chở vợ đi xem ca nhạc ồn quá ko tập trung nổi :too_sad:


via theNEXTvoz for iPhone
bác chăm quá :ops:. vừa xem ca nhạc, vừa code luôn:eek:
 
Giải 2 bài đầu bằng đt, bài 3 chắc là sort theo start end rồi greedy pick thôi hoặc ko ra thì xài Dp
Thôi té, mai giải vậy. Type bằng đt mệt quá :sweat:
À bài 2 cũng xài math thôi các fence, sum từ 1 tới n + k - k/2 - 1 rồi loại ra item từ k/2 < item < k.
O(1) kaka, beats 100% là chắc.
Đang chở vợ đi xem ca nhạc ồn quá ko tập trung nổi :too_sad:


via theNEXTvoz for iPhone
Bài 3 không biết nghĩ đoạn sau sao xong em ốp luôn segment tree :after_boom:
Bài 4 thì không biết ở đây có ai hardcode 2 con trỏ không :too_sad::too_sad:
 
Bài 3 thì mình làm theo kiểu binary search, rồi update nó với thằng trước nó để nó luôn có giá trị lớn hơn thằng trước nó.
C++:
class Solution {
public:
    int maximizeTheProfit(int n, vector<vector<int>>& offers) {
        sort(begin(offers), end(offers), [](const auto& a, const auto& b){
            return a[0] < b[0];
        });
        
        int no = offers.size(), res = 0;
        for(int i = no - 1; i >= 0; --i){
            int j = upper_bound(begin(offers) + i + 1, end(offers), offers[i][1],
                [&](int v, const auto& x){return v < x[0];}) - begin(offers);
            if (j < no) offers[i][2] += offers[j][2];
            if (i < no - 1)
                offers[i][2] = max(offers[i][2], offers[i + 1][2] );
            res = max(res, offers[i][2]);            
        }
        return res;
    }
};
Bài 4: Cách thím làm cách nào, toàn bị TLE :( cùi quá
 
Bài 3 thì mình làm theo kiểu binary search, rồi update nó với thằng trước nó để nó luôn có giá trị lớn hơn thằng trước nó.
C++:
class Solution {
public:
    int maximizeTheProfit(int n, vector<vector<int>>& offers) {
        sort(begin(offers), end(offers), [](const auto& a, const auto& b){
            return a[0] < b[0];
        });
       
        int no = offers.size(), res = 0;
        for(int i = no - 1; i >= 0; --i){
            int j = upper_bound(begin(offers) + i + 1, end(offers), offers[i][1],
                [&](int v, const auto& x){return v < x[0];}) - begin(offers);
            if (j < no) offers[i][2] += offers[j][2];
            if (i < no - 1)
                offers[i][2] = max(offers[i][2], offers[i + 1][2] );
            res = max(res, offers[i][2]);           
        }
        return res;
    }
};
Bài 4: Cách thím làm cách nào, toàn bị TLE :( cùi quá
nhóm index của từng số lại -> duyệt từng số một -> vs mỗi số thì tìm subarray các index của số đó liên tiếp sao cho khảng cách ở giữa <= k bằng cách sliding window
Code mình nếu thím chưa hiểu kĩ: https://leetcode.com/problems/find-the-longest-equal-subarray/submissions/1026294642/
 
Bài 3 này trc daily có rồi, bài đó n <= 10^9 nên phải dùng binary search. Bài này n <= 10^5, ốp luôn dp luôn cho nhanh.
Code: https://leetcode.com/problems/maximize-the-profit-as-the-salesman/submissions/1026282310/
Bài 3 em làm theo kiểu dp là max profit nếu chỉ có tối đa i dãy nhà. Gọi đoạn đang xét là [l,r] thì dp = max(dp[0],dp[1],...,dp[l-1]) +profit[đoạn đang xét] . Nếu duyệt chay thì tổng độ phức tạp là O(n^2) nhưng mà dùng segment tree truy vấn max thì giảm còn O(nlog(max r))
 

Có bác nào học khóa "Cấu trúc dữ liệu và giải thuật Thực chiến với LeetCode'' của The Brown Box chưa? Cho e xin ít review với.​

 
Đọc Editorial có cái solution quỷ thật. Thôi cứ KMP cho đơn giản :go:
JavaScript:
function repeatedSubstringPattern(s: string): boolean {
    const n = s.length;
    if (n <= 1) {
        return false;
    }
    const table: number[] = Array(n).fill(0);
    let prefixLen = 0;
    let longestPrefixSuffix = 0;
    for (let i = 1; i < n; i++) {
        while (prefixLen > 0 && s[i] !== s[prefixLen]) {
            prefixLen = table[prefixLen - 1];
        }
        if (s[i] === s[prefixLen]) {
            prefixLen++;
        }
        table[i] = prefixLen;
        longestPrefixSuffix = prefixLen;
    }
    if (n % (n - longestPrefixSuffix) === 0 && longestPrefixSuffix > 0) {
        return true;
    }
    return false;
}
 
C#:
public bool RepeatedSubstringPattern(string s)
{
    int n = s.Length, m = n / 2, i, j, k;
    if (n == 1)
        return false;

    for (i = 1; i <= m; ++i)
        if (n % i == 0)
        {
            k = n - i;
            for (j = 0; j < k; ++j)
                if (s[j] != s[j + i])
                    break;
            if (j == k)
                return true;
        }

    return false;
}
 
ez đâu ko thấy phải có cái trick chia hết nữa
C++:
struct Solution {
    bool repeatedSubstringPattern(string_view s) {
        for (size_t i = 1; i <= s.size() / 2; ++i) {
            if (s.size() % i != 0) continue;
            const auto sub = s.substr(0, i);
            bool isRepeated = true;
            for (size_t j = i; isRepeated && j < s.size(); j += i)
                if (s.substr(j, i) != sub) isRepeated = false;
            if (isRepeated) return true;
        }
        return false;
    }
};
 
JavaScript:
const isPrime = n => {
    for (let i = 2; i <= Math.sqrt(n); i++) {
        if (n % i === 0) {
            return false;
        }
    }

    return true;
}

/**
 * @param {string} s
 * @return {boolean}
 */
var repeatedSubstringPattern = function(s) {
    for (let i = 2; i <= s.length; i++) {
        if (s.length % i !== 0 || !isPrime(i)) {
            continue;
        }

        const l = s.length / i;

        if (s.substring(0, l).repeat(i) === s) {
            return true;
        }
    }

    return false;
};
 
Làm cách nhanh hơn cách check các ước bình thường 2 lần (5ms vs 9ms). Chưa nghĩ ra cách O(n). Đọc đề thì cảm nhận có liên quan đến KMP mà chưa biết áp dụng thế nào
ghXpJrI.png
, Thực tế quên luôn cả cách implement KMP rồi.
yBBewst.png
 
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.212.793
Quay lại
Lên đầu trang