力扣-多数元素+CCF认证考试模拟练习两题

题目一

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

解题思路

按照题目中的计算公式即可,注意如果有负数,注意把负数变成0.

代码

//202012-1	期末预测之安全指数

#include <iostream>
#include <algorithm>
using namespace std;


int ans = 0;
int n = 0;

int main()
{
	cin >> n;
	for (int i = 0; i < n; i++) {
		int w_i = 0, score_i = 0;
		scanf("%d %d", &w_i, &score_i);
		ans += w_i * score_i;
	}
	printf("%d", max(0, ans));
	return 0;
}

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

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

时间复杂度:O(N)
空间复杂度:O(1)

题目二:

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

在这里插入图片描述

解题思路

1、重复元素不进行判断

通过观察发现,相同元素不管在哪里,判断结果一致,所以说需要元素判重,利用unordered_set,如果出现过了,就跳过判断,可以加速。

2、利用排序将判断简化

如果是乱序的,那么按照题意,前面后面的y值都可能大于当前y,都可能小于当前y,那么没有任何规律可言了,所以不行,必须对数据进行整理归纳,当选中了一个点,比它小的要找result=0,反之找result=1,明显分大小讨论,所以对数据进行排序处理,方便统计。

3、利用前缀和加速判断

先明确,result只能在0和1之间选择。一个区间的和是3,就代表着有三个1。再者,我们只需要知道选中点(包括他自己)的右面有多少个1,左面(不包括他自己)有多少个0,所以再根据result的取值,所以完全可以通过左右侧区间的区间和,来看有多少个1,进而求出判断正确点的个数,那么求区间和,用前缀和在O(1)的时间复杂度内完成。

在这里插入图片描述

代码

//202012-2	期末预测之最佳阈值

#include <iostream>
#include <algorithm>
#include <unordered_set>
using namespace std;


struct record {
	int y;
	int result;
	bool operator < (const record & r ) const {//用于sort函数进行排序
		return y < r.y;//表示只比较y
	}
};
record rd[100002];//记录各个数据
int  m = 0;//记录总数
int ans = 0;
int cnt_right = 0;//判断

int main()
{
	cin >> m;
	for (int i = 1; i <= m; i++) {
		scanf("%d %d", &rd[i].y, &rd[i].result);
	}
	sort(rd + 1, rd + m + 1);//对输入进来的数据按照y排序
	for (int i = 1; i <= m; i++) {
		rd[i].result += rd[i - 1].result;//对于result重整,前缀和
	}
	unordered_set<int> uds;//用于防止判断重复元素
	int tmp_right = 0;//记录某个点它预测准确的个数
	for (int i = 1; i <= m; i++) {
		if (uds.count(rd[i].y)) {//如果该点已经判断过了,跳过
			continue;
		}
		else {
			uds.insert(rd[i].y);//没判断过加入集合
		}
		tmp_right = i - 1 + rd[0].result + rd[m].result - 2 * rd[i - 1].result;//用前缀和找判断正确的个数
		if (tmp_right > cnt_right) {//更新答案
			ans = rd[i].y;
			cnt_right = tmp_right;
		}
		else if (tmp_right == cnt_right) {
			ans = max(ans, rd[i].y);//判断次数相等,取二者中较大者
		}
	}
	cout << ans;
	return 0;
}

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

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

在这里插入图片描述

时间复杂度:O(N)

题目三

在这里插入图片描述

思路:

一:用unordered_map

判断到一个数字,没出现过,则加入map并且出现次数为1,出现过了,次数++,并且判断是否满足题意,动态判断,加速,但是注意,如果一直没找到答案,但是题目中说了一定有答案,那么就说明一直计算到了最后,所以答案是最后一个元素。

二:排序规整化

1、数据零散着存放,很难找到规律,所以拿到一个混乱的数据的时候,一定要先排序规整化,再找规律!!!!!!!!!!!!!!!!
2、经过规整化,数据排好序并且相同数据在一块,根据题意一定存在众数,那么就一定存在一种数,再根据他的数量,无论他在哪,在数组中间是一定能看到她的,所以得解

三:摩尔投票

假设数组中每个不同的数字就代表一个国家,而数字的个数就代表这个国家的人数,他们在一起混战,就是每两个两个同归于尽。我们就可以知道那个人数大于数组长度一半的肯定会获胜。就算退一万步来说,其他的所有人都来攻击这个人数最多的国家,他们每两个两个同归于尽,最终剩下的也是那个众数。

代码:

注意:在map中添加元素方法,要item.insert(pair<int,int>(nums[i], 1));

class Solution {
public:
	int majorityElement(vector<int>& nums) {
		int ans = 0;
		int n = nums.size();
		unordered_map<int, int> item;//键:nums中的元素   值:出现次数
		int i = 0;
		for (; i < n; i++) {
			if (!item.count(nums[i])) {
				item.insert(pair<int, int>(nums[i], 1));//一定注意这里给map添加元素时候的语法
			}
			else {
				item.at(nums[i])++;//at方法和数组的[]一致
				if (item.at(nums[i]) > n / 2) {
					return nums[i];
				}
			}
		}
		return nums[i - 1];
	}
};

时间复杂度:O(N)
空间复杂度:O(N)

class Solution {
public:
	int majorityElement(vector<int>& nums) {
		int n = nums.size();
		sort(nums.begin(), nums.end());
		return nums[n / 2];
	}
};

时间复杂度:O(N)
空间复杂度:O(1)

class Solution {
public:
	int majorityElement(vector<int>& nums) {
		int major = nums[0];//我国士兵
		int cnt = 1;//士兵数量
		for (int i = 1; i < nums.size(); i++) {
			if (nums[i] == major) {//同国士兵,数量++
				cnt++;
			}
			else {
				if (cnt != 0) {//碰到别国士兵,一换一
					cnt--;
				}
				else {
					cnt = 1;//我国士兵没了,就把下一个国家士兵当成我国
					major = nums[i];
				}
			}
		}
		return major;
	}
};

时间复杂度:O(N)
空间复杂度:O(1)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JLU_LYM

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值