目录
数组中两个字符串的最小距离:
本题是求两个字符串之间的最小距离,可以理解为求 str1 和 str2 下标差的最小值。
如果是找距离,我们只需要遍历数组,找到 str1 和 str2 所在的下标,作差即可。
那么如何找距离的最小值?我们可以根据示例2来理解, str1 为QWER, str2 为 666,
如图,我们用 prev1 来标记 str1 上次出现的下标,prev2 来标记 str2 上次出现的下标,把 prev1 和prev2 都初始化为 -1,不可以把 prev1 和prev2 初始化为 0,因为数组的下标从 0 开始,如果 str1 在数组下标为 0 的位置出现,此时 prev1 = 0,如果 str1 在数组中没有出现过,prev1 从来没有更新过,此时 prev1 的下标也为 0,那 prev1 = 0 时,我们无法判断 str1 有没有出现过。
开始遍历数组:
i = 0 时,字符串和 str1 相等,所以更新 prev1 的下标,由于 prev2 为 -1,即 str2 还没有出现,所以先不计算 str1 和 str2 的距离;
i = 1, i = 2 位置的字符串都和 str1、str2 不相等,所以继续向后访问;
i = 3时,字符串和 str2 相等,所以更新 prev2 的下标,因为 prev1 不为 -1,即 str1 已经出现过了,此时可以计算 str1 和 str2 之间的距离;
i = 4时,字符串和 str1 相等,所以更新 prev1 的下标,prev1 和 prev2 作差,然后和之前计算的距离的值作比较,得出距离的最小值;
数组遍历完时,距离的最小值也计算出来了。
#include <iostream>
using namespace std;
#include<string>
#include<vector>
int main() {
int n=0;//strs的长度
cin>>n;
string str1;
string str2;
cin>>str1>>str2;
int prev1=-1;//str1上次出现的下标,初始化为-1
int prev2=-1;//str2上次出现的下标,初始化为-1
string s;
int ret=n+1;//距离可以初始化为n+1
for(int i=0;i<n;i++)//依次输入字符串
{
cin>>s;
if(s==str1) prev1=i;//当前字符串为str1,prev1更新为本次出现的下标
if(s==str2) prev2=i;//当前字符串为str2,prev2更新为本次出现的下标
if(prev1!=-1 && prev2!=-1)//如果str1 和 str2 都出现过
{
ret=min(ret,abs(prev1-prev2));//更新此时距离的最小值
}
}
if(prev1==-1 || prev2==-1)//如果str1或str2没出现过
cout<<-1<<endl;
else
cout<<ret<<endl;
return 0;
}
上一道题是针对两个元素之间的距离,如果是多个元素,我们没办法定义很多个变量,一个个标记它们上一次出现的下标,这时可以用哈希表来解决问题:
存在重复的元素:
219. 存在重复元素 II - 力扣(LeetCode)https://leetcode.cn/problems/contains-duplicate-ii/description/
和上一题的思路类似,我们需要记录数字上一次出现的下标,我们可以用 unordered_map 。我们定义一个 unordered_map ,名为 _prev,在 _prev 中,键值对的 key value 存的是数字,mapped value 存的是该数字上次出现的下标。
我们遍历数组,如果当前遍历的数字 key 是第一次出现,则把该数字和下标存在 _prev 中,如果不是第一次出现,我们根据 _prev[ key ] ,就可以找到 key 上次出现的下标,从而计算距离是否小于 k,如果大于 k,则更新 _prev[ key ] 的值(为什么需要更新呢?由于数组时按顺序连续存储的,一个数字第 n 次和第 n+2 次出现时的距离,肯定大于第 n+1次 和第 n+2 次的距离,更新下标才能保证准确计算),如果小于 k ,直接返回 true 。当数组遍历完,但没有满足要求的距离时,返回 false。
for(size_t i=0;i<nums.size();i++);
for(int i=0;i<nums.size();i++)
注意这两句代码的区别,这里的 for 循环不写为size_t,最好写为int,否则 _first[nums[i] 为 int 类型,i为 size_t 类型,类型不相同,相减的差可能为 int ,也可能为 size_t ,这样会导致 error: call to 'abs' is ambiguous,即abs有很多重载,会重载为 int 型或者 size_t 型,此时的abs不知道要用哪一个重载类型。
class Solution {
public:
bool containsNearbyDuplicate(vector<int>& nums, int k) {
unordered_map<int,int> _prev;//记录数字第一次出现时的下标
for(int i=0;i<nums.size();i++)
{
if(_prev.find(nums[i])==_prev.end())
{
//该数字第一次出现
_prev.insert(pair(nums[i],i));
}
else
{
//该数字不是第一次出现
//距离小于等于K
if(abs(_prev[nums[i]]-i)<=k)
{
return true;
}
else{
_prev[nums[i]]=i;//距离大于k,更新为本次出现的下标
}
}
}
return false;
}
};