【基本数据结构】5.8任务

基本数据结构

Leetcode.1两数之和
Leetcode.187重复的DNA序列
Leetcode.706设计哈希映射
Leetcode.652寻找重复的子树
Leetcode.560和为 K 的子数组
Leetcode.547省份数量
Leetcode.684冗余连接
Leetcode.692前K个高频单词
Leetcode.295数据流的中位数
Leetcode.352将数据流变为多个不相交区间

一、Leetcode.1两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

  vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int>hash;
        for(int i=0;i<nums.size();i++){
            if(hash.count(target-nums[i]))return {hash[target-nums[i]],i};
            hash[nums[i]]=i;
        }
        return {-1,-1};
    }

二、Leetcode.187重复的DNA序列

DNA序列 由一系列核苷酸组成,缩写为 ‘A’, ‘C’, ‘G’ 和 ‘T’.。

例如,“ACGAATTCCG” 是一个 DNA序列 。
在研究 DNA 时,识别 DNA 中的重复序列非常有用。

给定一个表示 DNA序列 的字符串 s ,返回所有在 DNA 分子中出现不止一次的 长度为 10 的序列(子字符串)。你可以按 任意顺序 返回答案。

  vector<string> findRepeatedDnaSequences(string s) {
        unordered_map<string,int>hash;
        vector<string>ans;
        for(int i=0;i+9<=s.size()-1;i++){
            string str=s.substr(i,10);
            hash[str]++;
            if(hash[str]==2)ans.push_back(str);
        }
        return ans;
    }

三、Leetcode.706设计哈希映射

不使用任何内建的哈希表库设计一个哈希映射(HashMap)。

  int N=20011;
    vector<list<pair<int,int>>>h;
    MyHashMap() {
        h=vector<list<pair<int,int>>>(N);
    }
    list<pair<int,int>>::iterator find(int key){
        int t=key%N;
        for(auto it=h[t].begin();it!=h[t].end();it++){
            if(it->first==key)return it;
        }
        return h[t].end();
    }
    void put(int key, int value) {
        auto it=find(key);
        int t=key%N;
        if(it==h[t].end())h[t].push_back({key,value});
        else it->second=value;
    }
    
    int get(int key) {
        auto it=find(key);
        int t=key%N;
        if(it==h[t].end())return -1;
        else return it->second;
    }
    
    void remove(int key) {
        auto it=find(key);
        int t=key%N;
        if(it==h[t].end())return;
        else h[t].erase(it);
    }

四、Leetcode.652寻找重复的子树

给定一棵二叉树 root,返回所有重复的子树。

对于同一类的重复子树,你只需要返回其中任意一棵的根结点即可。

如果两棵树具有相同的结构和相同的结点值,则它们是重复的。

  unordered_map<string,int>h;
    vector<TreeNode*>ans;
    //1,2, , ,    
    string dfs(TreeNode*root){
        if(root==NULL)return "";
        string str="";
        str+=to_string(root->val)+",";
        str+=dfs(root->right)+",";
        str+=dfs(root->left);
        h[str]++;
        if(h[str]==2)ans.push_back(root);
        
        return str;
    }
    vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
        dfs(root);
        return ans;
    }

五、Leetcode.560和为 K 的子数组

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。

  int subarraySum(vector<int>& nums, int k) {
        unordered_map<int,int>h;
        int sum=0;
        h[0]=1;
        int ans=0;
        for(int i=0;i<nums.size();i++){
            sum+=nums[i];
            ans+=h[sum-k];
            h[sum]++;
        }
        return ans;
    }

六、Leetcode.547省份数量

有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。

省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。

给你一个 n x n 的矩阵 isConnected ,其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连,而 isConnected[i][j] = 0 表示二者不直接相连。

返回矩阵中 省份 的数量。

  vector<int>p;
    int find(int x){
        if(x!=p[x])p[x]=find(p[x]);
        return p[x];
    }
    int findCircleNum(vector<vector<int>>& isConnected) {
        int n=isConnected.size();
        p=vector<int>(n);
        for(int i=0;i<n;i++)p[i]=i;
        int ans=n;
        for(int i=0;i<n;i++){
            for(int j=0;j<i;j++){
                if(isConnected[i][j]==0)continue;
                if(find(i)!=find(j)){
                    p[find(i)]=find(j);
                    ans--;
                }
            }
        }
        return ans;
    }

