指针练习(下)
Posted 长路慢
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了指针练习(下)相关的知识,希望对你有一定的参考价值。
76.最小覆盖子串
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。
如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
注意:
对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
示例 2:
输入:s = "a", t = "a"
输出:"a"
示例 3:
输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 a 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。
思路:
第一次做困难的题目,首先我们可以将示例2和示例3的两种情况做处理:
if (s.size() < t.size())
return "";
if ((s.size() == t.size()) && (s == t))
return s;
示例1应该是考察滑动窗口概念,但是貌似没看懂题意,后面你这道题目在补。
LeetCode See: https://leetcode.cn/problems/linked-list-cycle-ii/
633.平方数之和
给定一个非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 a2 + b2 = c
示例 1:
输入:c = 5
输出:true
解释:1 * 1 + 2 * 2 = 5
示例 2:
输入:c = 3
输出:false
思路:
输入一个数,拆分成两个数的乘机,如果不用数据库函数真的不好搞,一开始想的11 + xx = input,但这样显然不合理也不对
x*x = input - (1*1)
如果看作x && y ,总要先假设一个有数据的
for(int x = 0 ; x <= input; ++ x)
int y = input - (x*x);
平方根(y);
判断是否满足;
求平方根的函数应该需要包含math.c/cmath,具体我也忘了百度了一下,sqrt()函数,返回是浮点数(很多位),那么我们需要判断返回的是不是整数。
bool judgeSquareSum(int c)
for (float x = 0; x <= c; ++x)
float y = c - (x * x);
auto y_ = sqrt(y);
if (y_ == (int)y_)
return true;
return false;
提交以后缺报错,输入3:但是本地的vs没有错误
Line 8: Char 18: runtime error: -nan is outside the range of representable values of type int (solution.cpp)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior prog_joined.cpp:17:18
用了官方答案:
bool judgeSquareSum(int c)
for (long a = 0; a * a <= c; a++)
double b = sqrt(c - a * a);
if (b == (int)b)
return true;
return false;
不纠结了
LeetCode See: https://leetcode.cn/problems/sum-of-square-numbers/
680.验证回文字符串 Ⅱ
给定一个非空字符串 s,最多删除一个字符。判断是否能成为回文字符串。
示例 1:
输入: s = "aba"
输出: true
示例 2:
输入: s = "abca"
输出: true
解释: 你可以删除c字符。
示例 3:
输入: s = "abc"
输出: false
特意百度了一下: "回文串"是一个正读和反读都一样的字符串,比如"level"或者"noon"等等就是回文串。 根据题意,正反读aba成立,删除其中一个还能保证一致即可。
思路:
定义两个指针分别从指向头尾,首尾字母(ascii码)比较,end指向字符串最后一个字母来做移动,start来右移动。
// 首先如果<=2那一定是真,因为允许删除一个,怎么都是正确的。
const int lens = strlen(s.c_str());
if (lens <= 2)
return true;
const char* pstr = s.c_str(); const char* phead = s.c_str();
const char* pend = pstr + lens - 1;
int idx = 1;
while (pstr <= pend)
if (*pstr != *pend)
if (0 == idx--)
return false;
// 处理: "xccccccccccc" "eccer" "aydmda"
if (*pstr != *(pend - 1))
pend++;
else
pstr--;
pstr++; pend--;
return true;
测试用例报错了"ebcbbececabbacecbbcbe",会发现上面逻辑还是有欠缺。
笨办法, 添加一个check_tr函数,分别传入pstar+1和pend-1,如果pstar+1匹配后为真直接返回,否则在传入pend-1重新遍历一次,可以保证剩下的字符串是否一致.
可以在Check_tr加一个判断if_else来区分到底用那种比较好可能会提高进一步优化,我这里么有优化。
class Solution
public:
bool check_tr(const char* pstr, const char* pend)
while (pstr <= pend)
if (*pstr != *pend)
return false;
pstr++; pend--;
return true;
bool validPalindrome(std::string s)
const int lens = strlen(s.c_str());
if (lens <= 2)
return true;
const char* pstr = s.c_str();
const char* pend = pstr + lens - 1;
while (pstr <= pend)
if (*pstr != *pend)
bool nret = false;
check_tr(pstr+1, pend) ? nret = true : nret = check_tr(pstr, pend-1);
return nret;
pstr++; pend--;
return true;
;
虽然通过了测试用力,但是会发现问题,如果运气不好则会调用两次check_tr()。
从内到外查询也会有缺陷,从内到外查询的意思:计算star - end中间还剩多少字符串,end - start = ;llens / 2,余数不需要管。
const int lens = (pend - pstr) / 2;
如果对很大的字符串"bbaaaaa...... bacb ......aaaaaacb",指针从外围会很耗时间,从内围直接可以返回,但是如果遇到外围很大的字符串反之。
以上是关于指针练习(下)的主要内容,如果未能解决你的问题,请参考以下文章