更新面试可能遇到以及遇到的算法题

排序

排序算法时间复杂度

alt

alt

快速排序

class Solution {
  public:
    vector<int> MySort(vector<int>& arr) {
      if (arr.empty()) {
        return arr; 
      }
      quick_sort(arr, 0, arr.size()-1); 
      return arr;
    }
  
  private:
    void quick_sort(std::vector<int> &arr, int low, int high) {
      if (left >= right) {
        return ;
      }
      
      std::swap(arr[left], arr[(left + right) / 2]);
      int key = arr[left];
      int l = left, r = right;
      
      while (l < r) {
        while (l < r && arr[l] <= key) ++l;
        while (l < r && arr[r] >= key) --r;
        std::swap(arr[l], arr[r]);
      }
      
      if (arr[l] > key) {
        --l;
      }
      
      std::swap(arr[l], arr[left]);
      
      quick_sort(arr, left, l - 1);
      quick_sort(arr, l + 1, right);
    }
};

归并排序

class Solution {
  public:
    vector<int> MySort(vector<int>& arr) {
      if (arr.empty()) {
        return arr; 
      }
      merge_sort(arr, 0 , arr.size()-1);
      return arr;
    }
  
  private:  
    void merge_elem(std::vector<int> &arr, int low, int mid, int high) {
      std::vector<int> temp;
      int i = low, j = mid + 1;
      
      // 排序插入
      while (i <= mid && j <= high) {
        if (arr[i] <= arr[j]) {
          temp.push_back(arr[i++]);
        } else {
          temp.push_back(arr[j++]);
        }
      }
      
      // 遍历剩下部分
      while (i <= mid) {
        temp.push_back(arr[i++]);
      }
      while (j <= high) {
        temp.push_back(arr[j++]);
      }
     
      // 拷贝回原数组
      for (int i = low, j = 0; i <= high; i++) {
        arr[i] = temp[j++];
      }
    }
    
    void merge_sort(std::vector<int> &arr, int low, int high) {
      if (low < high) {    // 分割到两个元素
        int mid = (low+high) / 2;
        merge_sort(arr, low, mid);
        merge_sort(arr, mid+1, high);
        merge_elem(arr, low, mid, high);   // 递归到两个元素后合并回退
      }
    }
};

堆排序

class Solution {
  public:
    vector<int> MySort(vector<int>& arr) {
      if (arr.empty()) {
        return arr; 
      }
      heap_sort(arr, 0, arr.size()-1);
      return arr;
    }
  
  private:
    void sink(std::vector<int> &arr, int node, int size) {
      while (2*node + 1 <= size) {
        int max_node = 2*node + 1;
        if (max_node < size && arr[max_node] < arr[max_node+1]) {  // 找到最大孩子
          max_node++;
        }
        if (arr[node] >= arr[max_node]) {
          break;
        } else {
          std::swap(arr[node], arr[max_node]);
        }
        node = max_node;   // 持续下沉到叶子结点或满足条件
      }
    }
    // 从零开始,使用(n-1)/2
    void heap_sort(std::vector<int> &arr, int low, int high) {
      for (int i = (high-1) / 2; i >= 0; i--) {   // 构建最大堆 
        sink(arr, i, high);
      }
      while (high > 0) {    // 交换-下沉 完成排序
        std::swap(arr[high--], arr[0]);   // 最大元素挪到末尾,再调整堆
        sink(arr, 0, high);
      }
    }
};

冒泡排序

class Solution {
  public:
    vector<int> MySort(vector<int>& arr) {
      if (arr.empty()) {
        return arr; 
      }
      bubble_sort(arr, arr.size()-1);
      return arr;
    }
  
  private:
    void bubble_sort(std::vector<int> &arr, int size) {
      for (int i = 0; i < size; i++) {  // n个元素循环n-1次
        for (int j = 0; j < size - i; j++) {  // 每次取出最大元素到最尾
          if (arr[j] > arr[j+1]) {
            std::swap(arr[j], arr[j+1]);
          }
        }
      }
    }
};

插入排序

class Solution {
  public:
    vector<int> MySort(vector<int>& arr) {
      if (arr.empty()) {
        return arr;
      }
      insertion_sort(arr, arr.size()-1);
      return arr;
    }
  
  private:
    void insertion_sort(std::vector<int> &arr, int size) {
      for (int i = 1; i <= size; i++) {
        int key = arr[i];
        int j = i - 1;
        while (j >= 0 && arr[j] > key) {
          arr[j+1] = arr[j];
          j--;
        }
        arr[j+1] = key;
      }
    }
};

