统计数组中不同元素出现的次数

这里写自定义目录标题

字节题目

有一个正整数数组A[N]每个元取值范围[1,N],统计每个元素出现次数。
要求:时间负责度O(n),空间复杂度O(1)
输入

1 3 2 5 3 1

输出

1=>2
2=>1
3=>2
5=>1

思路

常规思路是利用map进行统计,但不满足时间和空间复杂度的要求;
正确思路:
遍历数组,通过当前元素的值a作为下标,找到下一个元素。最后得到的数组中,下标(因为数组的下标都是从0开始的,所以需要+1)为数组中出现的元素,每个下标对应的值取反输出即是该元素出现的次数。

  • 若当前元素a小于0,则跳过;
  • 若当前元素a大于0,则判断其作为下标对应的元素b是否大于0。
    • b大于0,则把b的值赋值给a,并把b置为-1;
    • b小于0,则把a置为0,并把b自减1;

注意遍历时,若当前元素为正数依旧处理该当前元素;

// 举例
vector<int> arr = {2, 5, 5, 2, 3};
下标都+1;
/*
1、遍历数组,第一个arr[1]=2,然后看下标为2的元素是arr[2]=5。
2、把arr[2]对应的5赋值给arr[1],然后arr[2]就设置为-1
3、然后重复整个过程直到结束
它的整个变化过程就是这样
- {2, 5, 5, 2, 3}
- 5, [-1], 5, 2, 3
- 3, [-1], 5, 2, [-1]
- 5, [-1], [-1], 2, [-1]
- [0], [-1], [-1], 2, [-2]
- [0], [-2], [-1], [0], [-2]
这个结果表示:1有0个,2有2个,3有一个,4有0个,5有2个
*/

理解:第一个数是2,然后把arr2的值给arr1,然后arr2就为-1,表示2这个数出现了一次,以此类推。主要因为数组的范围就是1-n,所以这个方法可以遍历一次就统计出来

代码实现

#include <iostream>
#include <vector>

using namespace std;

void sort(vector<int> &num, int n) {
    int i = 0;
    while (i < n) {
        int temp = num[i] - 1;
        if (temp < 0) {
            i++;
            continue;
        }
        if (num[temp] > 0) {
            num[i] = num[temp];
            num[temp] = -1;
        } else {
            num[temp]--;
            num[i] = 0;
        }
    }
}

int main() {
    vector<int> a{2, 5, 5, 2, 3};
    sort(a, a.size());
    for (int i = 0; i < a.size(); i++) {
        if (a[i] < 0)
            cout << i + 1 << " " << (-a[i]) << endl;
    }
    return 0;
}

结果
在这里插入图片描述

参考:https://zhuanlan.zhihu.com/p/103778682

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值