thảo luận [Học Tập] Topic thuật toán

Cách này sai nhé, bài này là directed graph, phản ví dụ: [[2,3],[3,4],[1,4],[1,2]]
Link đề gốc ở leetcode: https://leetcode.com/problems/redundant-connection-ii/

Lần sau đồng chí nào đưa bài thì đưa cả constraint nhé.
Ví dụ này thì logic nào để delete đây? :(
Huynh đài review giúp xem cái script này sửa sao giúp với:
Thấy không ai nhận nên mình thử làm cho vui (Bảo đảm chỉ đúng với 2 test cases trong bài :LOL:, anh em chém nhè nhẹ @Nipin ):

Python:
from collections import defaultdict


def make_rooted_tree(list_of_lists):
    element_dict = defaultdict(list)
    root = 0
    ret = []
    print("Input: {}".format(list_of_lists))
    for i in range(0, len(list_of_lists)):
        element_dict[list_of_lists[i][0]].append(list_of_lists[i][1])

    # find root and candidates to delete
    # find root node
    parents = list(element_dict.keys())
    children = list(element_dict.values())
    children = [item for sublist in children for item in sublist]
    children = list(set(children))
    print("List of parent nodes: {}".format(parents))
    print("List of children nodes: {}".format(children))
    # case A: if node in parents but not in children, it's a root
    for value in parents:
        if value not in children:
            root = value
            break
    # case B: if root cannot be found above, choose the node with the most children
    if root == 0:
        max_children = 0
        for key in element_dict:
            number_of_chidlren = len(element_dict[key])
            if number_of_chidlren > max_children:
                max_children = number_of_chidlren
                root = key
    print("Root node is {}".format(root))
    # find candidate edges to delete
    children_of_root = element_dict[root]
    print(children_of_root)
    # if both nodes of an edge are children of root, then it should be removed
    for key in element_dict:
        if key in children_of_root:
            list_of_key_children = element_dict[key]
            for child in list_of_key_children:
                if child in children_of_root:
                    ret.append([key, child])
    # if root is a child of a node, edge [node,root] should be removed
    for key in element_dict:
        if root in element_dict[key]:
            ret.append([key, root])
    return ret


if __name__ == "__main__":
    a = [[1, 2], [1, 3], [2, 3]]
    b = [[1, 2], [2, 3], [3, 4], [4, 1], [1, 5]]
    deleted_edge_a = make_rooted_tree(a)
    print("Edge to be deleted: {} \n ==========================================================".format(deleted_edge_a))
    deleted_edge_b = make_rooted_tree(b)
    print("Edge to be deleted: {} \n ==========================================================".format(deleted_edge_b))
 
Cách làm như thế thì chỉ xét cái edge có connect 2 node cùng thuộc connected component hay ko, nếu chọn root khác thì cũng vậy thôi. Thứ 2 là hướng của edge cũng ko xử lý. Ví dụ: 1->2, 2<-3, chẳng lẽ 1 vs 3 cùng thuộc component?
1620394092634.png
 
Ví dụ này thì logic nào để delete đây? :(
Huynh đài review giúp xem cái script này sửa sao giúp với:
Bỏ edge [1, 4] .
Cách giải thì có quan sát thấy cận bài này n nhỏ <= 1000 thì có cách trâu bò là xét từng edge 1 thôi. Khi đó bài toán trở thành tìm root của directed tree rồi check xem tree đó có connected ko.
 
Bỏ edge [1, 4] .
Cách giải thì có quan sát thấy cận bài này n nhỏ <= 1000 thì có cách trâu bò là xét từng edge 1 thôi. Khi đó bài toán trở thành tìm root của directed tree rồi check xem tree đó có connected ko.
Uhm, ý tôi là nên thêm 1 cái check cho trường hợp không tìm ra edge (có vẻ nông dân quá) hay đổi logic nguyên cái script
 
Gì vậy tía? Cái đề nói rooted tree chỉ có 1 node không có parent thôi mà? Đổi đề vậy ai chơi?
C++:
#include <bits/stdc++.h>
using namespace std;

class UnionFind {
private:
    vector<int> p;
public:
    UnionFind(int N) {
        p.assign(N, 0);
        for (int i = 1; i <= N; ++i) p[i] = i;
    }
    int findSet(int i) { return (p[i] == i) ? i : (p[i] = findSet(p[i])); }
    bool isSameSet(int i, int j) { return findSet(i) == findSet(j); }
    void unionSet(int i, int j) {
        if (isSameSet(i, j)) return;
        int x = findSet(i), y = findSet(j);
        p[y] = x;
    }
};
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    int V, E;
    cin >> V >> E;
    vector<tuple<int, int, int>> EL(E);
    for (int i = 0; i < E; ++i) {
        int u, v;
        cin >> u >> v;
        EL[i] = {1, u, v};
    }
    sort(EL.begin(), EL.end());
    UnionFind UF(V);
    for (int i = 0; i < E; ++i) {
        auto[w, u, v] = EL[i];
        if (UF.isSameSet(u, v)) {
            cout << u << " " << v;
            return 0;
        }
        UF.unionSet(u, v);
    }
}
 
C++:
#include <bits/stdc++.h>
using namespace std;

class UnionFind {
private:
    vector<int> p;
public:
    UnionFind(int N) {
        p.assign(N, 0);
        for (int i = 1; i <= N; ++i) p[i] = i;
    }
    int findSet(int i) { return (p[i] == i) ? i : (p[i] = findSet(p[i])); }
    bool isSameSet(int i, int j) { return findSet(i) == findSet(j); }
    void unionSet(int i, int j) {
        if (isSameSet(i, j)) return;
        int x = findSet(i), y = findSet(j);
        p[y] = x;
    }
};
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    int V, E;
    cin >> V >> E;
    vector<tuple<int, int, int>> EL(E);
    for (int i = 0; i < E; ++i) {
        int u, v;
        cin >> u >> v;
        EL[i] = {1, u, v};
    }
    sort(EL.begin(), EL.end());
    UnionFind UF(V);
    for (int i = 0; i < E; ++i) {
        auto[w, u, v] = EL[i];
        if (UF.isSameSet(u, v)) {
            cout << u << " " << v;
            return 0;
        }
        UF.unionSet(u, v);
    }
}
Hàm sort này là sort theo cái j vậy, ko rành c++ lắm?
 