七、Leetcode.684冗余连接

树可以看成是一个连通且 无环 的 无向 图。

给定往一棵 n 个节点 (节点值 1~n) 的树中添加一条边后的图。添加的边的两个顶点包含在 1 到 n 中间,且这条附加的边不属于树中已存在的边。图的信息记录于长度为 n 的二维数组 edges ,edges[i] = [ai, bi] 表示图中在 ai 和 bi 之间存在一条边。

请找出一条可以删去的边,删除后可使得剩余部分是一个有着 n 个节点的树。如果有多个答案,则返回数组 edges 中最后出现的边。

  vector<int>p;
    int find(int x){
        if(x!=p[x])p[x]=find(p[x]);
        return p[x];
    }
    vector<int> findRedundantConnection(vector<vector<int>>& edges) {
        int n=edges.size();
        p=vector<int>(n+1);
        for(int i=i;i<=n;i++)p[i]=i;
        for(auto e:edges){
            int x=e[0];
            int y=e[1];
            if(find(x)==find(y))return {x,y};
            p[find(x)]=find(y);
        }
        return {-1,-1};
    }

八、Leetcode.692前K个高频单词

给定一个单词列表 words 和一个整数 k ,返回前 k 个出现次数最多的单词。

返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率, 按字典顺序 排序。

  unordered_map<string,int>hash;
    typedef pair<int,string> PIS;
    priority_queue<PIS>heap;
    vector<string> topKFrequent(vector<string>& words, int k) {
        for(int i=0;i<words.size();i++){
            hash[words[i]]++;
        }
        for(auto item:hash){
            PIS t(-item.second,item.first);
            heap.push(t);
            //cout<<item.second<<item.first<<endl;
            if(heap.size()>k){
                //cout<<heap.top().second<<endl;
                heap.pop();
            }
        }
        vector<string>ans(k);
        for(int i=k-1;i>=0;i--){
            ans[i]=heap.top().second;
            //cout<<ans[k]
            heap.pop();
        }
        return ans;
    }

九、Leetcode.295数据流的中位数

中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。

  priority_queue<int>down;
    priority_queue<int,vector<int>,greater<int>>up;
    MedianFinder() {

    }
    
    void addNum(int num) {
        if(down.empty()||num>=down.top())up.push(num);
        else{
            down.push(num);
            up.push(down.top());
            down.pop();
        }
        if(up.size()>down.size()+1){
            down.push(up.top());
            up.pop();
        }
    }
    
    double findMedian() {
        if(down.size()+up.size()&1==1)return up.top();
        else return (down.top()+up.top())/2.0;
    }

十、Leetcode.352将数据流变为多个不相交区间

给你一个由非负整数 a1, a2, …, an 组成的数据流输入,请你将到目前为止看到的数字总结为不相交的区间列表。

实现 SummaryRanges 类:

SummaryRanges() 使用一个空数据流初始化对象。
void addNum(int val) 向数据流中加入整数 val 。
int[][] getIntervals() 以不相交区间 [starti, endi] 的列表形式返回对数据流中整数的总结。

  map<int, int> interval;
    SummaryRanges() {}
    void addNum(int val) {
        auto up = interval.upper_bound(val);
        auto down = (up == interval.begin() ? interval.end() : prev(up));

        if (down != interval.end() && (val >= down->first && val <= down->second)) {

        } else if ((up != interval.end() && up->first - 1 == val) && (down != interval.end() && down->second + 1 == val)) {
            int l = down->first, r = up->second;
            interval.erase(down->first);
            interval.erase(up->first);
            interval.emplace(l, r);
        } else if (down != interval.end() && down->second + 1 == val) {
            int l = down->first, r = val;
            interval.erase(l);
            interval.emplace(l, r);
        } else if (up != interval.end() && up->first - 1 == val) {
            int l = val, r = up->second;
            interval.erase(up->first);
            interval.emplace(l, r);
        } else {
            interval.emplace(val, val);
        }
        cout << interval.size() << endl;

    }

    vector<vector<int>> getIntervals() {
        vector<vector<int>> ans;
        for (auto& it : interval) {
            ans.push_back({it.first, it.second});
        }
        return ans;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值