golang力扣leetcode 416.分割等和子集

简介: golang力扣leetcode 416.分割等和子集

416.分割等和子集

416.分割等和子集

题解

题目:给定一个数组,问能否将该数组分成两个数组,并且这两个数组元素累加值一样

思路:

首先剪枝:

1. 数组元素少于2,肯定不行

2. 数组元素累加和是奇数,肯定不行

3. 元素中最大元素>累加和的一半,肯定不行

那么对于数组来说,只要拼凑出元素和=累加和/2,就行了,一定会存在没有选的元素累加=一半的。

1. 刚开始,想的是递归,只有选和不选,超时
2. 记忆化, AC,但是效率很低

对于自上而下的递归,一般都可以修改为自下而上的动态规划

target=sum/2
因为我们需要元素累加刚好等于target
定义:dp[i][j]前i个元素,累加和j,是否为true
初始:dp[0][nums[0]]=true
状态转移:dp[i][j] = dp[i-1][j] || dp[i-1][j-v]
      不选这个元素  || 选这个元素
最终:dp[len(nums)-1][target]
众所周知01背包二位转一维优化空间复杂度
二维数组转一维,滚动数组

代码

func canPartition(nums []int) bool {
  if len(nums) < 2 {
    return false
  }
  sum, max := 0, 0
  for _, v := range nums {
    sum += v
    if max < v {
      max = v
    }
  }
  if sum%2 != 0 {
    return false
  }
  target := sum / 2
  if max > target {
    return false
  }
  type pair struct {
    idx, tot int
  }
  mp := make(map[pair]bool)
  var dfs func(idx, tot int) bool
  dfs = func(idx, tot int) bool {
    if tot == target {
      return true
    }
    if tot > target || idx >= len(nums) {
      return false
    }
    p := pair{idx, tot}
    if _, ok := mp[p]; !ok {
      mp[p] = dfs(idx+1, tot) || dfs(idx+1, tot+nums[idx])
    } else {
      return mp[p]
    }
    return mp[p]
  }
  return dfs(0, 0)
}
func canPartition(nums []int) bool {
  if len(nums) < 2 {
    return false
  }
  sum := 0
  max := 0
  for _, v := range nums {
    sum += v
    if max < v {
      max=v
    }
  }
  if sum%2 != 0 {
    return false
  }
  target := sum / 2
  if max > target {
    return false
  }
  dp := make([][]bool, len(nums))
  for i := range dp {
    dp[i] = make([]bool, target+1)
  }
  dp[0][nums[0]] = true
  for i := 1; i < len(nums); i++ {
    v := nums[i]
    for j := 1; j <= target; j++ {
      if j >= v {
        dp[i][j] = dp[i-1][j] || dp[i-1][j-v]
      } else {
        dp[i][j] = dp[i-1][j]
      }
    }
  }
  return dp[len(nums)-1][target]
}
func canPartition(nums []int) bool {
  if len(nums) < 2 {
    return false
  }
  sum := 0
  max := 0
  for _, v := range nums {
    sum += v
    if max < v {
      v = max
    }
  }
  if sum%2 != 0 {
    return false
  }
  target := sum / 2
  if max > target {
    return false
  }
  dp := make([]bool, target+1)
  dp[0] = true
  for i := 0; i < len(nums); i++ {
    v := nums[i]
    for j := target; j >= v; j-- {
      dp[j] = dp[j] || dp[j-v]
    }
  }
  return dp[target]
}
目录
相关文章
|
4月前
|
算法
LeetCode第90题子集II
LeetCode第90题"子集II"的解题方法,通过排序和回溯算法生成所有不重复的子集,并使用一个boolean数组来避免同一层中的重复元素,展示了解决这类问题的编码技巧。
LeetCode第90题子集II
|
2月前
|
程序员 C语言
【C语言】LeetCode(力扣)上经典题目
【C语言】LeetCode(力扣)上经典题目
|
2月前
|
索引
力扣(LeetCode)数据结构练习题(3)------链表
力扣(LeetCode)数据结构练习题(3)------链表
96 0
|
2月前
力扣(LeetCode)数据结构练习题(2)
力扣(LeetCode)数据结构练习题(2)
32 0
|
2月前
|
存储
力扣(LeetCode)数据结构练习题
力扣(LeetCode)数据结构练习题
57 0
|
3月前
|
Go
Golang语言之管道channel快速入门篇
这篇文章是关于Go语言中管道(channel)的快速入门教程,涵盖了管道的基本使用、有缓冲和无缓冲管道的区别、管道的关闭、遍历、协程和管道的协同工作、单向通道的使用以及select多路复用的详细案例和解释。
142 4
Golang语言之管道channel快速入门篇
|
3月前
|
Go
Golang语言文件操作快速入门篇
这篇文章是关于Go语言文件操作快速入门的教程,涵盖了文件的读取、写入、复制操作以及使用标准库中的ioutil、bufio、os等包进行文件操作的详细案例。
72 4
Golang语言文件操作快速入门篇
|
3月前
|
Go
Golang语言之gRPC程序设计示例
这篇文章是关于Golang语言使用gRPC进行程序设计的详细教程,涵盖了RPC协议的介绍、gRPC环境的搭建、Protocol Buffers的使用、gRPC服务的编写和通信示例。
117 3
Golang语言之gRPC程序设计示例
|
3月前
|
安全 Go
Golang语言goroutine协程并发安全及锁机制
这篇文章是关于Go语言中多协程操作同一数据问题、互斥锁Mutex和读写互斥锁RWMutex的详细介绍及使用案例,涵盖了如何使用这些同步原语来解决并发访问共享资源时的数据安全问题。
100 4
|
3月前
|
Go 调度
Golang语言goroutine协程篇
这篇文章是关于Go语言goroutine协程的详细教程,涵盖了并发编程的常见术语、goroutine的创建和调度、使用sync.WaitGroup控制协程退出以及如何通过GOMAXPROCS设置程序并发时占用的CPU逻辑核心数。
74 4
Golang语言goroutine协程篇