Ghi Chú Thuật Toán: Các Kỹ Năng Cơ Bản

Duyệt Cây

function duyetTruoc(goc) {
    if (goc) {
        duyetPath.push(goc.giaTri);
        duyetTruoc(goc.trai);
        duyetTruoc(goc.phai);
    }
}

function duyetGiua(goc) {
    if (goc) {
        duyetGiua(goc.trai);
        duyetPath.push(goc.giaTri);
        duyetGiua(goc.phai);
    }
}

function duyetSau(goc) {
    if (goc) {
        duyetSau(goc.trai);
        duyetSau(goc.phai);
        duyetPath.push(goc.giaTri);
    }
}

Đệ Quy

function deQuy(mucDo, thamSo1, thamSo2, ...) {
    // điều kiện kết thúc đệ quy
    if (mucDo > MUC_DO_TOI_DA) {
        hienThiKetQua;
        return;
    }
    
    // xử lý logic ở mức hiện tại
    xuLyDuLieu(mucDo, duLieu ...);
    
    // đệ quy sâu hơn
    deQuy(mucDo + 1, thamSo1, ...);
    
    // hoàn trạng thái mức hiện tại nếu cần
    hoanTinhTrang(mucDo);
}

Phân Chia và Chinh Phục

function chiaVaChinhPhuc(baiToan, thamSo1, thamSo2, ...) {
    // điều kiện kết thúc đệ quy
    if (baiToan == null) {
        hienThiKetQua;
        return; 
    }
    
    // chuẩn bị dữ liệu
    duLieu = chuanBiDuLieu(baiToan);
    cacBaiToanCon = chiaBaiToan(baiToan, duLieu);
    
    // chinh phục các bài toán con
    ketQua1 = chiaVaChinhPhuc(cacBaiToanCon[0], thamSo1, ...);
    ketQua2 = chiaVaChinhPhuc(cacBaiToanCon[1], thamSo1, ...);
    ketQua3 = chiaVaChinhPhuc(cacBaiToanCon[2], thamSo1, ...);
    ...
    
    // xử lý và tạo kết quả cuối cùng
    ketQuaCuoi = xuLyKetQua(ketQua1, ketQua2, ketQua3, ...);
}

Tìm Kiếm Theo Chiều Rộng (BFS)

function bfs(DoThi, diemBatDau, diemKetThuc) {
    hangDoi = [];
    hangDoi.push([diemBatDau]);
    daDuyet.add(diemBatDau);
    
    while (hangDoi.length > 0) {
        nut = hangDoi.shift();
        daDuyet.add(nut);
        
        xuLyNut(nut);
        cacNut = taoNutLienQuan(nut);
        hangDoi.push(cacNut);
        
    }
    // các xử lý khác
    ...
}

Tìm Kiếm Theo Chiều Sâu (DFS)

// Viết đệ quy
daDuyet = new Set();
function dfs(nut, daDuyet) {
    daDuyet.add(nut);
    // xử lý nut hiện tại tại đây.
    ...
    for (nutKe in nut.children()) {
        if (!daDuyet.has(nutKe)) {
            dfs(nutKe, daDuyet);
        }
    }
}
// Viết không đệ quy
function dfs(cay) {
    if (cay.goc == null) {
        return [];
    }
    daDuyet = [];
    nganXep = [cay.goc];
    while (nganXep.length > 0) {
        nut = nganXep.pop();
        daDuyet.add(nut);
        
        xuLyNut(nut);
        cacNut = taoNutLienQuan(nut);
        nganXep.push(cacNut);
    }
    // các xử lý khác
    ...
}

Tìm Kiếm Nhị Phân

trai, phai = 0, mang.length - 1
while trai <= phai:
    giua = trai + (phai - trai)/2
    if mang[giua] == mucTieu:
        // tìm thấy mục tiêu
        break or return ketQua
    elif mang[giua] < mucTieu:
        trai = giua + 1
    else:
        phai = giua - 1

Cây Từ Điển

Tính chất cơ bản

  1. Nút gốc không chứa ký tự, ngoài nút gốc mỗi nút chỉ chứa một ký tự.
  2. Từ nút gốc đến một nút nào đó, các ký tự trên đường nối lại tạo thành chuỗi tương ứng với nút đó.
  3. Tất cả các nút con của một nút chứa các ký tự khác nhau.
const KICH_THU_C_ALPHABET = 256;
class TrieNode {
    constructor() {
        this.children = new Array(KICH_THU_C_ALPHABET).fill(null);
        this.isEndOfWord = false;
    }
}

Bộ Lọc Bloom

Một vector nhị phân rất dài và một chuỗi các hàm ánh xạ ngẫu nhiên. Bộ lọc Bloom có thể được sử dụng để kiểm tra một phần tử có tồn tại trong một tập hợp hay không. Ưu điểm của nó là hiệu quả không gian và thời gian truy vấn vượt trội hơn nhiều thuật toán thông thường, nhược điểm là có tỷ lệ nhận dạng sai và khó xóa bỏ.

Thẻ: thuật toán Cấu trúc dữ liệu đệ quy tìm kiếm trie

Đăng vào ngày 27 tháng 5 lúc 11:05