Map 笔记

在c++中很多种映射。

unordered_map  和 map  以及 multimap  、 hash_map。其中unordered_map 是用 hash 完成的,map和multimap 是用 红黑树完成的。

unorder_map 可以在O(1) 找到查找的值,map 需要O(log(n))。

可是map 是有序的,找最小值,最大值等等时间复杂度为O(log(n))  ,而unorder_map 需要O(n)。

mulitmap 的键可以重复,map 的键不能重复。

 

map的所有操作

     begin()         返回指向map头部的迭代器

     clear()        删除所有元素

     count()         返回指定元素出现的次数

     empty()         如果map为空则返回true

     end()           返回指向map末尾的迭代器

     equal_range()   返回特殊条目的迭代器对

     erase()         删除一个元素

     find()          查找一个元素

     get_allocator() 返回map的配置器

     insert()        插入元素

     key_comp()      返回比较元素key的函数

     lower_bound()   返回键值>=给定元素的第一个位置

     max_size()      返回可以容纳的最大元素个数

     rbegin()        返回一个指向map尾部的逆向迭代器

     rend()          返回一个指向map头部的逆向迭代器

     size()          返回map中元素的个数

     swap()           交换两个map

     upper_bound()    返回键值>给定元素的第一个位置

     value_comp()     返回比较元素value的函数

int main()
{
	map<int, int> test;
	test[1]++;
	test[1]++;
	test[2] += 10;
	cout << test.count(10) << endl; //找map 中有没有键值为10的
	auto result = test.find(10) != test.end() ? 1 : 0; //和用count() 效果一样
	cout << result << endl;

	auto r2 = test.lower_bound(1); //返回键值>=给定元素的第一个位置
	cout << r2->first << " " << r2->second << endl;//1 2
	r2 = test.upper_bound(1);  //返回键值>给定元素的第一个位置
	cout << r2->first << " " << r2->second << endl;//2 10

	auto r3 = test.equal_range(1); //equal_range会返回一个pair,first是一个迭代器,指向匹配的第一个元素,second指向后一个。
	cout << r3.first->first << " " << r3.first->second << endl; //1 2

	cout << test.size() << endl;
	return 0;
}

 

 

大楼轮廓 LintCode131

题目:

输入:
[
    [1, 3, 3],
    [2, 4, 4],
    [5, 6, 1]
]
输出:
[
    [1, 2, 3],
    [2, 4, 4],
    [5, 6, 1]
]
说明:
建筑物如下图所示,黄色部分表示建筑物

图片

题解:

建两个map。curHeightMap和memoOutlineMap。

curHeightMap 记录当前位置上所有建筑的高度。

memoOutlineMap 记录每个“建筑边界”的最大高度。

class Solution {
public:
	struct Node{
		bool isUp;
		int position;
		int height;
		Node(bool a = 0, int b = 0, int c = 0){
			isUp = a;
			position = b;
			height = c;
		}//Node

		bool operator < (const Node& s2)const{
			if (position != s2.position){
				return position < s2.position;
			}//if
			else if(isUp != s2.isUp){
				return isUp == false ? true : false;
			}//else if 
			else if (isUp == s2.isUp){
				return true;
			}
		}
	};

	vector<vector<int>> buildingOutline(vector<vector<int>> &buildings) {
		static Node nodes[1000000];
		int buildingsLen = buildings.size();
		for (int i = 0; i < buildingsLen; i++){
			nodes[i * 2] = Node(true, buildings[i][0], buildings[i][2]);
			nodes[i * 2 + 1] = Node(false, buildings[i][1], buildings[i][2]); //building end position
		}//for
		sort(nodes, nodes + buildingsLen * 2);

		map<int, int> curHeightMap, memoOutlineMap;
		buildingsLen *= 2;
		for (int i = 0; i < buildingsLen; i++){
			if (nodes[i].isUp){
				curHeightMap[nodes[i].height]++;
			}//if (nodes[i].isUp)
			else{ // nodes[i].isDown
				if (curHeightMap[nodes[i].height] == 1){
					curHeightMap.erase(nodes[i].height);
				}//inner if
				else{
					curHeightMap[nodes[i].height]--;
				}
			}//extren else

			if (curHeightMap.empty()){// 如果当前的htMap清空了,那么当前位置的最大高度置为0
				memoOutlineMap[nodes[i].position] = 0;
			}//if
			else{
				memoOutlineMap[nodes[i].position] = curHeightMap.rbegin()->first;
				//cout << curHeightMap.rbegin()->first << endl;
			}
		}//for
		
		vector<vector<int>> result;
		int start = 0;
		int height = 0;
		int curMaxHeight;
		vector<int> newRecord;

		for (auto temp : memoOutlineMap){
			curMaxHeight = temp.second;
			if (height != curMaxHeight){ //在temp.second 这点高度发生变化
				if (height != 0){ // 需要记录Outline
					newRecord.clear();
					newRecord.push_back(start);
					newRecord.push_back(temp.first);
					newRecord.push_back(height);
					result.push_back(newRecord);
				}//inner for
				start = temp.first;
				height = curMaxHeight;
			}//if
		}//for
		return result;
	}
};