选择排序

class Solution {
  public:
    vector<int> MySort(vector<int>& arr) {
      if (arr.empty()) {
        return arr;
      }
      selection_sort(arr, arr.size()-1);
      return arr;
    }
  
  private:
    void selection_sort(std::vector<int> &arr, int size) {
      // 第一层循环选中n-1个元素
      // 从选中元素后面 挑选出最小的元素与当前元素交换
      // 选中元素最小则不交换
      for (int i = 0; i < size; i++) {
        int min = arr[i];
        int index = i;
        for (int j = i+1; j <= size; j++) {
          if (arr[j] < min) {
            min = arr[j];
            index = j;
          }
        }
        if (index != i) {
          std::swap(arr[i], arr[index]);
        }
      }
    }
};

计数排序

class Solution {
  public:
    vector<int> MySort(vector<int>& arr) {
      if (arr.empty()) {
        return arr;
      }
      counting_sort(arr, arr.size()-1);
      return arr;
    }
  
  private:
    void counting_sort(std::vector<int> &arr, int size) {
      int max = arr[0];
      std::vector<int> copy_arr(arr);  // 辅助数组
      for (int i = 0; i <= size; i++) {
        if (arr[i] > max) {
          max = arr[i];
        }
      }  
      std::vector<int> temp(max+1, 0);  // 大小为数据区间
      for (int i = 0; i <= size; i++) {
        temp[arr[i]]++;  // 统计每个值出现的次数,存放在对应下标
      }
      // 计数累加
      for (int i = 1; i < temp.size(); i++) {
        temp[i] += temp[i-1];   // 记录当前值排的位数
      }
      // 反向填充数组
      for (int i = size; i >= 0 ; i--) {
        arr[--temp[copy_arr[i]]] = copy_arr[i];  // 索引比计数值小1,先自减
      }
    }
};

希尔排序

void shell_sort(std::vector<int> &a, int n) {
  int i,j,gap;

    // gap为步长,每次减为原来的一半。
  for (gap = n / 2; gap > 0; gap /= 2) {
        // 共gap个组,对每一组都执行直接插入排序
    for (i = 0 ;i < gap; i++) {
      for (j = i + gap; j < n; j += gap) {
                // 如果a[j] < a[j-gap],则寻找a[j]位置,并将后面数据的位置都后移。
        if (a[j] < a[j - gap]) {
          int tmp = a[j];
          int k = j - gap;
          while (k >= 0 && a[k] > tmp) {
            a[k + gap] = a[k];
            k -= gap;
          }
          a[k + gap] = tmp;
        }
      }
    }
  }
}     

二叉树的前中后序遍历(迭代)

/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 * };
 */

class Solution {
public:
    /**
     * 
     * @param root TreeNode类 the root of binary tree
     * @return int整型vector<vector<>>
     */
    vector<vector<int> > threeOrders(TreeNode* root) {
      if (root == nullptr) {
        return std::vector<std::vector<int>>(3, std::vector<int>());
      }
      
      std::vector<std::vector<int>> res;
      std::stack<TreeNode *> s;
      std::vector<int> tmp;
      
      s.push(root);
      
      while (!s.empty()) {
        TreeNode *cur = s.top();
        s.pop();
        tmp.push_back(cur->val);
        if (cur->right) {
          s.push(cur->right);
        }
        if (cur->left) {
          s.push(cur->left);
        }
      }
      
      res.push_back(tmp);
      tmp.clear();
      
      TreeNode *node = root;
      //  中序
      while (node || !s.empty()) {
        while (node) {
          s.push(node);
          node = node->left;
        }
        
        TreeNode *cur = s.top();
        s.pop();
        tmp.push_back(cur->val);
        node = cur->right;
      }
      
      res.push_back(tmp);
      tmp.clear();
      
      s.push(root);
      
      while (!s.empty()) {
        TreeNode *cur = s.top();
        s.pop();
        tmp.push_back(cur->val);
        if (cur->left) {
          s.push(cur->left);
        }
        if (cur->right) {
          s.push(cur->right);
        }
      }
      
      std::reverse(tmp.begin(), tmp.end());
      res.push_back(tmp);
      
      return res;
    }
};

设计LRU缓存

class Solution {
  public:
    Solution(int capacity) {
      cap = capacity;
    }
    
    int get(int key) {
      if (hash.count(key)) {
        int val = hash[key]->second;
        lru.erase(hash[key]);
        lru.push_front({key, val});
        hash[key] = lru.begin();
        return val;
      } else {
        return -1;
      }
    }
    
