剑指offer?

1. 在一个m*n二维数组中,每一行都按照从左到右的递增顺排序,每一列都按照从上到下的顺序排序,请完成一个函数,输入这样一个二维数组和一个整数,判断数组中是否含有该整数。
1 2 8 9
2 4 9 12
4 7 9 12
6 8 11 15

杨氏矩阵。这题有更好的做法吗?O(m+n)是最好的吗?网上说的分治法只对m=n的情况吧。

 1 bool find(vector<vector<int> > &arr, int t) {
 2     if (arr.empty() || arr[0].empty()) return false;
 3     int m = arr.size(), n = arr[0].size();
 4 
 5     int x = 0, y = n - 1;
 6     while (x < m && y >= 0) {
 7         if (t == arr[x][y]) return true;
 8         else if (t > arr[x][y]) x++;
 9         else y--;
10     }      
11     return true;
12 }

变种1:

求第k个数,我觉得能想出来用堆就不错了。n路归并,O(klgn),就是维护一个堆。

 1 struct Num {
 2     int val, row, col;
 3     Num(int r, int c, int v) : val(v), row(r), col(c) {}
 4 };
 5 
 6 class Comparator {
 7 public:
 8     bool operator() (Num &n1, Num &n2) {
 9         return n1.val > n2.val;
10     }
11 };
12 
13 int findKthSmallest(vector<vector<int> > &arr, int k) {
14     if (arr.empty() || arr[0].empty()) return false;
15     int m = arr.size(), n = arr[0].size();
16 
17     priority_queue<Num, vector<Num>, Comparator> mins;
18     for (int i = 0; i < k && i < n; ++i) {
19         mins.push(Num(0, i, arr[0][i]));
20     }
21     for (--k; k; --k) {
22         Num top = mins.top(); mins.pop(); 
23         if (top.row < n - 1) {
24             mins.push(Num(top.row + 1, top.col, arr[top.row + 1][top.col]));
25         }     
26     }
27     return mins.top().val;
28 }

这问题线性的比较难了。http://www.quora.com/How-can-you-efficiently-determine-the-k-th-maximum-element-in-a-MxN-sorted-matrix

可以用一个k大小的堆,O(klgk)。每次pop掉一个数,比如arr[i][j],然后把arr[i+1][j]和arr[i][j+1]进堆,代价是要有一个数组维护这个数是不是已经在堆里了。

变种2:

给定两个有序数组,长度分别为m和n,分别取出一个数再求和,共有m*n个数,求第k个和(从小到大)。

还是组成一个杨氏矩阵。

 1 int findKthSmallest2(vector<int> &arr1, vector<int> &arr2, int k) {
 2     if (arr1.empty() || arr2.empty()) return false;
 3     int m = arr1.size(), n = arr2.size();
 4 
 5     priority_queue<Num, vector<Num>, Comparator> mins;
 6     for (int i = 0; i < k && i < n; ++i) {
 7         mins.push(Num(0, i, arr1[0] + arr2[i]));
 8     }
 9     
10     for (--k; k; --k) {
11         Num top = mins.top(); mins.pop(); 
12         if (top.row < n - 1) {
13             mins.push(Num(top.row + 1, top.col, arr1[top.row + 1] + arr2[top.col]));
14         }     
15     }
16 
17     return mins.top().val;
18 }

2 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并输出它的后序遍历序列。 (本题可以直接输出来,不用先还原出二叉树)

原文地址:https://www.cnblogs.com/linyx/p/4017812.html