【LeetCode 1711】大餐计数

15 篇文章 0 订阅
/*
难度:中等

大餐是指恰好包含两道不同餐品的一餐,其美味程度之和等于2的幂。
你可以搭配任意两道餐品做一顿大餐。
给定一个整数数组,其中第i项是第i道餐品的美味程度,返回你可以用数组中的餐品做出的不同大餐的数量。
结果需要对 10^9 + 7 取余。
只要餐品下标不同就可以认为是不同的餐品,即便美味程度相同。

示例 1:
输入:deliciousness=[1,3,5,7,9]
输出:4
解释:(1,3), (1,7),(3,5),(7,9)

示例 2:
输入:deliciousness=[1,1,1,3,3,3,7]
输出:15
解释:3种(1,1), 9种(1,3), 3种(1,7)

提示:
1<= deliciousness.length <= 100000
0<= deliciousness[i] <= 2^20
*/ 
extension Daily { 
	static func test_leetcode1711() {
		let cases = [
			[1,3,5,7,9],
			[1,1,1,3,3,3,7],
			[1048576,1048576],
		]
		for deliciousness in cases {
			print("输入:\(deliciousness)")
			let start = NSDate.now
			print("开始时间 \(NSDate.now)")
			let res = Daily.leetcode1711(deliciousness: deliciousness)
			let end = NSDate.now
			print("输出:\(res), \(end.timeIntervalSince(start))\n")
		}
	}
	static func leetcode1711(deliciousness: [Int]) -> Int {
		//必须包含两道餐品
		if deliciousness.count < 2 {
			return 0
		}
		var stat = [Int:Int]()
		for idx in 0..<deliciousness.count {
			let current = deliciousness[idx]
			if stat[current] == nil {
				stat[current] = 1
			}
			else {
				stat[current]! += 1
			}
		}
		let bits = [
			0x200000, 0x100000, 0x80000, 0x40000, 0x20000, 
			0x10000, 0x8000, 0x4000, 0x2000, 0x1000, 
			0x800, 0x400, 0x200, 0x100, 0x80,
			64, 32, 16, 8, 4, 2, 1,
		]
		
		var total = 0
		for idx in 0..<deliciousness.count {
			let current = deliciousness[idx]
			if stat[current] == nil {
				continue
			}
			for other in bits {
				if other < current {
					break
				}
				let rest = other - current
				if let x = stat[rest] {
					if rest == current {
						total += x*(x-1)/2
					}
					else {
						total += x * stat[current]!
					}
				}
			}
			total %= 1000000007
			stat.removeValue(forKey: current)
		}
		
		return total
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值