int main()
{
	vector<vector<int>> data,r;
	data.push_back({ 1, 3, 3 });
	data.push_back({ 2, 4, 4 });
	data.push_back({ 5, 6, 1 });
	Solution s;
	r = s.buildingOutline(data);

	return 0;
}

 

LongestSumSubArrayLength

题意:给你一个数字num , 和一个数组Array 。 要你找出一个子数组,它的和为 num , 同时长度要最大。

例子:

arr = {7,3,2,1,1,7,7,7} num = 7

其中有很多的子数组累加和等于7,但是最长的子数组是{3,2,1,1},所

以返回其长度4

 

题解:用前缀和 和 map 。map 的键为一个数t,值为前缀和t为最小下标。我们找当前的前缀和sum -  map[k] == num 。 k 为 sum - num 的值。 而map 又是映射, 找到键为 sum - num 的 值,即为下标。

int maxLength(int arr[], int len,int k)
{
	if (len == 0){
		return 0;
	}
	map<int, int> HashMap;
	HashMap[0] = -1;// 前缀和为0 时,下标为 -1
	int maxL = 0, sum = 0;
	for (int i = 0; i < len; i++){
		sum += arr[i];
		if (HashMap.count(sum - k) == 1){  //HashMap contain (sum - k) in key
			maxL = max(maxL, i - HashMap[sum - k]);
		}//if
		if (HashMap.count(sum) == 0){ //HashMap not contain (sum) in key
			HashMap[sum] = i;
		}
	}//for
	return maxL;
}

void generateArray(int Arr[], int len)
{
	srand(time(0));
	for (int i = 0; i < len; i++){
		Arr[i] = (int)rand() % 10 - (int)rand() % 10;
	}
}


int main()
{
	int arr[1000];
	generateArray(arr,5);
	for (int i = 0; i < 5; i++){
		cout << arr[i] << " ";
	}
	cout << endl;

	cout << maxLength(arr,5,5) << endl;
	return 0;
}

找一个数组中 ,子数组中奇数和偶数 的数量相等,也是这题的一个变形。

 

Most_EOR

定义数组的异或和的概念:(相同为假,相异为真是异或)

数组中所有的数异或起来,得到的结果叫做数组的异或和,

比如数组{3,2,1}的异或和是,3^2^1 = 0

给定一个数组arr,你可以任意把arr分成很多不相容的子数组,你的目的是:

分出来的子数组中,异或和为0的子数组最多。

请返回:分出来的子数组中,异或和为0的子数组最多是多少?

 

题解:

异或有交换律和结合律。我们用任何数 ^ 0  等于 该数本身, 这个性质找异或和为 0 的划分。

用 map 加 dp ,map 记录了所有前缀异或和 对应的下标。dp 记录 下标为i 时,最多划分数。

如果当前i 的前缀异或和 等于  0 - i 中其中一个j前缀异或和 ,用 任何数 ^ 0  等于 该数本身  这个性质,可以得到,j + 1 到 i 的异或和一定为 0  , 可以得到 dp[i] = dp[j] + 1。

这里我们用了对拍。

对拍函数用的是dp 。如果:

if ((eors[i] ^ eors[j]) == 0)

也说明了 i 的 前缀异或和 等于 j 的异或和的 。因为两个相等的数异或等于 0 。

 

#pragma GCC optimize(3,"Ofast","inline")
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<vector>
#include<cstring>
#include<queue>
#include<stack>
#include<list>
#include<map>
#include<set>
#include<cmath>
#include<sstream>
#include<cstdlib>
#include<bitset>
#include<climits>
#include<functional>
#include<unordered_set>
#include<unordered_map>
#include<time.h>
#define F(i,s,t) for(int i=(s);i<=(t);i++)
#define D(i,s,t) for(int i=(s);i>=(t);i--)
#define dBug(i) printf("Value=%d\n",i)
#define ddBug(i,j) printf("Value=%d %d\n",i,j)
#define ed putchar('\n')
#define FO freopen("D:\\in.txt","r",stdin)
#define IOS cin.tie(0) ,cout.tie(0), cout.sync_with_stdio(0)
typedef long long ll;
//const int INF = 1 << 30;
//const double EPS = 1e-6;
//#define MX 102
//#define Mod 10000
using namespace std;

