这两道题略微有点难,其中第一道题我自己解出来了,还补充了一个更好的解法,在空间上做了优化。
第二道题看了别人的题解,我正在努力理解。
题目一:
题意:为什么有n个元素,但是还有一些元素不存在呢?原因是有些元素重复了,比如2 2 3,2把1的位置给占了。
我的代码:
cpp
class Solution {
public:
vector<int> findDisappearedNumbers(vector<int>& nums) {
int n = nums.size();
unordered_set<int> s;
for(const auto&e:nums){
s.insert(e);
}
vector<int> res;
for(int i = 1;i<=n;i++){
if(!s.count(i)){
res.push_back(i);
}
}
return res;
}
};
更好的实现,对于空间做了优化:
cpp
class Solution {
public:
vector<int> findDisappearedNumbers(vector<int>& nums) {
for(auto e:nums){
e = abs(e);
if(nums[e-1]>0)nums[e-1]*=-1;
}
vector<int> res;
for(int i = 0;i<nums.size();i++){
if(nums[i]>0){
res.push_back(i+1);
}
}
return res;
}
};
还挺难理解的,我使用了两种方法帮助我理解它:
1)
可以使用一个数组来调试模拟一下过程,具体调试过程如下:
这次调试帮助我理解了代码本身:
首先我们利用范围for从数组中取出元素,注意这个nums[e-1] 。【由于我们是以下标来访问数组,可是nums数组本来值都是大于等于1的,所以我们要[e-1]。否则你访问不到nums[0],却访问到了nums[n]越界了】
另外,e要取绝对值,因为e有可能在if 条件中已经被变为相反数了,真实的数是它的绝对值。
继续:第二次for循环,最后push_back时应该把i +1 push进去,注意 i 是下标。比如我的调试结果中最后返回的结果是5 6,他俩对应原数组nums[4] nums[5] 的索引再加一。而不是nums[4] nums[5]的 元素8 和 元素2。
2)在纸上模拟:
以该数组为例:
题目二:
cpp
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
const int P = 131;
typedef unsigned long long ULL;
unordered_set<ULL> hash;
for(auto& word:wordDict){
ULL h = 0;
for(auto c:word){
h = h*P + c;
}
hash.insert(h);
}
//至此将wordDict中的字符串哈希之后放在了hash中。
int n = s.size();
vector<bool> v(n+1);
v[0] = true;
s = ' '+s;
for(int i = 0;i<n;i++){
if(v[i]){
ULL h = 0;
for(int j = i+1;j<=n;j++){
h = h*P +s[j];
if(hash.count(h)){
v[j] = true;
}
}
}
}
return v[n];
}
};
https://www.acwing.com/video/1505/