检查是否存在具有给定总和的非相邻对
给定一个数组nums [ ] 和一个整数目标。查找nums [ ] 中是否存在整数组合,使得它们的和等于目标,并且这些元素在原始数组中都不相邻。
示例:
Input : nums[ ] = [1, 2, 2, 3], target = 4
Output : true
Explanation : We can pick [1, 3] since they are non-adjacent and sums to 4
Input : nums[ ] = [1, 3, 1], target = 4
Output: false
Explanation : We can’t pick [1, 3] or [3, 1] since they are adjacent.
方法:可以使用动态编程按照以下步骤解决问题:
- dp[i][j]:创建一个 2-d dp 数组,存储在考虑数组中的前 i 个元素后是否有可能获得恰好 j 的总和。
- 在给定索引 i 和给定总和 j 处,可能有两种情况:
- 要么我们可以包含当前数字 nums[i],要么不包含。
- 如果我们不包括当前数字,我们只需回顾 dp 的上一行。
- 如果我们确实包含当前数字,我们必须回顾 dp 数组中的两行,因为不能选择相邻的元素。
- 因此,一旦我们选择了元素 i,我们就可以忽略元素 i-1,因为它不能被采用。
- 基本情况:
- 最初用 false 初始化布尔 dp 表。
- 然后,在第一列中填写 true,因为总和 0 始终可以通过不取任何元素来实现。
- 同时用真值填充dp[i][nums[i]] ,这表明我们可以在考虑数组中的前 i 个元素后得到 nums[i] 的总和(很明显只取索引 i 处的元素) .
- 过渡状态:
- 案例1: dp[i][j] = dp[i – 1][j] || dp[i][j]
- 检查上一行的值
- 如果它是真的,那么我们可以通过将元素直到最后一行来使子集总和等于目标,
- 所以也让 dp[i][j] 为真
- 案例2: dp[i][j] = dp[i – 2][j – nums[i]] || dp[i][j]
- 检查我们是否将当前元素 nums[i] 添加到当前行 - 2(因为它不相邻)dp 表,并使总和等于目标。
- 案例1: dp[i][j] = dp[i – 1][j] || dp[i][j]
插图:
Consider the example where nums[ ] = [1, 2, 2, 3], target = 4
The dp table would look like the following (i represents nums[i] and j represent target)i (nums[i]) \ j (target) 0 1 2 3 4 0 (nums[0]=1) true true false false false 1 (nums[1]=2) true true true false false 2 (nums[2]=2) true true true true false 3 (nums[2]=3) true true true true true
下面是上述方法的实现:
C++
// C++ program to implement above approach
#include
using namespace std;
bool subsetSumNonAdjacent(
vector& nums, int target)
{
// size of the array
int n = nums.size();
// Boolean dp table fill with false
vector > dp(
n, vector(target + 1, false));
// Base Case
// Initialize dp[i][0]= true
// as 0 can always be achieved
// by not taking anything
for (int i = 0; i < n; i++) {
dp[i][0] = true;
}
// Initialize dp[i][nums[i]]= true
// as nums[i] can always be achieved
// by taking only element
// at index i that is nums[i]
for (int i = 0; i < n; i++) {
dp[i][nums[i]] = true;
}
for (int i = 0; i < n; i++) {
for (int j = 0; j <= target; j++) {
// check if we can take previous row
if (i - 1 >= 0) {
dp[i][j]
= dp[i - 1][j] || dp[i][j];
}
// check for row-2
if (i - 2 >= 0 && j >= nums[i]) {
dp[i][j]
= dp[i - 2][j - nums[i]]
|| dp[i][j];
}
}
}
return dp[n - 1][target];
}
// Driver code
int main()
{
vector nums = { 1, 2, 2, 3 };
int target = 4;
cout << boolalpha
<< subsetSumNonAdjacent(nums, target);
return 0;
}
Java
// Java Program of the above approach.
import java.util.*;
class GFG {
static boolean subsetSumNonAdjacent(int[] nums, int target)
{
// size of the array
int n = nums.length;
// Boolean dp table fill with false
boolean[][] dp = new boolean[n][target + 1];
for (int i = 0; i < n; i++) {
for (int j = 0; j < target + 1; j++) {
dp[i][j] = false;
}
}
// Base Case
// Initialize dp[i][0]= true
// as 0 can always be achieved
// by not taking anything
for (int i = 0; i < n; i++) {
dp[i][0] = true;
}
// Initialize dp[i][nums[i]]= true
// as nums[i] can always be achieved
// by taking only element
// at index i that is nums[i]
for (int i = 0; i < n; i++) {
dp[i][nums[i]] = true;
}
for (int i = 0; i < n; i++) {
for (int j = 0; j <= target; j++) {
// check if we can take previous row
if (i - 1 >= 0) {
dp[i][j] = dp[i - 1][j] || dp[i][j];
}
// check for row-2
if (i - 2 >= 0 && j >= nums[i]) {
dp[i][j] = dp[i - 2][j - nums[i]]
|| dp[i][ j];
}
}
}
return dp[n - 1][target];
}
// Driver Code
public static void main(String args[])
{
int[] nums = { 1, 2, 2, 3 };
int target = 4;
System.out.print(subsetSumNonAdjacent(nums, target));
}
}
// This code is contributed by code_hunt.
Python3
# Python program to implement above approach
def subsetSumNonAdjacent(nums,target):
# size of the array
n = len(nums)
# Boolean dp table fill with false
dp = [[False]*(target+1)]*n
# Base Case
# Initialize dp[i][0]= true
# as 0 can always be achieved
# by not taking anything
for i in range(n):
dp[i][0] = True
# Initialize dp[i][nums[i]]= true
# as nums[i] can always be achieved
# by taking only element
# at index i that is nums[i]
for i in range(n):
dp[i][nums[i]] = True
for i in range(n):
for j in range(target+1):
# check if we can take previous row
if (i - 1 >= 0):
dp[i][j] = dp[i - 1][j] or dp[i][j]
# check for row-2
if (i - 2 >= 0 and j >= nums[i]):
dp[i][j] = dp[i - 2][j - nums[i]] or dp[i][j]
return dp[n - 1][target]
# Driver code
nums = [ 1, 2, 2, 3 ]
target = 4
print(subsetSumNonAdjacent(nums, target))
# This code is contributed by shinjanpatra
C#
// C# program to implement above approach
using System;
class GFG {
static bool subsetSumNonAdjacent(int[] nums, int target)
{
// size of the array
int n = nums.Length;
// Boolean dp table fill with false
bool[, ] dp = new bool[n, target + 1];
for (int i = 0; i < n; i++) {
for (int j = 0; j < target + 1; j++) {
dp[i, j] = false;
}
}
// Base Case
// Initialize dp[i][0]= true
// as 0 can always be achieved
// by not taking anything
for (int i = 0; i < n; i++) {
dp[i, 0] = true;
}
// Initialize dp[i][nums[i]]= true
// as nums[i] can always be achieved
// by taking only element
// at index i that is nums[i]
for (int i = 0; i < n; i++) {
dp[i, nums[i]] = true;
}
for (int i = 0; i < n; i++) {
for (int j = 0; j <= target; j++) {
// check if we can take previous row
if (i - 1 >= 0) {
dp[i, j] = dp[i - 1, j] || dp[i, j];
}
// check for row-2
if (i - 2 >= 0 && j >= nums[i]) {
dp[i, j] = dp[i - 2, j - nums[i]]
|| dp[i, j];
}
}
}
return dp[n - 1, target];
}
// Driver code
public static void Main()
{
int[] nums = { 1, 2, 2, 3 };
int target = 4;
Console.Write(subsetSumNonAdjacent(nums, target));
}
}
// This code is contributed by Samim Hossain Mondal.
Javascript
true
时间复杂度:O(N*target)
辅助空间:O(N*target)