标签搜索

目 录CONTENT

文章目录

字节跳动---特征提取.md

小小城
2022-05-02 / 0 评论 / 0 点赞 / 11 阅读 / 2,596 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-05-02,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

特征提取.md
date: 2021-08-22 12:11:39.91
updated: 2021-08-22 12:11:39.91
url: /2021/08/22/字节跳动---特征提取md
categories:
tags:

字节跳动---特征提取

@[toc]

一、题目描述

小明是一名算法工程师,同时也是一名铲屎官。某天,他突发奇想,想从猫咪的视频里挖掘一些猫咪的运动信息。为了提取运动信息,他需要从视频的每一帧提取“猫咪特征”。一个猫咪特征是一个两维的vector<x, y>。如果x_1=x_2 and y_1=y_2,那么这俩是同一个特征。

因此,如果喵咪特征连续一致,可以认为喵咪在运动。也就是说,如果特征<a, b>在持续帧里出现,那么它将构成特征运动。比如,特征<a, b>在第2/3/4/7/8帧出现,那么该特征将形成两个特征运动2-3-4 和7-8

现在,给定每一帧的特征,特征的数量可能不一样。小明期望能找到最长的特征运动

输入描述:

第一行包含一个正整数N,代表测试用例的个数。

每个测试用例的第一行包含一个正整数M,代表视频的帧数。

接下来的M行,每行代表一帧。其中,第一个数字是该帧的特征个数,接下来的数字是在特征的取值;比如样例输入第三行里,2代表该帧有两个猫咪特征,<1,1>和<2,2>
所有用例的输入特征总数和<100000

N满足1≤N≤100000,M满足1≤M≤10000,一帧的特征个数满足 ≤ 10000。
特征取值均为非负整数。

输出描述:

对每一个测试用例,输出特征运动的最大长度作为一行

输入例子1:

1
8
2 1 1 2 2
2 1 1 1 4
2 1 1 2 2
2 2 2 1 4
0
0
1 1 1
1 1 1

输出例子1:

3

例子说明1:

特征<1,1>在连续的帧中连续出现3次,相比其他特征连续出现的次数大,所以输出3

二、分析

  •  这道题不难,如果你去暴力遍历肯定会超时。所以需要选取合适的数据结构快速处理数据
  •  特征<a, b>是一个键值对的形式,所以需要有一个pair<int,int>的键值对数据结构
  •  你需要存储每个键值对的出现次数信息,所以你还需要一个map/unordered_map

三、代码

方法一:

#include <iostream>
#include <vector>
#include <map>
using namespace std;
 
int main()
{
	//代表用例的个数
    int n;
    cin >> n;
 
    pair<int, int> xy;
 
    while (n--)
    {
    	//代表行数
    	int m;
        cin >> m;
 
 		//保存结果
        int count = 0;
        
        //存储上一行键值对出现的次数信息
        map<pair<int, int>, int> preFeaTimes;
        
        //存储本行键值对在上一行的基础上出现的次数信息
        map<pair<int, int>, int> feaTimes;
        
        while (m--)
        {
        	//代表每行键值对的个数
        	int len;
            cin >> len;
            for (int i = 0; i < len; i++)
            {
                cin >> xy.first >> xy.second;
                
                //判断如果本次输入的键值对在上一行出现过,那么该键值对的次数
                //等于上一行中记录的出现次数+1
                if (preFeaTimes.count(xy))
                    feaTimes[xy] = preFeaTimes[xy] + 1;
                else
                //如果该键值对没有出现过或者没在上一行出现过,说明该键值对
                //要么根本没出现过要么中间断了,所以重新置为1
                    feaTimes[xy] = 1;
 
                count = max(count,feaTimes[xy]);
               
            }
            //注意注意⚠️⚠️,这里的清空和交换非常重要
            //正式因为有这两个操作才完成每次记录的都是本行和上一行键值对出现的信息
            //清理:是因为本行已经遍历完了,键值对的更新信息已经保存在feaTimes中了
            preFeaTimes.clear();
            //swap:是因为要继续判断下一行的键值对信息,下一行是依赖本行的
            preFeaTimes.swap(feaTimes);
            //总结:就是通过这两个操作完成判读最长连续出现的键值对
        }
        cout << count << endl;
    }
 
    return 0;
}

方法二:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<bits/stdc++.h>
using namespace std;

map< pair<int,int>, set<int> > m1;

int main()
{
    int n;
    cin>>n;
    while(n--)
    {
    	int m;
        cin>>m;
        int maxn = 0,now = 0;
        int k;
        int x,y;
        for(int i = 0;i < m;i++)
        {
            cin>>k;
            for(int j = 0;j < k;j++)
            {
                cin>>x>>y;
                m1[make_pair(x,y)].insert(i);
            }
        }
        for(map <pair<int,int>, set<int> >::iterator it = m1.begin();it != m1.end();it++)
        {
            int num = 0;
            int sum = 1;
            set<int>::iterator itt = it->second.begin();
            num = *itt;
            itt++;
            for(;itt != it->second.end();itt++)
            {
                if(*itt == num+1)
                {
                    sum++;
                    num = *itt;
                }
                else 
                {
                    num =* itt;
                    maxn = max(maxn,sum);
                    sum = 1;
                }
            }
            if(itt == it->second.end()) 
                maxn = max(maxn,sum);
        }
        cout<<max(maxn,now)<<endl;
    }
    return 0;
}


0

评论区