<p align="center">
<a href="https://www.programmercarl.com/xunlian/xunlianying.html" target="_blank">
  <img src="../pics/训练营.png" width="1000"/>
</a>
<p align="center"><strong><a href="./qita/join.md">参与本项目</a>，贡献其他语言版本的代码，拥抱开源，让更多学习算法的小伙伴们受益！</strong></p>

# 1207.独一无二的出现次数

[力扣题目链接](https://leetcode.cn/problems/unique-number-of-occurrences/)

给你一个整数数组 arr，请你帮忙统计数组中每个数的出现次数。

如果每个数的出现次数都是独一无二的，就返回 true；否则返回 false。

示例 1：
* 输入：arr = [1,2,2,1,1,3]
* 输出：true
* 解释：在该数组中，1 出现了 3 次，2 出现了 2 次，3 只出现了 1 次。没有两个数的出现次数相同。

示例 2：
* 输入：arr = [1,2]
* 输出：false

示例 3：
* 输入：arr = [-3,0,1,-3,1,1,1,-3,10,0]
* 输出：true

提示：

* 1 <= arr.length <= 1000
* -1000 <= arr[i] <= 1000


## 思路

这道题目数组在是哈希法中的经典应用，如果对数组在哈希法中的使用还不熟悉的同学可以看这两篇：[数组在哈希法中的应用](https://programmercarl.com/0242.有效的字母异位词.html)和[哈希法：383. 赎金信](https://programmercarl.com/0383.赎金信.html)

进而可以学习一下[set在哈希法中的应用](https://programmercarl.com/0349.两个数组的交集.html)，以及[map在哈希法中的应用](https://programmercarl.com/0001.两数之和.html)

回归本题，**本题强调了-1000 <= arr[i] <= 1000**，那么就可以用数组来做哈希，arr[i]作为哈希表（数组）的下标，那么arr[i]可以是负数，怎么办？负数不能做数组下标。


**此时可以定义一个2001大小的数组，例如int count[2001];**，统计的时候，将arr[i]统一加1000，这样就可以统计arr[i]的出现频率了。

题目中要求的是是否有相同的频率出现，那么需要再定义一个哈希表（数组）用来记录频率是否重复出现过，bool fre[1001]; 定义布尔类型的就可以了，**因为题目中强调1 <= arr.length <= 1000，所以哈希表大小为1000就可以了**。

如图所示：


<img src='https://code-thinking.cdn.bcebos.com/pics/1207.独一无二的出现次数.png' width=600> </img></div>

C++代码如下：

```CPP
class Solution {
public:
    bool uniqueOccurrences(vector<int>& arr) {
        int count[2001] = {0}; // 统计数字出现的频率
        for (int i = 0; i < arr.size(); i++) {
            count[arr[i] + 1000]++;
        }
        bool fre[1001] = {false}; // 看相同频率是否重复出现
        for (int i = 0; i <= 2000; i++) {
            if (count[i]) {
                if (fre[count[i]] == false) fre[count[i]] = true;
                else return false;
            }
        }
        return true;
    }
};
```

## 其他语言版本

### Java：

```java
class Solution {
    public boolean uniqueOccurrences(int[] arr) {
        int[] count = new int[2001];
        for (int i = 0; i < arr.length; i++) {
            count[arr[i] + 1000]++; // 防止负数作为下标
        }
        boolean[] flag = new boolean[1002]; // 标记相同频率是否重复出现
        for (int i = 0; i <= 2000; i++) {
            if (count[i] > 0) {
                if (flag[count[i]] == false) {
                    flag[count[i]] = true;
                } else {
                    return false;
                }
            }
        }
        return true;
    }
}
```

### Python：

```python 
# 方法 1: 数组在哈西法的应用
class Solution:
    def uniqueOccurrences(self, arr: List[int]) -> bool:
        count = [0] * 2001
        for i in range(len(arr)):
            count[arr[i] + 1000] += 1 # 防止负数作为下标
        freq = [False] * 1001 # 标记相同频率是否重复出现
        for i in range(2001):
            if count[i] > 0:
                if freq[count[i]] == False:
                    freq[count[i]] = True
                else:
                    return False
        return True
```
```python 
# 方法 2： map 在哈西法的应用
class Solution:
    def uniqueOccurrences(self, arr: List[int]) -> bool:
        ref = dict()

        for i in range(len(arr)):
            ref[arr[i]] = ref.get(arr[i], 0) + 1

        value_list = sorted(ref.values())

        for i in range(len(value_list) - 1):
            if value_list[i + 1] == value_list[i]:
                return False 

        return True 

```

### JavaScript：

``` javascript
// 方法一：使用数组记录元素出现次数
var uniqueOccurrences = function(arr) {
    const count = new Array(2001).fill(0);// -1000 <= arr[i] <= 1000
    for(let i = 0; i < arr.length; i++){
        count[arr[i] + 1000]++;// 防止负数作为下标
    }
    // 标记相同频率是否重复出现
    const fre = new Array(1001).fill(false);// 1 <= arr.length <= 1000
    for(let i = 0; i <= 2000; i++){
        if(count[i] > 0){//有i出现过
            if(fre[count[i]] === false) fre[count[i]] = true;//之前未出现过，标记为出现
            else return false;//之前就出现了，重复出现
        }
    }
    return true;
};

// 方法二：使用Map 和 Set
/**
 * @param {number[]} arr
 * @return {boolean}
 */
var uniqueOccurrences = function(arr) {
    // 记录每个元素出现次数
    let map = new Map();
    arr.forEach( x => {
        map.set(x, (map.get(x) || 0) + 1); 
    })
    // Set() 里的元素是不重复的。如果有元素出现次数相同，则最后的set的长度不等于map的长度
    return map.size === new Set(map.values()).size
};
```

### TypeScript：

> 借用数组：

```typescript
function uniqueOccurrences(arr: number[]): boolean {
    const countArr: number[] = new Array(2001).fill(0);
    for (let i = 0, length = arr.length; i < length; i++) {
        countArr[arr[i] + 1000]++;
    }
    const flagArr: boolean[] = new Array(1001).fill(false);
    for (let count of countArr) {
        if (count === 0) continue;
        if (flagArr[count] === true) return false;
        flagArr[count] = true;
    }
    return true;
};
```

> 借用map、set

```typescript
function uniqueOccurrences(arr: number[]): boolean {
    const countMap: Map<number, number> = new Map();
    arr.forEach(val => {
        countMap.set(val, (countMap.get(val) || 0) + 1);
    })
    return countMap.size === new Set(countMap.values()).size;
};
``` 


### Go：
```Go
func uniqueOccurrences(arr []int) bool {
	count := make(map[int]int) // 统计数字出现的频率
	for _, v := range arr {
		count[v] += 1
	}
	fre := make(map[int]struct{}) // 看相同频率是否重复出现
	for _, v := range count {
		if _, ok := fre[v]; ok {
			return false
		}
		fre[v] = struct{}{}
	}
	return true
}
```

### Rust

```rust
use std::collections::{HashMap, HashSet};
impl Solution {
    pub fn unique_occurrences(arr: Vec<i32>) -> bool {
        let mut hash = HashMap::<i32, i32>::new();
        for x in arr {
            *hash.entry(x).or_insert(0) += 1;
        }
        let mut set = HashSet::<i32>::new();
        for (_k, v) in hash {
            if set.contains(&v) {
                return false
            } else {
                set.insert(v);
            }
        }
        true
    }
}
```




<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
  <img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>
