【LeetCode 1049】最后一块石头的重量 II

15 篇文章 0 订阅
/*
难度:中等
有一堆石头,每块石头的重量都是正整数,
每一回合,从中选出任意两块石头: 如果重量不等,则将较轻的石头粉碎,然后将两者重量之差赋给较重的那块石头;如果重量相等,则两块都粉碎,
最后,最多只会剩下一块石头,求此石头最小的可能重量。如果没有石头剩下,则返回0。

示例:
输入:[2,7,4,1,8,1]
输出:1
解释:
组合 2 和 4,得到 2,所以数组转化为 [2,7,1,8,1],
组合 7 和 8,得到 1,所以数组转化为 [2,1,1,1],
组合 2 和 1,得到 1,所以数组转化为 [1,1,1],
组合 1 和 1,得到 0,所以数组转化为 [1],这就是最优值。
*/ 
extension Daily { 
	static func test_leetcode1049() {
		let nums = [2,7,4,1,8,1]
		if let res = Daily.leetcode1049(stones: nums) {
			print("最终结果 \(res)")
		}
	}
	
	static func leetcode1049(stones: [Int]) -> Int? {
		if stones.count < 1 {
//			print("nums is empty")
			return 0
		}
		if stones.count == 1 {
			return stones[0]
		}
		if stones.count == 2 {
			return abs(stones[0] - stones[1])
		}
		var sum = 0
		for item in stones {
			sum += item
		}
//		print("sum=\(sum)")

		let rows = stones.count + 1
		let cols = sum/2 + 1
		var map = Array(repeating: 0, count: rows * cols)
		
		for idx1 in 1..<rows {
			let current = stones[idx1-1] //当前石头重量
			for idx2 in 1..<cols {
				let cidx = idx1 * cols + idx2
				let cidxTop = cidx - cols
				if current < idx2 {
					map[cidx] = map[cidxTop] + map[(idx1-1)*cols + idx2 - current]
				}
				else if current == idx2 {
					map[cidx] = map[cidxTop] + 1
				}
				else {
					map[cidx] = map[cidxTop]
				}
			}
		}
				
		//找到第一个不为0的
		var exist = 0
		aloop: for idx1 in stride(from: cols-1, through: 0, by: -1) {
			for idx2 in stride(from: rows-1, through: 0, by: -1) {
				if map[idx2*cols + idx1] > 0 {
					exist = idx1
					break aloop
				}
			}
		}
		
//		print("最大: \(exist)")
		
		//找出一种可能的解法
//		floop: for idx1 in stride(from: cols-1, through: 0, by: -1) {
//			for idx2 in 1..<rows {
//				var cur = map[idx2*cols + idx1]
//				var top = map[idx2*cols + idx1 - cols]
//				var count = 0
//				var nextcol = idx1
//				var nextrow = idx2
//				var choosed = [Int]()
//				if cur <= top {
//					continue
//				}
//				while nextrow > 0 && nextcol > 0 {
//					cur = map[nextrow*cols + nextcol]
//					top = map[nextrow*cols + nextcol - cols]
//					if cur == 0 {
//						count = 0
//						break
//					}
//					if cur > top {
//						choosed.append(stones[nextrow-1])
//						count += 1
//						nextcol = nextcol - stones[nextrow-1]
//						nextrow -= 1
//					}
//					else {
//						nextrow -= 1
//					}
//				}
//				if count > 0 {
//					print("一种解法:\(idx1), \(idx2), \(choosed)")
//				}
//				break floop
//			}
//		}
		
		return sum - 2*exist
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值