想不到吧,毕业了,我还跑来刷算法题,不过确实忘了很多,所以。。。从头开始吧,日更新好吧,看看能不能坚持,嗯,手残了电脑没了另说。
目录
20220211两数之和
这么简单的题,为什么会纠结这么久。。。连代码都懒得贴(vector不像QVector,注意用法,and多上手。。。)
20220211两数相加
链表的使用还是需要进一步学习,这里一个有next的时候不能L1++,应该l1 =l1->next。还有新建一个结点的时候需要用L1->next=tmp,而不能L1=L1->nextp;L1=tmp;
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode * res = new ListNode(l1->val+l2->val);
ListNode * res_head = res;
l1 = l1->next;
l2 = l2->next;
while(l1 && l2)
{
//两数相加,先不考虑进位
int sum = l1->val + l2->val;
ListNode *tmp = new ListNode(sum);
res->next = tmp;
res = res->next;
l1 = l1->next;
l2 = l2->next;
}
//这个数字结束,就把另一个数字的剩余部分直接给res
if(l1 == NULL)
{
res->next = l2;
}
else if(l2 == NULL)
{
res->next = l1;
}
else
{
//sure ?
}
//对res进行进位操作
ListNode *res2 = res_head;
int carry = 0;
while(res_head->next != NULL)
{
res_head->val += carry;
if(res_head->val >= 10)
{
res_head->val -= 10;
carry = 1;
}
else
{
carry = 0;
}
res_head = res_head->next;
}
//考虑一下,最后一位的进位
res_head->val += carry;
if(res_head->val >= 10)
{
res_head->val -= 10;
ListNode *tmp = new ListNode(1);
res_head->next = tmp;
}
return res2;
}
};
20220213无重复字符的最长子串
首先昨天咕了,因为周六放假,一玩就没刹住车,嗯,因为学习算法看到人没了。
然后这道题,一开始是以为是KMP,还跑去复习半天,看懂以后发现不是一个题目(一个是最长子串,一个是无重复子串,我为什么会觉得是同一个?)。然后去看一眼题解(leetcode有题解,真的就舒服好多啊~),用滑动窗口(为什么我以前重来没听过。。。还是太逊了我)
- start不动,end向后移动
- 当end遇到重复字符,start应该放在上一个重复字符的位置的后一位,同时记录最长的长度(如果上一个重复字符的位置后一位在原start前面,则不调回start)
- 用map的key来判断是否重复,用value来记录该字符的下一个不重复的位置。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
map<char, int> hash;
int start = 0;
int res = 0;
for(int end = 0; end < s.length(); end++)
{
char ch = s.at(end);
if(hash.find(ch) != hash.end())
{
start = max(start, hash[ch]+1);//从上一个这个字符,的后一位,继续匹配
hash[ch] = end;//更新这个字符的位置
}
else
{
hash.insert(pair<char, int>(ch, end));//插入新的字符
}
res = max(res, end-start+1);//记录最长字长
}
return res;
}
};
todo:20220214寻找两个正序数组的中位数
是的,todo,昨晚一小时+今晚一小时,我决定,先拖回。。。
情人节一个人过就罢了,还要受这人间疾苦,下次再议
20220215二分查找
是的,因为被中等、困难打击到了,所以找了简单的题目做一下(才不是不想做题,所以找个简单应付一下)
这是个简单的二分查找,但是一开始因为我的start=mid-1,没有-1,导致超出时间了。。。
(ps:大家没事的时候练练爱好,例如口琴,那就要先找准口,发对音,慢慢练)
class Solution {
public:
int search(vector<int>& nums, int target) {
int start = 0;
int end = nums.size()-1;
int res = -1;
while(start <= end)
{
int mid = (start+end)/2;
if(target == nums[mid])
{
res = mid;
break;
}
else if(target < nums[mid])
{
end = mid - 1;
}
else //target > nums[mid]
{
start = mid + 1;
}
}
return res;
}
};
20220216轮转数组
这就好简单唉,虽然是简单题,但热热手还是不错的。(我就纳闷,项目里写注释,不是常识嘛,为什么要丢给我一份没注释的代码,难受一天了)。
class Solution {
public:
void rotate(vector<int>& nums, int k) {
int len = nums.size();
int rel_k = k % len;
vector<int> res(len);
for(int i = 0, j = len-rel_k; i < rel_k; i++, j++)
{
res[i] = nums[j];
}
for(int i = rel_k, j = 0; i < len; i++, j++)
{
res[i] = nums[j];
}
nums = res;
}
};
20220220最长回文子串(dp必须会)
这个题目一上来,就想到dp了,然后!dp忘了。。。所以中间去学dp啦。然后这不出差了嘛,所以拖了几天。(第一天坏了空调被冻在被窝不想出来,第二天收拾行李处理一些事,第三天刚到西安,咕咕咕)todo:这道题的题解有建议用马拉车算法,还说不会也背一下,嗯,下次一定
ps:个人愚见,做算法题,先学习嘛,所以一开始如果遇到不会的,不要丧气,看看人家怎么做的,集大成了,再去对自己做要求
class Solution {
public:
string longestPalindrome(string s) {
int n = s.size();
if(n == 1)
{
return s;//就一个字符,直接返回(题目设定n>=1)
}
vector<vector<int> > dp(n, vector<int>(n, 0));
for(int i = 0; i < n; i++)
{
dp[i][i] = 1;
}
int len = 1;
string res = s.substr(0, len);
for(int j = 1; j < n; j++)
{
for(int i = 0; i < j; i++)
{
if(s[i] != s[j])
{
dp[i][j] = 0;
}
else
{
if(j-i <= 2)
{
dp[i][j] = 1;//边界值
}
else
{
dp[i][j] = dp[i+1][j-1];//dp的精髓啊
}
}
if(dp[i][j] == 1 && j-i+1 > len)//更新长度
{
len = j-i+1;
res = s.substr(i, len);
}
}
}
return res;
}
};
20220222 Z字型变换
好吧,昨天晚上自己想了半天,然后就无了啊。中午参考了一下别人的题解,补一下
思路差不多,但是根据flag和row,管理好了下一个字符的位置
class Solution {
public:
string convert(string s, int numRows) {
if(numRows == 1)
{
return s;
}
int n = s.size();
//这是我一开始的想法,填表来着,没想好怎么安排x和y,所以无了
//int t = numRows * 1.5;
//int col = (n/t) * (1+numRows/2) + (n/t*t == n ? 0 : 1);
//vector<vector<char> > rec(numRows, vector<char>(col, ' '));
vector<string> process(numRows, "");//将z字变换的过程模拟出来
int flag = 0;//0:向左,1:向下
int row = 0;//下一个s字符所处的行数
for(int i = 0; i < n; i ++)
{
process[row] += s[i];
//然后要判断,下一个字符的走向
if(flag)
{
row++;//向下走
}
else
{
row--;//向左走,也就是向上走
}
if(row == -1) // 0--=-1,上一个字符行数为0,不能再向上了
{
flag = 1;//所以下一个字符,应该是向下
row = 1;//向下的话,下一个字符的行数应该为1
}
else if(row == numRows)//numrows-1 ++ = numrows。到底了,应该向上走了
{
flag = 0;
row = numRows-2;
}
}
string res = "";
for(string tmp : process)
{
res += tmp;
}
return res;
}
};
20220224整数反转
这个题,没用什么算法,嗯。大体思路就是int转string,string转换(string好像可以直接颠倒),然后再转成int输出。然后我就写的这么烂了。。。
昨晚写的,但是因为没考虑到超出限制,然后以为有问题了,就重写了。。。(记得审题)
提醒:环境只能存储得下 32 位的有符号整数,意味着其数值范围为 [−2^31, 2^31 − 1]
class Solution {
public:
int reverse(int x) {
string strx = to_string(x);
int n = strx.size();
if(x < 0)
{
for(int i = 1; i <= n/2; i++)//考虑到去一位符号位
{
char tmp = strx[i];
strx[i] = strx[n-i];
strx[n-i] = tmp;
}
int pos = 1;
char tmp = strx[pos];
while(tmp == '0')
{
tmp = strx[++pos];
}
strx = "-"+strx.substr(pos, n-pos+1);
}
else if(x > 0)
{
for(int i = 0; i < n/2; i++)
{
char tmp = strx[i];
strx[i] = strx[n-i-1];//注意好下标
strx[n-i-1] = tmp;
}
int pos = 0;
char tmp = strx[pos];
while(tmp == '0')//不会一直等于0的,所以不设限制
{
tmp = strx[++pos];
}
strx = strx.substr(pos, n-pos);//注意好长度
}
else//x == 0
{
return 0;
}
try
{
return stoi(strx);//超出限制了,要返回0。无语了我都
}
catch(...)
{
return 0;
}
}
};
然后这是人家好一点的代码(对啊,直接%不就行了嘛,还是对数据不够敏感)
int reverse(int x) {
int ans = 0;
while (x) {
if (ans > INT_MAX / 10 || ans < INT_MIN / 10)
return 0;
ans = ans * 10 + x % 10;
x /= 10;
}
return ans;
}
作者:tab-liu
链接:https://leetcode-cn.com/problems/reverse-integer/solution/7-zheng-shu-fan-zhuan-rust-c-python3-by-bhlin/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
20220226字符串转换成整数(atoi)
首先,强调读题。。。不知道为什么自己前面那么大意,题都没读好,就开干了
这道题,一开始什么都没想,正则匹配一下,然后就花了三天时间(当然也有因为最近10.下班的原因,想不到吧。领导说9.开个例会就下班,然后她9.40过来,讲讲到10.,她再整理一下我们上交的文档,就回去啦)
因为自己慢慢折腾嘛,就是先复习一下正则,然后提交,看哪里有问题,针对着改。。。
class Solution {
public:
int myAtoi(string s) {
// regex reg("[-]?[\\d]*[.]?[\\d]*"); //一开始以为要匹配浮点数
s = regex_replace(s, regex("^\\s*"), ""); //去除空格,而且是前置空格,中间的空格不消除
//regex_replace(s, regex(" "), "");则是去除所有空格
if(!isdigit(s[0]) && (s[0]!='-'&& s[0]!='+') || (s.size()>2 && !isdigit(s[1])))
//首字母不是数字,并且不是正负号的,直接return 0(貌似数据集不存在这个情况)
//+-,连续两个字符的情况。。。
{
return 0;
}
regex reg("[-+]?[\\d]*"); //匹配有符号整型
cmatch m;
auto flag = regex_search(s.c_str(), m, reg);
string res = m[0].str(); //结果放在这个m[0]里了
try
{
return stoi(res);//超出限制了,要返回0
}
catch(out_of_range&)
{
if (res[0] == '-')
{
return INT_MIN; //超出界限的情况,直接返回最值
}
else
{
return INT_MAX;
}
}
catch(...)
{
return 0; //else 也可以加个std::invalid_argument&
}
}
};
//遇到的稀奇古怪的情况。。。
// 24
//-24
//+-24
//-91283472332
//3.1415926
// +0 123
20220228回文数
emmm,一个很简单的题目,嗯,然后被我弄复杂了,就很难受。想到了从数字入手,然后节省一半时间,弄个prefix和suffix,结果最后纠结在prefix+suffix==x。难道直接prefix==suffix不行嘛。折腾两天了,嗯,昨天周日没躺平而是在改错
(不过,要准备考研的话,可能没时间再做题了,也许辞职以后专心考研,可能还能抽个一小时做会。也是在担心,中间没管住自己,该怎么办)
class Solution {
public:
bool isPalindrome(int x) {
if(x < 0 || (x>0&&x%10==0))//有个负号,或者个位是0,不可能回文
{
return false;
}
int suffix = 0;
while(x > suffix)
{
suffix = suffix*10 + x%10;
x /= 10;
}
return suffix==x || suffix/10==x;
// int prefix = 0;
// int suffix = x;
// int digit = 0;
// while(suffix >= prefix)
// //suffix的位数比prefix多,相等的时候,就是 x.size()/2 了
// {
// prefix = prefix*10 + suffix%10;
// suffix /= 10;
// digit++;
// }
// for(int i = 0; i < digit-1; i++)
// {
// prefix *= 10;
// }
//error了,不用看
// if(suffix)
// {
// return prefix+suffix == x;
// }
// else
// {
// return prefix == x;
// }
}
};