1.学习目标
1.按照如下类型来刷题:数组-> 链表-> 哈希表->字符串->栈与队列->树->回溯->贪心->动态规划->图论->高级数据结构,再从简单刷起,做了几个类型题目之后,再慢慢做中等题目、困难题目。
2.动手用多种语言来进行写题,并要有自己的代码模板。
3.总结程序员简历技巧。
2.每日一题
2.1题目
给定一个二进制矩阵 A,我们想先水平翻转图像,然后反转图像并返回结果。
水平翻转图片就是将图片的每一行都进行翻转,即逆序。例如,水平翻转 [1, 1, 0] 的结果是 [0, 1, 1]。
反转图片的意思是图片中的 0 全部被 1 替换, 1 全部被 0 替换。例如,反转 [0, 1, 1] 的结果是 [1, 0, 0]。
2.2思考
这道题说是图像,其实就是对数组的操作运算,另外这个题目有点特殊,说是矩阵,但更准确的是方阵,数组长宽相等。
对于写C的人来说,有点折磨,输入参数这么多,而且还不知道各自的用处,看了眼C++的输入参数,就只有一个数组。
然后总结下这道题的要点:
1.翻转。等同于逆序,就是将数组倒过来,这个我们简单的用双指针来实现。
2.反转。0变成1,1变成0,用异或就可以解决。
3.方阵。不管是不是方阵其实都无所谓,C++可以用.size()来获取大小,所以关系不是很大。
因此就是一个双层遍历来遍历整个数组,在内循环我们可以采用双指针法,一个指向left,一个指向right。然后left和right进行交换位置,这就是实现翻转。交换的同时我们也可以对值进行异或1的处理,这是对值的处理。这样反转和翻转都实现了。
2.3代码
class Solution {
public:
vector<vector<int>> flipAndInvertImage(vector<vector<int>>& A) {
int m = A.size();
for (int i = 0; i < m; i++) {
for (int j = 0, k = m - 1; j <= k; j++, k--) {
int a = !A[i][j], b = !A[i][k];// 或者 int a = A[i][j] ^ 1, b = A[i][k] ^ 1;
A[i][j] = b, A[i][k] = a;
}
}
return A;
}
};
3.哈希表
3.1题目
给定两个数组,编写一个函数来计算它们的交集。
3.2双指针法
这道题如果只用指针写的话,我的思路是这样的:
排序:先对两个数组进行排序(从低到高),时间复杂度为O(nlogn) + O(mlogm)。
遍历:用双指针进行遍历,指针分别指向两个数组的头端。如果指针1大于指针2,则指针2向后移位。如果指针2大于指针1,则指针1想后移位。如果两数相等,则记录该数存储到输出数组中作为交集,并且指针向后移动直到不等于这个“交集”的数。
结束条件:考虑一个数组提前遍历完的情况,此时只移动另外一个数组的指针,直到数值大于提前遍历完的那个数组的最大值。遍历的时间复杂度为O(m+n)。
这个方法主要的运算时间全部花在了排序算法上,但效率还是相当的好的。
3.3哈希表法
因为这个数值范围没有确定,所以使用之前数组做的简单的哈希表是不行的,然后这边推荐的是C++的set和map结构,这个我暂时还没学会,但试图钻研下用法吧。
先挂上别人的优秀代码:
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> result_set; // 存放结果
unordered_set<int> nums_set(nums1.begin(), nums1.end());
for (int num : nums2) {
// 发现nums2的元素 在nums_set里又出现过
if (nums_set.find(num) != nums_set.end()) {
result_set.insert(num);
}
}
return vector<int>(result_set.begin(), result_set.end());
}
};
个人理解(没看STL):
这里使用unordered_set 可以声明一个set类型,set类型可以简单的理解成是一个数据结构所组成的哈希表,可以保证set里的元素不重复。
然后它可以利用一个数组的两个下标来对哈希表进行初始化;还可以使用.find()在set里寻找是否存在。
4.闲聊
百度鸽我一次就算了,说好周四面试,现在还没消息,真的无法吐槽了!!!!今天投下字节跳动的岗位吧。