OJ || 求数组中特定元素之间的距离

目录

数组中两个字符串的最小距离:

存在重复的元素:


数组中两个字符串的最小距离:

数组中两个字符串的最小距离__牛客网 (nowcoder.com)icon-default.png?t=N7T8https://www.nowcoder.com/questionTerminal/2c6a0a8e1d20492f92941400036e0890

 本题是求两个字符串之间的最小距离,可以理解为求 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)icon-default.png?t=N7T8https://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;
    }
};

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值