剑指offer 1
1 class Solution {
2 public:
3 bool Find(int target, vector<vector<int> > array) {
4 int s1 = array.size(), s2 = array[0].size();
5 int i = s1 - 1, j = 0;
6 while (i >= 0 && j < s2) {
7 if (array[i][j] == target) {
8 return true;
9 }
10 else if (array[i][j] > target) {
11 i--;
12 }
13 else {
14 j++;
15 }
16 }
17 return false;
18 }
19 };
本题还可采用其他分治策略,后续补充。
2. 替换空格
请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
分析:
插入元素如果从前向后插入的话需要O(n^2)的时间复杂度,考虑先把空格个数算出,然后从后向前复制。
代码:
1 class Solution {
2 public:
3 void replaceSpace(char *str,int length) {
4 int blankSz = 0;
5 for (int i = 0; i < length; ++i) {
6 if (str[i] == ' ') {
7 blankSz ++;
8 }
9 }
10 int i = length - 1, j = length + 2 * blankSz - 1;
11 while (i >= 0) {
12 if (str[i] != ' ') {
13 str[j] = str[i];
14 j--;
15 i--;
16 } else {
17 str[j] = '0';
18 str[j - 1] = '2';
19 str[j - 2] = '%';
20 i--;
21 j -= 3;
22 }
23 }
24 }
25 };
3. 从尾到头打印链表
输入一个链表,从尾到头打印链表每个节点的值
分析:
方法1:利用一个栈,把元素以此压栈,然后弹栈倒序输出;
方法2:利用递归(本质利用了系统的栈)
代码:
1 //方法1
2 class Solution {
3 public:
4 vector<int> printListFromTailToHead(ListNode* head) {
5 stack<int> st;
6 vector<int> result;
7 while (head != nullptr) {
8 st.push(head -> val);
9 head = head -> next;
10 }
11 while (!st.empty()) {
12 result.push_back(st.top());
13 st.pop();
14 }
15 return result;
16 }
17 };
18
19 //方法2
20 class Solution {
21 private:
22 vector<int> result;
23 public:
24 vector<int> printListFromTailToHead(ListNode* head) {
25 if (head != nullptr) {
26 printListFromTailToHead(head -> next);
27 result.push_back(head -> val);
28 }
29 return result;
30 }
31 };
4. 重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
分析:
思路就是手动做二叉树恢复的思路,在中序遍历中找到根节点的位置,然后对左右子树各自递归。注意代码的写法,helper函数的参数设计(要传起始终止位置,不要拷贝vector)和传递(搞不清楚就举例子)即可。
代码:
1 class Solution {
2 private:
3 TreeNode* helper(const vector<int>& pre, int prevStart, int prevEnd, const vector<int>& vin, int vinStart, int vinEnd) {
4 if (prevStart == prevEnd) {
5 return nullptr;
6 }
7 if (prevEnd - prevStart == 1) {
8 TreeNode* result = new TreeNode(pre[prevStart]);
9 return result;
10 }
11 int rootVal = pre[prevStart];
12 TreeNode* result = new TreeNode(rootVal);
13 int length = 0;
14 for (int i = vinStart; i < vinEnd; ++i) {
15 if (vin[i] != rootVal) {
16 length++;
17 }
18 else {
19 break;
20 }
21 }
22 result -> left = helper(pre, prevStart + 1, prevStart + length + 1, vin, vinStart, vinStart + length);
23 result -> right = helper(pre, prevStart + length + 1, prevEnd, vin, vinStart + length + 1, vinEnd);
24 return result;
25 }
26 public:
27 TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
28 TreeNode* result = helper(pre, 0, pre.size(), vin, 0, vin.size());
29 return result;
30 }
31 };
5. 用两个栈实现队列
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
分析:
思路1 stack1用来push, stack2用来pop(),每次pop()完把数据倒回到stack1中,保证满足队列顺序,但效率比较低;
思路2 stack1用来push, stack2用来pop(), 每次pop()前判定stack2是否为空,如果为空则将stack1中元素均倒入stack2,然后再在stack2中pop(),不空直接pop()stack2
代码:
1 //方法1
2 class Solution
3 {
4 public:
5 void push(int node) {
6 stack1.push(node);
7 }
8
9 int pop() {
10 while (!stack1.empty()) {
11 stack2.push(stack1.top());
12 stack1.pop();
13 }
14 int result = stack2.top();
15 stack2.pop();
16 while (!stack2.empty()) {
17 stack1.push(stack2.top());
18 stack2.pop();
19 }
20 return result;
21
22 }
23
24 private:
25 stack<int> stack1;
26 stack<int> stack2;
27 };
28
29 //方法2
30 class Solution
31 {
32 public:
33 void push(int node) {
34 stack1.push(node);
35 }
36
37 int pop() {
38 if (stack2.empty()) {
39 while (!stack1.empty()) {
40 stack2.push(stack1.top());
41 stack1.pop();
42 }
43 }
44 int result = stack2.top();
45 stack2.pop();
46 return result;
47
48 }
49
50 private:
51 stack<int> stack1;
52 stack<int> stack2;
53 };
6. 旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
分析:
思路1 二分搜索,用套路写就行,注意的是,其实由于更新start的条件只能在array[mid] > target时,start = mid,所以出循环后array[start]肯定不是解,可以不加那个判断;
思路2 可以用递归,注意分开两个区间的时候,有可能一个区间是非旋转的,所以递归终止条件是
if (rotateArray[0] <= rotateArray[n - 1]) {
return rotateArray[0];
}
可以同时处理两种情况。
代码:
1 class Solution {
2 public:
3 int minNumberInRotateArray(vector<int> rotateArray) {
4 int start = 0, end = rotateArray.size() - 1;
5 while (start + 1 < end) {
6 int mid = start + (end - start) / 2;
7 if (rotateArray[mid] == rotateArray[0]) {
8 start = mid;
9 }
10 else if (rotateArray[mid] < rotateArray[0]) {
11 end = mid;
12 }
13 else {
14 start = mid;
15 }
16 }
17 return rotateArray[end];
18 }
19 };


浙公网安备 33010602011771号