int maxEOR(int arr[], int len)
{
	int ans = 0, xor = 0, pre;
	int dp[1000] = { 0 };
	map<int, int> HashMap;
	HashMap[0] = -1;

	for (int i = 0; i < len; i++){
		xor ^= arr[i];
		if (HashMap.count(xor) == 1){
			pre = HashMap[xor];
			dp[i] = pre == -1 ? 1 : (dp[pre] + 1);
		}//if
		if (i > 0){
			dp[i] = max(dp[i], dp[i - 1]);
		}//if
		HashMap[xor] = i;
		ans = max(ans, dp[i]);
	}//for
	return ans;
}

int comparatot(int arr[], int len)
{
	if (len == 0){
		return 0;
	}
	int eors[1000]; // 表示第i位的异或和
	int eor = 0;
	for (int i = 0; i < len; i++){
		eor ^= arr[i];
		eors[i] = eor;
	}//for

	int dp[1000]; // dp[i] 表示 第i 位的答案
	dp[0] = arr[0] == 0 ? 1 : 0;
	for (int i = 1; i < len; i++){
		dp[i] = eors[i] == 0 ? 1 : 0;
		for (int j = 0; j < i; j++){
			if ((eors[i] ^ eors[j]) == 0){ //note : 位运算的优先级
				/*cout << eors[i] << endl;
				cout << eors[j] << endl;
				int temp = eors[i] ^ eors[j];
				cout << temp << endl;*/
				dp[i] = max(dp[i], dp[j] + 1);
			}//if
		}//for
		dp[i] = max(dp[i], dp[i - 1]);
	}//for
	return dp[len - 1];
}

void generateArray(int Arr[], int len, int maxValue)
{
	srand(time(0));
	for (int i = 0; i < len; i++){
		Arr[i] = (int)rand() % maxValue;
	}
}

void printArray(int arr[], int len)
{
	if (len == 0){
		return;
	}
	for (int i = 0; i < len; i++){
		cout << arr[i] << " ";
	}
	cout << endl;
}

int main()
{
	int testTime = 5000;
	int maxSize = 5;
	int maxValue = 30;
	int arr[1000];
	bool succeed = true;
	int res, comp;


	for (int i = 0; i < testTime; i++){
		generateArray(arr, maxSize, maxValue);
		res = maxEOR(arr, maxSize);
		comp = comparatot(arr, maxSize);
		if (res != comp){
			succeed = false;
			printArray(arr, maxSize);
			cout << res << endl;
			cout << comp << endl;
			break;
		}//if
		//cout << i << endl;
	}//for
	if (succeed){
		cout << "Nice" << endl;
	}
	else{
		cout << "Fucking" << endl;
	}

	return 0;
}

LeetCode187. 重复的DNA序列

所有 DNA 都由一系列缩写为 A,C,G 和 T 的核苷酸组成,例如:“ACGAATTCCG”。在研究 DNA 时,识别 DNA 中的重复序列有时会对研究非常有帮助。

编写一个函数来查找目标子串,目标子串的长度为 10,且在 DNA 字符串 s 中出现次数超过一次。

示例:

输入:s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"
输出:["AAAAACCCCC", "CCCCCAAAAA"]

题解:

双指针,和 map 。

遍历所有的长度为 10的子串,用 map 的 key 来存出现的字串,value 来存出现的次数。

class Solution {
public:
	vector<string> findRepeatedDnaSequences(string s) {
		string subDNA;
		vector<string> sameDNACollect;
		map<string, int> allSubDNA;
		int time = s.length() - 10 + 1;

		for (int i = 0; i < time; i++){
			subDNA = s.substr(i,10);
			if (allSubDNA.count(subDNA) == 0){
				allSubDNA[subDNA] = 1;
			}//if
			else if(allSubDNA[subDNA] == 1){
				sameDNACollect.push_back(subDNA);
				allSubDNA[subDNA]++;
			}
			else{
				allSubDNA[subDNA]++;
			}
		}//for
		return sameDNACollect;
	}
};

LeetCode219. 存在重复元素 II

给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k。

示例 1:

输入: nums = [1,2,3,1], k = 3
输出: true

题解:

用map,map的key 存 nums里面的数,map 的 value 存 最近一次出现在第几位。

class Solution {
public:
	bool containsNearbyDuplicate(vector<int>& nums, int k) {
		map<int, int> numIndex;
		int len = nums.size();
		for (int i = 0; i < len; i++){
			if (numIndex.count(nums[i]) == 1){
				if (i - numIndex[nums[i]] <= k){
					return true;
				}
				else{
					numIndex[nums[i]] = i;
				}//else
			}//extren if
			else{
				numIndex[nums[i]] = i;
			}
		}//for
		return false;
	}
};

 

 

参考博客:https://blog.csdn.net/sevenjoin/article/details/81943864

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值