C++:
#include <bits/stdc++.h>
using namespace std;

class UnionFind {
private:
    vector<int> p;
public:
    UnionFind(int N) {
        p.assign(N, 0);
        for (int i = 1; i <= N; ++i) p[i] = i;
    }
    int findSet(int i) { return (p[i] == i) ? i : (p[i] = findSet(p[i])); }
    bool isSameSet(int i, int j) { return findSet(i) == findSet(j); }
    void unionSet(int i, int j) {
        if (isSameSet(i, j)) return;
        int x = findSet(i), y = findSet(j);
        p[y] = x;
    }
};
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    int V, E;
    cin >> V >> E;
    vector<tuple<int, int, int>> EL(E);
    for (int i = 0; i < E; ++i) {
        int u, v;
        cin >> u >> v;
        EL[i] = {1, u, v};
    }
    sort(EL.begin(), EL.end());
    UnionFind UF(V);
    for (int i = 0; i < E; ++i) {
        auto[w, u, v] = EL[i];
        if (UF.isSameSet(u, v)) {
            cout << u << " " << v;
            return 0;
        }
        UF.unionSet(u, v);
    }
}
Tôi...thành thật thừa nhận là tôi đọc vài lần mới hiểu được nửa cái đoạn code này :surrender: .Tôi có vài đề xuất như sau:
1. Làm ơn đừng đặt biến viết tắt, hoặc bằng chữ in hoa (hay ít nhất cũng dùng Camel case)
2. Thêm comment
3. Giải thích cái đoạn ios_base::sync_with_stdio (line 29) và auto[w, u, v] (line 45)
 
à tui đang hơi nhầm, nhưng mà tui suy nghĩ lại một chút, tại sao mình ko đếm node nào có indegree = 2 là xong nhỉ?, hình như chỉ có 1 node như vậy
Chia TH cũng ok, mà sẽ có trường hợp tồn tại circle thì mỗi node đều có indegree = 1 nên phải xử lý riêng. Indegree = 2 thì phải xét xem edge nào bỏ đc, ví dụ 1->2, 2->3, 3->2.
 
Chia TH cũng ok, mà sẽ có trường hợp tồn tại circle thì mỗi node đều có indegree = 1 nên phải xử lý riêng. Indegree = 2 thì phải xét xem edge nào bỏ đc, ví dụ 1->2, 2->3, 3->2.
ban đầu tui định duyệt đỉnh, DFS cho mỗi đỉnh, đỉnh nào mà DFS 1 lần mà bôi đen được hết node và lưu được 1 back edge hoặc cross edge thì đỉnh ý là root còn cái phải loại là back edge hoặc cross edge vừa được lưu
 
