이진 검색 트리에 대한 몇 가지 결론

솔직히, 난 항상 트리 구조가 특히 복잡하다는 느낌이 주로 내가 정말 재귀 과정을 모르는, 그래서 항상 주로, (나는 순서 배열 BST 될 방법을 잊고, 지금) 잊지 그래서 나는 다음 쿼리에 대한 요약 ...... 그것을 이해하지 않습니다.

BST 이진 검색 나무는 매우 일반적인 구조, 일부 특히 좋은 특성이있다 :

  1. 노드의 모든 노드의 값은 N이 N은 동일하다 노드의 좌측 서브 트리 미만인
  2. N 노드 N의 우측 서브 트리를 초과하는 노드의 모든 노드의 값은 동일하다
  3. 왼쪽 하위 트리 오른쪽 서브 트리도 있습니다 BST

BST는 매우 중요한 기능이 있으므로 때문에 같은 특성 : 예약 주문은 사실 순서 배열의 결과입니다. 이 속성은 몇 가지 문제를 해결하는 데 사용할 수 있습니다.

다음과 같이 또한 설명의 편의상 상기의 TreeNode 구조는 이하 정의된다 :

struct TreeNode
{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

첫 번째는 BST의 정렬 된 배열로 변환하고,이 이분법을 사용하여 달성 될 수있다 :

TreeNode *getBST(vector<int> &nums, int b, int e)
{
    if (b == e)
    {
        return new TreeNode(nums[b]);
    }
    if (b > e)
    {
        return nullptr;
    }
    int mid = (b + e + 1) / 2;
    TreeNode *root = new TreeNode(nums[mid]);
    root->left = getBST(nums, b, mid - 1);
    root->right = getBST(nums, mid + 1, e);
    return root;
}

대량의 데이터가 중간 찾는 경우 중간 유사한 프로세스는 변경 될 수 b + ( e - b ) / 2첨가하여 피 오버플 감산한다.

이진 검색 트리의 모든 요구 사항 및 최소 절대 차이의 수 : 그런 특별한 종류의 사용을 비교합니다. 외모는 모두 현재 값의 상황에 따라 달라집니다의 예약 주문 이진 검색 트리가 있기 때문에 사실, 일종의, 아무것도 주문 에. 같은 순서 배열을 추구하는 회중의 수와 배열의 맥락에서 경우, 첫 번째 반응은 (아마도 다음과 같이 비어에 다른 번호를 발견 할 때마다 카운터를 얻을 후 최대 수를 찾을 확실히 모드)는 둘 이상의 수익보다 경우 :

vector<int> findModeInArray(vector<int> &arr)
{
    vector<int> mode;
    int max_count = 0;
    int cur_count = 1;
    int length = arr.size();
    for (int i = 1; i < length; ++i)
    {
        cur_count = arr[i] == arr[i - 1] ? cur_count + 1 : 1;

        if (cur_count == max_count)
        {
            mode.push_back(arr[i]);
        }
        else if (cur_count > max_count)
        {
            mode.clear();
            mode.push_back(arr[i]);
            max_count = cur_count;
        }
    }
    return mode;
}

다음 BST의 맥락에 배치하는 경우는 동일는 "번역"프로세스에 가깝습니다. 또한, 재귀 때문에, 우리는 함수의 시간 컨텍스트 매개 변수를 저장해야합니다. 전역 변수를 사용하는 경우, 전역 변수가 발생할 수 있습니다 예기치 않은 상황의 변화이다. 에서 솔루션 junstat @LeetCode :

void inOrder(TreeNode* root, TreeNode*& pre, int& curTimes, 
             int& maxTimes, vector<int>& res){
    if (!root) return;
    inOrder(root->left, pre, curTimes, maxTimes, res);
    if (pre)
        curTimes = (root->val == pre->val) ? curTimes + 1 : 1;
    if (curTimes == maxTimes)
        res.push_back(root->val);
    else if (curTimes > maxTimes){
        res.clear();
        res.push_back(root->val);
        maxTimes = curTimes;
    }
    pre = root;
    inOrder(root->right, pre, curTimes, maxTimes, res);
}
vector<int> findMode(TreeNode* root) {
    vector<int> res;
    if (!root) return res;
    TreeNode* pre = NULL;
    int curTimes = 1, maxTimes = 0;
    inOrder(root, pre, curTimes, maxTimes, res);
    return res;
}

그것은 같은 거의 정확하게 알 수있는 유일한 차이점은 문맥 BST의 맥락에서 사용 된 루프를 통과 할 어레이에 사용되는 재귀 순회 시퀀스이며, 각각의 반복 사용된다는 것이다 (약간의 폐쇄를 의미)에서 매개 변수의 데이터.

BST는 절대적인 최소 차이이다. 이 지시되기 때문에, 필연적으로 두 개의 인접한 소자들 사이의 가장 작은 절대 차를 생성한다. 어레이 컨텍스트 A는 다음 최소값 간의 차이를 찾는 것도 이전 말할 각각 사용 후에 감소되고 상기 BST의 맥락에서,이 같을 :

void inOrderTraverse(TreeNode *root, TreeNode *&pre, int &min_diff)
{
    if (root)
    {
        inOrderTraverse(root->left, pre, min_diff);
        if (pre)
        {
            min_diff = min(root->val - pre->val, min_diff);
        }
        pre = root;
        inOrderTraverse(root->right, pre, min_diff);
    }
}

int getMinimumDifference(TreeNode *root)
{
    TreeNode *pre = nullptr;
    int min_diff = INT_MAX; // #include <climits>
    inOrderTraverse(root, pre, min_diff);
    return min_diff;
}

그리고 나중에 축적 BST에 나무가 대상이 보았다 :

이진 검색 트리 (이진 검색 트리)를 감안할 때, 그것은 각 노드의 값이 노드 플러스의 모든 노드 값의 원래 값이 합계보다 큰되도록 축적 나무 (큰 나무)로 변환된다.

이 조금 특별한 (? 내가 특히 HashMap의 같은 것) 나는 누적 값을 해당 선주문이 다음 각 노드 HashMap에 저장 생각하기 시작, 다음으로 반복 다시 원래의 트리의 값을 수정 :

unordered_map<int, int> sum_map;

void traverse(TreeNode *root)
{
    if (root)
    {
        traverse(root->left);

        for (auto &p : sum_map)
        {
            p.second += root->val;
        }
        sum_map[root->val] = root->val;

        traverse(root->right);
    }
}

void convert(TreeNode *root)
{
    if (root)
    {
        convert(root->left);
        root->val = sum_map[root->val];
        convert(root->right);
    }
}

TreeNode *convertBST(TreeNode *root)
{
    traverse(root);
    convert(root);
    return root;
}

결과는 220ms를 나온 사람들은 바보입니다. 그런 다음 문제에 대한 해결책을 보았다뿐만 아니라, 일반적인 분위기는 말로 정말 어렵와 예약 주문 뒤로 발견 :

int sum = 0;

TreeNode *convertBST(TreeNode *root)
{
    if (root)
    {
        convertBST(root->right);

        sum += root->val;
        root->val = sum;

        convertBST(root->left);
    }
    return root;
}

하지만 배열의 컨텍스트에있는 경우, 아마 그런 연습, 그것은 생각합니다. 그래서, 아래로 요약, BST 아마도 그것은 또한 매우 간단 말하는, 그런 연습의 주제이다 :

  1. 배열의 맥락에서 연습을 고려
  2. 재귀 예약 주문

마지막으로, 단지 CPP를 인식 할 수 ++ 즉, CSDN 에디터가 실제로 MD C 인식하지 못하는 추가?

게시 92 개 원래 기사 · 원 찬양 (108) ·은 30000 +를 볼

추천

출처blog.csdn.net/HermitSun/article/details/104101536