前言
小白一枚,在做题的过程中发生了很多好笑的事情,以供一笑…^~^
题组一:数组与字符串
题目一:https://leetcode-cn.com/leetbook/read/array-and-string/yf47s/
- 在使用accumlate函数的过程中忘记了添加头文件<numeric>
- 忘记了accumulate函数的第二个参数对应迭代器的值是不参与求和计算的
- 在调试的过程中忘记vector的初始化是采取{1,2,3}的赋值形式,而非[1,2,3]
- 第一道leetcode花了我两个小时^~^!,不是算法不过关(其实也不行),而是语法一堆错
- 其实可以用左边的和等于总和的一半来做,这样总和只要在进循环之前进行一遍即可,而左边的和可以采用累加的方式来进行,这样就不用用accumulate,时间复杂度从n方降到n
- vector支持随机访问,这样可以不用迭代器,用下标来替代,(操作已有的元素可以用下标,插入新元素不可以用下标)
class Solution {
public:
int pivotIndex(vector<int>& nums) {
if (accumulate(nums.begin()+1, nums.end(), 0) == 0) { return 0; }
int answer = 1;
int leftTotal = 0;
int rightTotal =0;
for (vector<int>::iterator it = nums.begin()+1; it != nums.end(); ++it) {
leftTotal = accumulate(nums.begin(), it, 0);
rightTotal = accumulate(it + 1, nums.end(), 0);
if (leftTotal == rightTotal) {
return answer;
}
else {
++answer;
}
}
return -1;
}
};
收获:
- 学会了调试,下面是调试代码,可以更改例子,然后设置断点,逐语句调试的过程中监视关键数据,我就是这样发现leftTotal不对劲的:
#include <iostream> #include<vector> #include<numeric> using namespace std; class Solution { public: int pivotIndex(vector<int>& nums) { if (accumulate(nums.begin() + 1, nums.end(), 0) == 0) { return 0; } int answer = 1; int leftTotal = 0; int rightTotal = 0; for (vector<int>::iterator it = nums.begin() + 1; it != nums.end(); ++it) { leftTotal = accumulate(nums.begin(), it, 0); rightTotal = accumulate(it + 1, nums.end(), 0); if (leftTotal == rightTotal) { return answer; } else { ++answer; } } return -1; } }; int main() { vector<int> num = { 1,7,3,6,5,6 }; Solution example; cout<<example.pivotIndex(num); }
- 其实还有很多更好的方法,这个方法只是第一感觉,要多多看看其他人的题解
题目二:https://leetcode-cn.com/leetbook/read/array-and-string/cxqdh/
- 花了一个小时,好耶!
- 看到题目的logn和查找,就想到了二分对半查找,算法是知道的,奈何从来没有用C++实现过,所以第一次忽略了很多操作,而且明明记得有个while(left < = right)主体,但是在使用的过程中用不上!所以实操是很重要的!!于是就用了left = mid 和 right = mid来操作了,结果因为这个卡了好久呜呜,测试了很多个案例,后来发现没有考虑到target在两端的特殊情况,我可真是个大聪明啊[]~( ̄▽ ̄)~*,于是加上了开头的判断target与首尾元素大小的判断才通过了测试,对了,在修改的时候,我把其中一种情况的return给误删了,于是就有了下面这段,萌萌的我百度了好久,后来〒▽〒,额。。。调试是个好东西,断点逐语句
- 做完后看了其他人的解法,我才想起来,原来应该left=mid+1,right=mid-1的呀o(TヘTo),下次一定
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
if (target <= nums[0]) { return 0; }
else if (target > nums[right]) { return nums.size(); }
for (int mid = (left + right) / 2; left < right;) {
mid = (left + right) / 2;
if (target == nums[mid]) { return mid; }
else if (right - left == 1) { return right; }
else if (target > nums[mid]) {
left = mid;
}
else {
right = mid;
}
mid = (left + right) / 2;
}
}
};
题目三:https://leetcode-cn.com/leetbook/read/array-and-string/c5tv3/
- 题目花了一个半小时,可惜的是二维数组是在下一节才学,刚开始写的时候想过先排序,后来觉得没有这个必要,就直接写了,想法是先创造一个二维数组,再把原数组的一个个插入合并进去,但是再如何插入合并的过程想的太复杂了,分成了判断左右区间落在答案数组的那个区间,反正弄得乱七八糟的,后来忍不住看了眼参考,先排序ε(┬┬﹏┬┬)3,然后就会灰溜溜的回去排序了,后来已看排完序后可以保证前后两个区间的左端点是有序的,问题就变成了,有没有交集,没有直接添加,有交集完不完全包含,包含接下一个,不包含的话改下答案数组的右端点即可
这是乱七八糟的未完成版
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
vector<vector<int>> answer;
while (!intervals.empty()) {
int left = leftInWhichgroup(intervals, answer);
int right = rightInWhichgroup(intervals, answer);
if (left) {
if (right) {
if (right - left == 0) {
intervals.erase(intervals.begin());
}
}
}
}
}
int leftInWhichgroup(vector<vector<int>> target, vector<vector<int>> answer) {
int zu = 1;
for (vector<vector<int>>::iterator it = answer.begin(); it != answer.end(); ++it,++zu) {
if ((target[0][0] > (*it)[0]) && (target[0][0] < (*it)[1]))return zu;
}
return false;
}
int rightInWhichgroup(vector<vector<int>> target, vector<vector<int>> answer) {
int zu = 1;
for (vector<vector<int>>::iterator it = answer.begin(); it != answer.end(); ++it, ++zu) {
if ((target[0][1] > (*it)[0]) && (target[0][1] < (*it)[1]))return zu;
}
return false;
}
};
这是第一次样本通过却超时的版本
class compare {
public:
bool operator()(vector<int> &v1, vector<int> &v2) {
return v1[0]<v2[0]; //传入的应该是*it,也就是一个vector<int>
} //这里不能写成if()return true;因为忽略了else的情况
};
static bool cmp(const vector<int>& a, const vector<int>& b) {
return a[0] < b[0];
}
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
sort(intervals.begin(), intervals.end(),compare());
vector<vector<int>>answer;
int t = 0;
answer.push_back(intervals[0]);
while (!intervals.empty()) {
if (intervals[0][0] > answer[t][1]) {
answer.push_back(intervals[0]);
++t;
intervals.erase(intervals.begin()); }//是v1.erase(v1.beigin())
else {
if(intervals[0][1]>answer[t][1]) //少
answer[t][1] = intervals[0][1];
intervals.erase(intervals.begin());
}
}
return answer;
}
};
我猜测是因为原vector不断地删除头元素,重新配置空间导致的吧,哦还有顺便复习了下sort的用法和谓词的写法,听说直接用静态函数也可以
这是通过版
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
sort(intervals.begin(), intervals.end());
vector<vector<int>>answer;
int t = 0;
int i =0;
answer.push_back(intervals[0]);
while (t!=intervals.size()) {
if (intervals[t][0] > answer[i][1]) {
answer.push_back(intervals[t]);
++i;
}
else {
if(intervals[t][1]>answer[i][1]){
answer[i][1] = intervals[t][1];}
}
++t;
}
return answer;
}
};
题目四:https://leetcode-cn.com/leetbook/read/array-and-string/clpgd/
- 旋转90度的话大概就是对角线翻转,然后再来水平翻转下了,那就是选对角线的问题了,如果是左对角线(从左上到右下),水平翻转就很简单,直接在一行里reverse(),记住先行后列,如果是右对角线,就要麻烦点,上下翻转的话就涉及到不同的行
自己写的版本
class Solution {
public:
int temp = 0;//注意:vector<vector<int>>temp;不方便 下面的应该是temp[0][0]=matrix[i][j]
void rotate(vector<vector<int>>& matrix) {
for (int i = 0; i != matrix.size();++i) {
for (int j = i; j != matrix[0].size(); ++j) {
temp = matrix[i][j]; //其实可以用swap
matrix[i][j] = matrix[j][i];
matrix[j][i] = temp;
}
}
for (auto i = 0; i != matrix.size(); ++i) {
reverse(matrix[i].begin(), matrix[i].end());
}
}
};
评论区看到一个更简洁的理想版本,为什莫我就写不出这种风格┭┮﹏┭┮
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int N = matrix.size();
//对角线翻转 —— std::swap
for(int i = 0; i < N; i++)
for(int j = i + 1; j < N; j++)
swap(matrix[i][j], matrix[j][i]);
//水平翻转 —— std::reverse
for(auto& vec: matrix)
reverse(vec.begin(), vec.end());
}
};
作者:TX牧野
链接:https://leetcode-cn.com/leetbook/read/array-and-string/clpgd/?discussion=SR44lT
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
可爱的std
题目五:https://leetcode-cn.com/leetbook/read/array-and-string/ciekh/
- 题目理解没问题,半个小时过✌,自己的思路就是遍历一遍,记录下为0的(i,j),用二维vector一个个push_back进去就好,然后再实现这个数组涉及的行改0,涉及的列改0,值得注意的是不能一边遍历一边改,因为改完的元素会影响到后面遍历的元素,所以要记录下来,再改,这个思想跟那个py里的生命游戏有点像, 都是记下所有的,再改,不能影响当前状态
- 看评论里还有一个想法是,不用记录具体位置,只要记录哪行哪列是0即可,然后遍历一遍数组,数组元素里是这些行或者列的改为0即可
下面是我的版本
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
vector<vector<int>> v;
for (auto i = 0; i != matrix.size();++i) {
for (auto j = 0; j != matrix[0].size();++j) {
if (matrix[i][j] == 0) {
v.push_back({ i,j });
}
}
}
for (auto i = 0; i != v.size(); ++i) {
for (auto row = 0; row != matrix[0].size(); ++row) {
matrix[v[i][0]][row] = 0;
}//行上改0
for (auto col = 0; col != matrix.size();++col) {
matrix[col][v[i][1]] = 0;
}//列上改0
}
}
};
题目六:https://leetcode-cn.com/leetbook/read/array-and-string/cuxq3/
罢笔Q了,这题我放弃了,写了好久。。。
题目七:https://leetcode-cn.com/problems/longest-common-prefix/submissions/
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
string answer = "";
if(strs.empty()||strs[0]=="")return answer;
if(strs.size()==1){return strs[0];}
for (int i = 0;; ++i) {
for (int k = 1; k != strs.size(); ++k) {
if (strs[k][i] != strs[0][i] || i == strs[k].size()) {
return answer;
}
}
answer += strs[0][i];
}
return answer;
}
};
果然还是得面面俱到啊,弄清楚每一轮循环该做什么,同时该层循环该控制的条件,该做的事