Tôi...thành thật thừa nhận là tôi đọc vài lần mới hiểu được nửa cái đoạn code này :surrender: .Tôi có vài đề xuất như sau:
1. Làm ơn đừng đặt biến viết tắt, hoặc bằng chữ in hoa (hay ít nhất cũng dùng Camel case)
2. Thêm comment
3. Giải thích cái đoạn ios_base::sync_with_stdio (line 29) và auto[w, u, v] (line 45)
ừ fen.
1. giải mấy bài nhỏ thì hay đặt tên vớ vẩn lắm fen cho nó nhanh, tui đọc giải bọn nó code mà đau hết đầu, các mạng bọn nó toàn đặt là mảng a, mảng b theo chữ cái chứ ko rõ tên
2. có comment mà tui xóa mất tiêu rùi
3. cái ios_base là tăng tốc đọc file thôi, còn auto kia là cú pháp mới trong C++17 nói chung ko có liên quan gì đến thuật toán cả, ngôn ngữ thui
 
ừ fen.
1. giải mấy bài nhỏ thì hay đặt tên vớ vẩn lắm fen cho nó nhanh, tui đọc giải bọn nó code mà đau hết đầu, các mạng bọn nó toàn đặt là mảng a, mảng b theo chữ cái chứ ko rõ tên
2. có comment mà tui xóa mất tiêu rùi
3. cái ios_base là tăng tốc đọc file thôi, còn auto kia là cú pháp mới trong C++17 nói chung ko có liên quan gì đến thuật toán cả, ngôn ngữ thui
Đây có thật là mày không thế ?:rolleyes:
Giỏi C++ thế này tao giới thiệu cho mày đi intern code Unreal 4 luôn
Sau này có kinh nghiệm rồi sang Trung Quốc code game bom tấn lương 5000 $
 
Đây có thật là mày không thế ?:rolleyes:
Giỏi C++ thế này tao giới thiệu cho mày đi intern code Unreal 4 luôn
Sau này có kinh nghiệm rồi sang Trung Quốc code game bom tấn lương 5000 $
Thanh niên này như đa nhân cách ấy nhỉ ? mấy thread khác thì toàn hỏi mấy thứ đâu đâu, vào mấy thớt thuật toán chém kinh ! :rolleyes:
 
Đéo phải! Anh này thuộc dạng giỏi lí thuyết do đọc nhiều, nhưng khi làm việc thực tế lại làm éo được. Mấy cái anh ấy chém ở trên ai đọc nhiều thì biết, có khó khăn gì đâu!
Cá nhân thích làm việc với những người nắm chắc lý thuyết hơn, nói gì cũng hiểu cực nhanh. Còn người hổng căn bản nhưng làm được việc thì chỉ giỏi phần mà họ hay làm dựa trên kinh nghiệm, chệch đi tí là phải giải thích lại tư đầu rất mệt.
Từ lúc đi làm đến giờ loại thứ 1 cực hiếm gặp, loại thứ 2 lại rất nhiều. Kể cả sinh viên mới ra trường mà có chút kinh nghiệm cũng toàn thuộc loại 2, mấy bạn này kiểu thi qua môn xong là quên sạch, chỉ nhớ được những thứ hay dùng.
 
Mới xong, test của PropertyGuru Singapore.
Thời gian 20 phút.


View attachment 568957
Giải bằng Python (nhưng lố 20 phút :(). Mình test với 3 strings trong bài và một số string khác thì OK. Có điều tạch khi string là "aaaaaa...aaaaa" hay "bbbb...bbbb"

Python:
def semialtstring(s):
    str_len = len(s)
    tmp_list = []
    repeat_count = 0
    character_count = 1
    n = 1
    # print("Start at {}\n\ncharacter count is 1\n".format(s[0]))
    while n < str_len:
        # print("char {}\n".format(s[n]))
        character_count += 1
        if s[n] == s[n-1]:
            repeat_count += 1
        else:
            repeat_count = 0
            
        if repeat_count >= 2:
            # print("current repeat count is {}. Save current char_count to list. Reseting...\n".format(repeat_count))
            tmp_list.append(character_count-1) # Doesn't take the current character
            repeat_count = 0
            character_count = 2
        # print("repeat count: {}\n".format(repeat_count))
        # print("character count: {}\n".format(character_count))
        n += 1
        if n == str_len:
            tmp_list.append(character_count)
    return max(tmp_list)
    
if __name__ == "__main__":
    print("Semialtstring Solution\n")
    test_string = "abaaaa"
    print(semialtstring(test_string))
 
Back
Top