题目
解题思路
此题可以通过排序+倒序遍历处理。
根据题意,一个角色是弱角色的充要条件是存在一个其他角色的攻击力和防御力都严格高于本角色。存在一个即可。那么我们不妨对数组按攻击力从小到大排序,之后对数组倒序遍历,并在遍历过程中实时更新最大防御力,则只要遍历到的当前角色防御力小于最大防御力,该角色就必然是弱角色。因为角色是攻击力从小到大排序的,而我们又是使用倒序的方式遍历,则已遍历过的角色攻击力一定比当前角色高,只需要有一个角色防御力严格高于当前角色,当前角色就是弱角色。
这里存在一个特殊情况,就是角色攻击力可能相同。对于攻击力相同的角色,我们将其合并为一组进行处理,先使用临时变量存储和更新组内最大防御力,而判断组内角色是否是弱角色则使用全局的当前最高防御力进行判断,待这一组处理完毕后,再更新全局当前最大防御力。这样做的理由显而易见,同组角色的攻击力完全相同,不存在严格大于关系,如果处理同组角色的过程中更新全局最高防御力使该最高防御力落在了组内角色上,就会产生误判。
于是有算法:
- 计算输入数组大小
m
,若m==1
返回0
; - 将数组排序,初始化全局最大防御力
maxDfs
为-1
,初始化弱角色数ans
为0
; - 从计数器
i=m-1
对数组进行倒序遍历:
- 若为攻击力非重复元素则直接处理,判断当前角色防御力是否严格小于
maxDfs
,是则++ans
,不是则更新maxDfs
; - 若为攻击力重复元素则分组处理,初始化角色组指针
k
为i
,组内最大防御力tempMaxDfs
为-1
,对所有攻击力与角色i
相同的组内元素进行遍历,直至攻击力不等。对每个角色,判断当前角色防御力是否严格小于maxDfs
,是则++ans
,不是则更新tempMaxDfs
。同组角色处理完毕更新maxDfs
,更新i
为k+1
;
- 所有数据处理完毕返回答案
ans
。
代码
class Solution {
public:
int numberOfWeakCharacters(vector<vector<int>>& properties) {
int m = properties.size();//计算输入数组的大小
if(m==1) return 0;//如果大小为1,直接返回0
sort(properties.begin(),properties.end());//将数组排序
int maxDfs = -1;//初始化最大防御力为-1
int ans = 0;//初始化答案为0
for(int i = m-1; i >= 0; --i){//倒序遍历
if(i >= 1 && properties[i][0] != properties[i-1][0]){//攻击力非重复元素则直接处理
if(properties[i][1]<maxDfs) ++ans;//若防御力小于当前最大防御力,则该角色为弱角色
else maxDfs = properties[i][1];//否则更新最大防御力
}
else{//攻击力重复元素按组处理
int k = i;
int tempMaxDfs = -1;//组内最大防御力,暂时不同步到maxDfs,因为组内攻击力相同,
//不存在严格小于关系,不能使用tempDfs判断是否是弱角色
while(k>=0 && properties[k][0] == properties[i][0]){
if(properties[k][1]<maxDfs) ++ans;//若防御力小于组外最大防御力,则该角色为弱角色
else tempMaxDfs = tempMaxDfs<properties[k][1] ? properties[k][1] : tempMaxDfs;//否则更新组内防御力
--k;
}
maxDfs = tempMaxDfs>maxDfs ? tempMaxDfs : maxDfs;//对比组内最大防御力和组外最大防御力,更新maxDfs
i = ++k;
}
}
return ans;//返回答案
}
};
复杂度分析
时间复杂度: O(mlogm)
。m
为角色数,排序需要O(mlogm)
,遍历需要O(m)
,总时间复杂度O(mlogm)
。
空间复杂度: O(logm)
。sort
底层大致是快排,需要O(logm)
的栈空间。