力扣2007+力扣2012+力扣2006+力扣2011(259场周赛+61场双周赛前两题)

第六十八天 --- 力扣2007+力扣2012+力扣2006+力扣2011

题目一

在这里插入图片描述
在这里插入图片描述

思路

1、先读好题,把每个元素都乘以二,再把结果加入数组,则新的混合数组元素个数必是偶数个。
2、拿1和2举例子,在读入2的时候,需要快速知道1在不在数组里面,因为数据量极为庞大,且两个数可能相距很远,所以最快速的做法就是hash表。但是可能出现重复元素,所以要用unordered_map,key值是数组元素,value是出现次数。出现无法配对的元素先放在map里面,当出现次数归零,说明完全被匹配完了,所以该把它从map里删除。
3、这里我们拿1,3,4,2,6,8如果保持数组乱序,那么,小的数可能出现在数组后面,大的数在前面,更大的数在最前面,这样一定会产生匹配混乱的情况。每个数和乘二后的数按照递增顺序排列,每一个数对都按照这个顺序排列,最后把所有数对放在一起递增排列,比如1,2,3,4,6,8这样,就会发现,答案数组里的元素,一定会出现在其乘二后的元素之前,这样就不会产生错误匹配了,原来的元素和乘二的元素相对位置一前一后固定了,不会匹配出错的

代码

注:其实题目中特意强调随机打乱,说明数组中的数无规律了,这样尤其在匹配的时候最容易出错,相对位置不固定,所以最常见的方法就是排序重整数组,让相对位置固定就好了

class Solution {
    
    
public:
	vector<int> findOriginalArray(vector<int>& changed) {
    
    
		vector<int> ans;
		unordered_map<int, int> mapper;
		if (changed.size() % 2 != 0) {
    
    //快速判断特殊情况
			return ans;
		}
		sort(changed.begin(), changed.end());//排序,固定相对位置
		for (int i = 0; i < changed.size(); i++) {
    
    
			if (changed[i] % 2 != 0) {
    
    //奇数元素一定是目标,所以直接加入
				if (mapper.count(changed[i]) == 0) {
    
    //第一次加入
					mapper.insert(pair<int, int>(changed[i], 1));
				}
				else {
    
    
					mapper[changed[i]]++;//多次加入
				}
			}
			else {
    
    
				int item = changed[i] / 2;//偶数元素要判断他是不是乘二元素,不是的话直接加入,因为他的乘二元素一定在后面
				if (mapper.count(item) > 0) {
    
    
					ans.push_back(item);
					mapper[item]--;
					if (mapper[item] == 0) {
    
    //答案元素被匹配光了,删除
						mapper.erase(item);
					}
				}
				else {
    
    //加入,原理同上
					if (mapper.count(changed[i]) == 0) {
    
    
						mapper.insert(pair<int, int>(changed[i], 1));
					}
					else {
    
    
						mapper[changed[i]]++;
					}
				}
			}
		}
		if (mapper.size() > 0) {
    
    //如果map里有剩余元素,说明一定未完全匹配,为错
			vector<int> tmp;
			return tmp;
		}
		return ans;
	}
};

(所有代码均已在力扣上运行无误)

经测试,该代码运行情况是(经过多次测试所得最短时间):
在这里插入图片描述

题目二:

在这里插入图片描述
在这里插入图片描述

思路

1、针对1到n-2这个范围中的每个元素,他的左面都小于他,右面都大于他,那么我们就记录一下他左面最大的人是谁,右面最小的的人是谁,它大于左面最大的,小于右面最小的,就满足了第一条,第二条略。
2、其实面对大数据量,很明显能想得到的就是hash表,其次在发现一个数组数据很乱很没有找规律的头绪的时候,可以尝试排序重整数组,让数组变得有序,或者前缀和,前缀最大,后缀最小等等技巧,多试一试,总有一个方法会弄出来的

代码

class Solution {
    
    
public:
	int sumOfBeauties(vector<int>& nums) {
    
    
		int ans = 0;
		int max[100005];
		int min[100005];
		int n = nums.size();
		max[0] = nums[0];
		min[n - 1] = nums[n - 1];
		for (int i = 1; i < n; i++) {
    
    
			max[i] = nums[i] > max[i - 1] ? nums[i] : max[i - 1];//求前缀最大
		}
		for (int i = n - 2; i >= 0; i--) {
    
    
			min[i] = nums[i] < min[i + 1] ? nums[i] : min[i + 1];//求后缀最小
		}
		for (int i = 1; i < n - 1; i++) {
    
    //保证了每个元素在O(1)的复杂度内完成计算
			if (nums[i] > max[i - 1] && nums[i] < min[i + 1]) {
    
    
				ans += 2;
				continue;
			}
			else if (nums[i - 1] < nums[i] && nums[i] < nums[i + 1]) {
    
    
				ans += 1;
				continue;
			}
		}
		return ans;
	}
};

(所有代码均已在力扣上运行无误)

经测试,该代码运行情况是(经过多次测试所得最短时间):

在这里插入图片描述
时间复杂度O(N)
空间复杂度O(N)

题目三

在这里插入图片描述

思路

直接模拟

代码

class Solution {
    
    
public:
	int countKDifference(vector<int>& nums, int k) {
    
    
		int ans = 0;
		for (int i = 0; i < nums.size(); i++) {
    
    
			for (int j = i + 1; j < nums.size(); j++) {
    
    
				if (abs(nums[i] - nums[j]) == k) {
    
    
					ans++;
				}
			}
		}
		return ans;
	}
};

(所有代码均已在力扣上运行无误)

经测试,该代码运行情况是(经过多次测试所得最短时间):
在这里插入图片描述

时间复杂度O(N^2)

题目四

在这里插入图片描述

思路

计算带+和-的数目,相减就行

代码

class Solution {
    
    
public:
	int finalValueAfterOperations(vector<string>& operations) {
    
    
		int add = 0;
		int sub = 0;
		for (int i = 0; i < operations.size(); i++) {
    
    
			for (int j = 0; j < 3; j++) {
    
    //vector里面一个元素三个字符,检测+-
				if (operations[i][j] == '-') {
    
    
					sub++;
					break;
				}
				else if (operations[i][j] == '+') {
    
    
					add++;
					break;
				}
				else {
    
    
					continue;
				}
			}
		}
		return add - sub;

	}
};

(所有代码均已在力扣上运行无误)

经测试,该代码运行情况是(经过多次测试所得最短时间):
在这里插入图片描述

时间复杂度O(N)

猜你喜欢

转载自blog.csdn.net/qq_45678698/article/details/120421419