给你一个正整数数组 arr ,请你计算所有可能的奇数长度子数组的和。
子数组 定义为原数组中的一个连续子序列。
请你返回 arr 中 所有奇数长度子数组的和 。
int sumOddLengthSubarrays(vector<int>& arr) {
int res = 0;
for(int i = 0; i < arr.size(); i ++){
int left = i + 1, right = arr.size() - i,
left_even = (left + 1) / 2, right_even = (right + 1) / 2,
left_odd = left / 2, right_odd = right / 2;
res += (left_even * right_even + left_odd * right_odd) * arr[i];
}
return res;
}
非常神奇,虽然我也知道不需要直接去统计每个序列的和,再求和,应该直接去计算元素出现的次数。但是始终没找到合适的算法公式来实现。
很简单的想法,把数组分成两个部分,前部分0~i-1,后部分i+1到最后。既然是奇数和,那前部分出现的序列长度的奇偶性跟后部分的奇偶性应该一样,这样(奇+奇)+1或者(偶+偶)+1的长度才是奇数,这样就统计了i出现的总的次数,一次遍历,求和,搞定,妙啊。
数组中占比超过一半的元素称之为主要元素。给定一个整数数组,找到它的主要元素。若没有,返回-1。
你有办法在时间复杂度为 O(N),空间复杂度为 O(1) 内完成吗?
想用排序的办法去解决的闷逼了吧,排序最快的也要nlogn,空间复杂度也有限制O(1),意味着你别想用字典来计数,哈哈。。
摩尔投票法:
int majorityElement(vector<int>& nums) {
if (nums.size() == 0) return -1;
if (nums.size() == 1) return nums[0];
int count = 0, num = -1;
for (int c : nums) {
//投票清零,统计新牛郎
if (count == 0) {
num = c;
count++;
}else {
//“我”得一票
if (c == num) count++;
//我以外得一票(我减一票)
else count--;
}
}
count = 0;
for (int c : nums) {
if (c == num){
count++;
}
}
return count < nums.size()/2+1 ? -1 : num;
}
话说世界上只有两种人,候选人摩尔跟其他人,只有摩尔超过半数才能得选。
摩尔得一票则加1,别人得一票则摩尔的票减1,如果摩尔的最终票数>0,则摩尔当选。注意问题是我并不知道摩尔是谁?
得票候选人数组里面去猜?如果默认票数为0,那就假定这个人是摩尔。如果票数归0了,意味着摩尔需要换人了,也可能是同一个人(得票数组有重复候选人,意味着得票多张)。
最终得到的摩尔是不是一定就超过半数呢?
不一定!
需要再统计一次,哈哈,第一次遍历只能证明,假如有人超过半数那一定是摩尔,但是不保证。
再次计数就能得出摩尔的真正票数。