    void set(int key, int value){
      if (hash.count(key)) {
        lru.erase(hash[key]);
      } else if (lru.size() >= cap) {
        hash.erase(lru.back().first);
        lru.pop_back();
      } 
      
      lru.push_front({key, value});
      hash[key] = lru.begin();
    }
  private:
    int cap;
    std::list<std::pair<int, int>> lru;
    std::unordered_map<int, std::list<std::pair<int, int>>::iterator> hash;
};

/**
 * Your Solution object will be instantiated and called as such:
 * Solution* solution = new Solution(capacity);
 * int output = solution->get(key);
 * solution->set(key,value);
 */

TopK(小根堆还有快排变种)

//  小根堆
class Solution {
  public:
    int findKth(vector<int> a, int n, int K) {
      int res;
      
      //  创建k个元素的小根堆存放最大的k个元素
      create_heap(a, K - 1);
      
      for (int i = K; i < n; ++i) {
        if (a[i] > a[0]) {
          std::swap(a[i], a[0]);
          sink(a, 0, K - 1);
        }
      }
      
      //  堆顶就是第K大
      return a[0];
    }
  private:
    void create_heap(std::vector<int> &arr, int size) {
      for (int i = (size - 1) / 2; i >= 0; --i) {
        sink(arr, i, size);
      }
    }
  
    void sink(std::vector<int> &arr, int node, int size) {
      while (node * 2 + 1 <= size) {
        int min_node = node * 2 + 1;
        if (min_node < size && arr[min_node + 1] < arr[min_node]) {
          ++min_node;
        }
        if (arr[node] <= arr[min_node]) {
          return ;
        }
        std::swap(arr[node], arr[min_node]);
        node = min_node;
      }
    }
};
//  快排加分治
class Solution {
  public:
    int findKth(vector<int> a, int n, int K) {
      return quick_sort(a, 0, n - 1, K);
    }
  private:
    int quick_sort(std::vector<int> &arr, int left, int right, int k) {
      //  防止超时
      std::swap(arr[left], arr[(right + left) / 2]);
      int key = arr[left];
      int l = left, r = right;
      
      while (l < r) {
        while (l < r && arr[l] >= key) ++l;
        while (l < r && arr[r] <= key) --r;
        std::swap(arr[l], arr[r]);
      }
      
      if (arr[l] < key) {
        --l;
      }
      
      std::swap(arr[l], arr[left]);
      
      if (l + 1 == k) {
        return arr[l];
      } else if (l + 1 > k) {
        return quick_sort(arr, left, l - 1, k);
      } else {
        return quick_sort(arr, l + 1, right, k);
      }
    }
};

最小的K个数

//  快排加分治

class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
      if (input.empty() || k == 0) {
        return std::vector<int>();
      }
      
      quick_sort(input, k, 0, input.size() - 1);
      
      return std::vector<int>(input.begin(), input.begin() + k);
    }
  void quick_sort(std::vector<int> &input, int k, int left, int right) {
    if (left >= right) {
      return ;
    } 
    
    int key = input[left];
    int l = left, r = right;
    
    while (l < r) {
      while (l < r && input[l] <= key) ++l;
      while (l < r && input[r] >= key) --r;
      std::swap(input[l], input[r]);
    }
    
    if (input[l] > key) {
      --l;
    }
    
    std::swap(input[l], input[left]);
    
    if (l + 1 == k) {
      return ;
    } else if (l + 1 > k) {
      quick_sort(input, k, left, l - 1);
    } else {
      quick_sort(input, k, l + 1, right);
    }
  }
};
//  最大堆法
class Solution {
  public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
      if (input.empty() || k == 0) {
        return std::vector<int>();
      }
      
      //  建立k个元素的最大堆
      create_heap(input, k - 1);
      
      //  调整堆
      for (int i = k; i < input.size(); ++i) {
        if (input[i] < input[0]) {
          std::swap(input[0], input[i]);
          sink(input, 0, k - 1);
        }
      }
      
      return std::vector<int>(input.begin(), input.begin() + k);
    }
  private:
    void create_heap(std::vector<int> &input, int size) {
      for (int i = (size - 1) / 2; i >= 0; --i) {
        sink(input, i, size);
      } 
    }
   
    void sink(std::vector<int> &input, int node, int size) {
      while (node * 2 + 1 <= size) {
        int max_node = node * 2 + 1;
        if (max_node < size && input[max_node + 1] > input[max_node]) {
          ++max_node;
        }
        if (input[node] >= input[max_node]) {
          return ;
        }
        std::swap(input[node], input[max_node]);
        node = max_node;
      }
    }
};