目录
写在开头
一刷到后面断更了,发现每题都写太浪费时间了。
一刷总结:数学问题、贪心、递归分治、数据结构二基本都刷完了,图论只刷了并查集和最小生成树,动态规划只刷了0-1背包,搜索勉强能看懂,基本写不出。大致看了一下目标院校的机试真题,对我现在的水平来说还是有点难orz,机试4题可能勉强才能做出1道吧。0A肯定是过不了复试的,目标:保1争2,确保常规题做出来。
二刷计划:一眼就看出解法的不敲了,思路不清楚的重新敲一遍。把不记得的重点记下来。计划一天一章+总结。
第3章 排序与查找
3.1 排序
总结
1、把几个比较重要的排序算法(冒泡、快排、堆排序)基本思想再过一遍,面试可能会问;
2、题目不是考排序的话直接调用algorithm库中的sort函数排序,注意sort函数不稳定,要稳定排序就调用stable_sort函数;
3、包含的信息比较多时考虑用结构体;
4、二刷这五题基本都是一遍AC。
3.2 查找
总结
1、查找最常用的一种思路:暴力查找,数据量不大的时候基本都能过;
2、数据量大时用二分查找能把时间复杂度降到logN,注意二分查找的循环条件,容易写错。
刷点经典题强化一下。
1、直接暴力查找,修改之后测试用例只能通过15/22 。
2、二分查找法
(1)思路:题目将数组边界看成最小值,只需要找到其中一个波峰,因此只要不断地往高处走,一定会有波峰。每次找一个标杆元素,将数组分成两个区间,每次就较高的一边走,因此也可以用分治来解决,而标杆元素可以选择区间中点。
(2)具体做法
- step 1:二分查找首先从数组首尾开始,每次取中间值,直到首尾相遇。
- step 2:如果中间值的元素 > 它右边的元素,说明往右是向下,不一定会遇到波峰,往左收缩区间。
- step 3:如果中间值 < 右边的元素,说明往右是向上,向上一定能有波峰,往右收缩区间。
- step 4:最后区间首尾相遇的点一定就是波峰。
(3)源代码
class Solution {
public:
int findPeakElement(vector<int>& nums) {
int left = 0, right = nums.size() - 1, mid;
while (left < right) {
mid = (left + right) / 2;
// 二分中点右边是往上的趋势
if (nums[mid] < nums[mid + 1]) // 这里我一开始写的是nums[mid] < nums[right],也能A
left = mid + 1 ;
else
right = mid;
}
// 循环结束left=right
return left;
}
};
二分查找-I_牛客题霸_牛客网 (nowcoder.com)
第一次分支判断条件写错了,最重要的跳出target == nums[mid] 没写;第二次发现循环条件不完整,应该是low <= high,而不是 low < high 。(只有二分查找中是小于等于)改了之后全部AC了。
class Solution {
public:
int search(vector<int>& nums, int target) {
int low = 0,high = nums.size() - 1,mid;
while(low <= high) { // 别漏了等于号
mid = (low + high) / 2;
if(target == nums[mid]) // 找到target
return mid;
else if(target < nums[mid]) // target < nums[mid]
high = mid - 1; // 在左半区间继续查找
else
low = mid + 1;
}
return -1; // 没找到返回-1
}
};
二维数组中的查找_牛客题霸_牛客网 (nowcoder.com)
1、暴力解法:遍历一遍矩阵,可以AC。
2、二分搜索:从一行开始使用二分查找,一直到最后一行。(发现这种方法比暴力耗时高)
3、线性搜索(开眼界了):利用二维数组行列递增特性
- 由于行列递增,可以得出:
a.在一列中的某个数字,其上的数字都比它小
b.在一行中的某个数字,其右的数字都比它大 - 搜索流程:
a.首先从数组左下角搜索.
b.如果当前数字大于target,那么查找往上移一位,如果当前数字小于target,那么查找往右移一位。
c.查找到target,返回true; 如果越界,返回false;
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
int row = array.size(); // 行数
int col = array[0].size(); // 列数
int i = row - 1, j = 0; // 从左下角开始
while (i >= 0 && j < col) {
if (target == array[i][j]) {
return true;
} else if (target > array[i][j]) {
// target > array[i][j],向右走
j++;
} else {
// target < array[i][j],向上走
i--;
}
}
return false;
}
};