Sword finger Offer questions 34-44

AcWing 46. Post order traversal sequence of binary search tree

Enter an integer array to determine whether the array is the result of post order traversal of a binary search tree.

If yes, it returns true; otherwise, it returns false.

Suppose that any two numbers of the input array are different from each other.

Sample
Input: [4, 8, 6, 12, 16, 14, 10]

Output: true

Solution:

  1. Middle order (the middle order of binary search tree is the result from small to large) + post order tree building
  2. The last number of postorder traversal is the root. For the nature of binary search tree, we directly find the value smaller than the root from scratch, which is the left subtree; The right part is the right subtree. If it does not match, it is an error.
class Solution {
public:
    vector<int>  seq;
    bool verifySequenceOfBST(vector<int> sequence) {
        seq = sequence;
        if(seq.empty()) return true;
        return dfs(1, seq.size() - 1);
    }
    bool dfs(int l, int r){
        if(l >= r) return true;
        int root = seq[r];
        int  k = 0;
        while(k < r && seq[k] < root) k++;
        for(int i = k; i < r; i++)
        {A
            if(seq[i] < root) return false;
        }
        return dfs(l, k - 1) && dfs(k, r - 1);
    }
};

AcWing 47. A path with a value in a binary tree

Enter a binary tree and an integer, and print out all paths where the sum of node values in the binary tree is the input integer.

A path is formed from the root node of the tree down to the leaf node.

Sample
The binary tree is given as follows, and num=22 is given.

dfs

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> res;
    vector<vector<int>> findPath(TreeNode* root, int sum) {
        if(root == NULL) return res;
        vector<int> path;
        dfs(root, sum, path);
        return res;
    }
    void dfs(TreeNode* root, int sum, vector<int>&path){
        if(root->left == NULL && root->right == NULL)
        {
            if(sum - root->val == 0)
            {
                path.push_back(root->val);
                res.push_back(path);
                path.pop_back();
            }
            return;
        }
        path.push_back(root->val);
        if(root->left != NULL) dfs(root->left, sum - root->val, path);
        if(root->right != NULL) dfs(root->right, sum - root->val, path);
        path.pop_back();
    }
};

AcWing 48. Reproduction of complex linked lists

Please implement a function that can copy a complex linked list.

In a complex linked list, in addition to a pointer to the next node, each node has an additional pointer to any node or null in the linked list.

be careful:

After the function, the original linked list should be consistent with the input.

  1. hash table mapping time O(n) space O(n)
