欢迎关注我的 个人主页 && 个人博客 && 个人知识库 && 微信公众号“前端自习课”

本周练习内容:数据结构与算法 —— Set

这些都是数据结构与算法,一部分方法是团队其他成员实现的,一部分我自己做的,有什么其他实现方法或错误,欢迎各位大佬指点,感谢。

一、集合是什么?与它相关数学概念有哪些


解题:
1.集合定义:
集合(Set)是一种包含不同元素的数据结构。集合中的元素称为成员,集合最重要的两个特点:

  • 集合中的成员是无序;
  • 集合中不存在相同成员;

即:无序且唯一。

2.集合相关的数学概念:
集合的概念,如数学中一个由大于或等于0的整数组成的自然数集合, N = { 0, 1, 2, ...}
还有如空集,表示不包含任何元素的集合。
并且也有并集,交集,差集等操作。

二、请实现一个集合,并实现以下方法

add(value):向集合添加一个新的项。
delete(value):从集合移除一个值。
has(value):如果值在集合中,返回 true,否则返回 false。
clear():移除集合中的所有项。
size():返回集合所包含元素的数量。与数组的 length 属性类似。
values():返回一个包含集合中所有值的数组。


解题:

  1. class Sets {
  2. constructor(){
  3. this.items = {}
  4. }
  5. has(value){
  6. // return value in this.items
  7. return this.items.hasOwnProperty(value)
  8. }
  9. add(value){
  10. if(!this.has(value)) {
  11. this.items[value] = value
  12. return true
  13. }
  14. return false
  15. }
  16. delete(value){
  17. if(!this.has(value)){
  18. delete this.items[value]
  19. return true
  20. }
  21. return false
  22. }
  23. clear(){
  24. this.items = {}
  25. }
  26. size(){
  27. const values = this.values()
  28. return values.length
  29. }
  30. values(){
  31. return Object.keys(this.items)
  32. }
  33. }

三、请实现集合的并集、交集、差集、子集操作

  • 并集(union):对于给定的两个集合,返回一个包含两个集合中所有元素的新集合。
  • 交集(intersection):对于给定的两个集合,返回一个包含两个集合中共用元素的新集合。
  • 差集(difference):对于给定的两个集合,返回一个包含所有存在于第一个集合且不存在于第二个集合的元素的新集合。
  • 子集(subset):验证一个给定集合是否是另一个集合的子集。

解题:

  1. /**
  2. * union 并集
  3. * @param {Object} otherSet 其他集合
  4. */
  5. Sets.prototype.union = function(otherSet){
  6. let result = new Sets(),
  7. current = this.values(),
  8. other = otherSet.values()
  9. for(let i = 0; i < current.length; i++){
  10. result.add(current[i])
  11. }
  12. for(let i = 0; i < other.length; i++){
  13. result.add(other[i])
  14. }
  15. return result
  16. }
  17. /**
  18. * intersection 交集
  19. * @param {Object} otherSet 其他集合
  20. */
  21. Sets.prototype.intersection = function(otherSet){
  22. let result = new Sets(),
  23. current = this.values()
  24. for(let i = 0; i < current.length; i++){
  25. if(otherSet.has(current[i])){
  26. result.add(current[i])
  27. }
  28. }
  29. return result
  30. }
  31. /**
  32. * difference 差集
  33. * @param {Object} otherSet 其他集合
  34. */
  35. Sets.prototype.difference = function(otherSet){
  36. let result = new Sets(),
  37. current = this.values()
  38. for(let i = 0; i < current.length; i++){
  39. if(!otherSet.has(current[i])){
  40. result.add(current[i])
  41. }
  42. }
  43. return result
  44. }
  45. /**
  46. * subset 子集
  47. * @param {Object} otherSet 其他集合
  48. */
  49. Sets.prototype.subset = function(otherSet){
  50. let result = new Sets(),
  51. current = this.values()
  52. if(this.size() > otherSet.size()) return false
  53. for(let i = 0; i < current.length; i++){
  54. if(!otherSet.has(current[i])){
  55. return false
  56. }
  57. }
  58. return true
  59. }

四、给定两个数组,编写一个 intersection() 函数来计算它们的交集

使用示例如下:

  1. const nums1 = [1, 2, 2, 1];
  2. const nums2 = [2, 2];
  3. const nums3 = [4, 9, 5];
  4. const nums4 = [9, 4, 9, 8, 4];
  5. intersection(nums1, nums2); // [2]
  6. intersection(nums3, nums4); // [9, 4]

提示:输出结果中的每个元素是唯一的,可以不考虑输出结果的顺序。


解题:

  1. function intersection(arr1, arr2){
  2. if(!Array.isArray(arr1) || !Array.isArray(arr2)) return []
  3. let create = function(arr){
  4. let sets = new Sets()
  5. arr.map(item => sets.add(item))
  6. return sets
  7. }
  8. let Sets1 = create(arr1)
  9. let Sets2 = create(arr2)
  10. let result = Sets1.intersection(Sets2)
  11. return result.values()
  12. }

五、给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集

使用示例如下:

  1. const nums = [1, 2, 3];
  2. subsets(nums);
  3. // 输出以下结果:
  4. [
  5. [3],
  6. [1],
  7. [2],
  8. [1, 2, 3],
  9. [1, 3],
  10. [2, 3],
  11. [1, 2],
  12. []
  13. ]

来源:leetcode 78.集合


解题:

目前网络上的最优解:

  1. function subsets(nums){
  2. if(!nums || !Array.isArray(nums)) return []
  3. function diff (num, vec) {
  4. let tmp = vec.slice(0)
  5. result.push(tmp)
  6. for (let i = num; i < len; i++) {
  7. vec.push(nums[i])
  8. diff(i + 1, vec)
  9. vec.splice(-1)
  10. }
  11. }
  12. const len = nums.length
  13. let arr = [], result = []
  14. diff(0, arr)
  15. return result
  16. }

穷举法:

  1. function subsets(nums){
  2. if(!nums || !Array.isArray(nums)) return []
  3. let result = [[]],
  4. len = nums.length
  5. if(len === 0) return result
  6. for(let i = 0; i < len; i++){
  7. let l = result.length
  8. let num = nums[i]
  9. let array = [num]
  10. for(let j = 0; j < l; j++){
  11. let tmparray = result[j].concat(array)
  12. result.push(tmparray)
  13. }
  14. }
  15. return result
  16. }

下周预告

下周将练习Dictionary 和 HashTable 的题目。

Author 王平安
E-mail pingan8787@qq.com
博 客 www.pingan8787.com
微 信 pingan8787
每日文章推荐 https://github.com/pingan8787/Leo_Reading/issues
ES小册 js.pingan8787.com

微信公众号

3.Set - 图1