/**
 * Definition for singly-linked list with a random pointer.
 * struct ListNode {
 *     int val;
 *     ListNode *next, *random;
 *     ListNode(int x) : val(x), next(NULL), random(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *copyRandomList(ListNode *head) {
        if(!head) return head;
        unordered_map<ListNode*, ListNode*> pos;
        for(auto p = head; p; p = p -> next)
        {
            pos[p] = new ListNode(p->val);
        }
        
        pos[NULL] = NULL;
        for(auto p = head; p; p = p -> next)
        {
            pos[p]->next = pos[p->next];
            pos[p]->random = pos[p->random];
        }
        return pos[head];
    }
};
/**
 * Definition for singly-linked list with a random pointer.
 * struct ListNode {
 *     int val;
 *     ListNode *next, *random;
 *     ListNode(int x) : val(x), next(NULL), random(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *copyRandomList(ListNode *head) {
        // Each node is followed by replication
        for(auto p = head; p; p = p->next)
        {
            auto np = new ListNode(p->val);
            auto next = p->next;
            p->next = np;
            np->next = next;
            p = np;
        }
        
        // Copy random pointer
        for(auto p = head; p; p = p->next->next)
        {
            if(p->random)
                p->next->random = p->random->next;
        }
        
        // Separate two linked lists
        auto dummy = new ListNode(-1);
        auto cur = dummy;
        for(auto p = head; p; p = p->next)
        {
            cur->next = p->next;
            cur = cur->next;
            p->next = p->next->next;
        }
        return dummy->next;
    }
};

AcWing 49. Binary search tree and bidirectional linked list

Enter a binary search tree and convert the binary search tree into a sorted two-way linked list.

It is required that no new node can be created, and only the node pointer in the tree can be adjusted.

be careful:

You need to return the leftmost node of the bidirectional linked list.
For example, if you enter the binary search tree on the left in the figure below, the sorted two-way linked list on the right will be output.

Problem solving ideas
The implementation can return the nodes at both ends of each sub tree

AcWing 50. Serialized binary tree

AcWing 51. Digital arrangement (good)

Enter a group of numbers (which may contain duplicate numbers) and output all their arrangement.

Sample
Input: [1,2,3]

Output:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]

Problem solution

The previous enumeration is different. You need to enumerate with the idea of space occupation. Open n pits in advance and put each number of nums in it. A number can only be placed after the previous same number.

class Solution {
public:
    int n = 0;
    vector<vector<int> > ans;
    vector<int> path;//position
    //u indicates the number of e nums, and start indicates the number of empty bits
    void dfs(int u, int start, int state, vector<int>& nums)
    {
        if(u == n)
        {
            ans.push_back(path);
            return;
        }
        
        // The first number or different from the previous number
        if(u == 0 || nums[u] != nums[u-1]) start = 0;
        for(int i = start; i < n; i++)
        {
            if(!(state>>i&1))
            {
                path[i] = nums[u];
                dfs(u + 1, i + 1, state+(1<<i), nums);
            }
        }
    }
    vector<vector<int>> permutation(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        n = nums.size();
        path.resize(n);
        dfs(0, 0, 0, nums);
    
        return ans;
    }
};

Library function

class Solution {
public:
    vector<vector<int>> permutation(vector<int>& nums) {
        sort(nums.begin(), nums.end());

        vector<vector<int>> res;
        do
        {
            res.push_back(nums);
        }while (next_permutation(nums.begin(),nums.end()));
        // do res.push_back(nums); while (next_permutation(nums.begin(), nums.end()));

        return res;
    }
};

AcWing 52. A number that appears more than half the time in the array

A number in the array appears more than half the length of the array. Please find out this number.

Suppose the array is not empty and there must be a number that satisfies the condition.

Thinking questions:

Assuming that only O(n) time and additional O(1) space are required, what should we do?
Sample
Input: [1,2,1,1,3]

Output: 1

Problem solution

The idea of offsetting (pairing).
Circular array

  1. count == 0: value=a[i], count=1
  2. count != 0:
    • value != a[i] : count -= 1
    • value == a[i] : count += 1

n villagers
Number of good people > n / 2 (correct answer)
Number of bad guys < n / 2 (random response)
o(n) inquiries to find the bad guy.

count: the number of times the current person is trusted, 0
val: who is the person, - 1

Ab initio circulation,

  1. count == 0, first ask yourself if you are trusted,
    The answer is good, count += 1, val = id
    Those who answer bad guys must be bad guys. Good people only answer that they are good people.
  2. count != 0. Ask val is a good person. If val is a good person, count += 1.
    If it is a bad person, count -= 1. If count is reduced to 0, replace
    The trust of good people.

The credit of good people must be greater than that of bad people. Consuming a good person must consume a bad person.

class Solution {
public:
    int moreThanHalfNum_Solution(vector<int>& nums) {
        int cnt = 0, val = -1;
        for(auto it: nums)
        {
            if(cnt == 0)
            {
                val = it;
                cnt ++;
            }
            else
            {
                if(val == it) cnt ++;
                else cnt --;
            }
        }
        return val;
    }
};

AcWing 53. Minimum number of k

Enter n integers to find the smallest number of k.

be careful:

The data guarantee k must be less than or equal to the length of the input array;
Please sort the elements in the output array from small to large;
Sample
Input: [1,2,3,4,5,6,7,8], k = 4

Output: [1,2,3,4]

Just use the large root heap for maintenance, (priority queue)

class Solution {
public:

    vector<int> getLeastNumbers_Solution(vector<int> input, int k) {
        priority_queue<int> heap;
        for(auto it : input)
        {
            
            if(heap.size() >= k)
            {
               
                if(it < heap.top())
                {
                    
                    heap.pop();
                    heap.push(it);
                }
            }
            else
                heap.push(it);
           
        }
        vector<int> res;
        for(int i = 0; i < k; i++)
        {
            res.push_back(heap.top());
            heap.pop();
        }
        reverse(res.begin(), res.end());
        return res;
    }
};
class Solution {
public:
    vector<int> getLeastNumbers_Solution(vector<int> input, int k) {
        priority_queue<int> heap;
        for (auto x : input)
        {
            if (heap.size() < k || heap.top() > x) heap.push(x);
            if (heap.size() > k) heap.pop();
        }
        vector<int> res;
        while (heap.size()) res.push_back(heap.top()), heap.pop();
        reverse(res.begin(), res.end());
        return res;
    }
};


AcWing 54. Median in data stream

How to get the median in a data stream?

If an odd number of values are read out from the data stream, the median is the value in the middle after all values are sorted.

If an even number of values are read from the data stream, the median is the average of the middle two numbers after all values are sorted.

Sample
Input: 1, 2, 3, 4

Output: 1,1.5,2,2.5

Explanation: every time a data stream reads in a data stream, it makes a judgment and outputs the current median.

Problem solution
Maintain two heaps. The large root heap maintains the smaller part and the small root heap maintains the larger part. Ensure that the maximum number of large heel heaps is only one more than the number of small root heaps. The implementation in the code is relatively simple.

class Solution {
public:
    priority_queue<int, vector<int>, greater<int> > heap_u;
    priority_queue<int> heap_d;
    int n = 0;
    void insert(int num){
        n++; 
        heap_d.push(num);
      
        while(heap_u.size() != 0 && heap_d.top() > heap_u.top())
        {
            int maxx = heap_d.top(), minn = heap_u.top();
            heap_d.pop(), heap_u.pop();
            heap_d.push(minn), heap_u.push(maxx);
        }
       
        
        if(heap_d.size() - heap_u.size() > 1)
        {
            heap_u.push(heap_d.top());
            heap_d.pop();
        }
    }

    double getMedian(){
        if(n & 1)
            return heap_d.top();
        else
            return (heap_d.top() + heap_u.top()) / 2.0;
    }
};

AcWing 55. Maximum sum of continuous subarrays

Enter a non empty integer array. The number in the array may be positive or negative.

One or more consecutive integers in the array form a sub array.

Find the maximum value of the sum of all subarrays.

The required time complexity is O(n).

Sample
Input: [1, - 2, 3, 10, - 4, 7, 2, - 5]

Output: 18

Problem solution
Status indication:
Set partition: continuous subarray ending with a[k]

  1. There is only a[k] one number
  2. At least two numbers, you must choose a[k], so you can remove a[k]

    Equivalent to f(k-1) + a[k]

f(k) = max{a[k], f(k-1) +a[k]}
f(k) = a[k] + max(0, f(k-1))
S = a[k] + max(0, S)

AcWing 56. Number of occurrences of 1 in integers from 1 to n

Tags: Algorithm

Posted on Sun, 05 Dec 2021 23:21:37 -0500 by BrianG