Java 给定一个未排序的非负整数数组,找到一个非连续的子数组,使其总和为一个给定的数。
时间: 2024-03-16 12:45:50 浏览: 14
可以使用动态规划来解决这个问题。
定义一个数组 dp,其中 dp[i] 表示在前 i 个元素中是否存在一个子数组的和等于给定的数。初始时,dp[0] 为 true,其余为 false。
然后遍历数组中的每一个元素,对于每一个元素 nums[i],从后往前遍历 dp 数组,如果 dp[j-nums[i]] 为 true,则 dp[j] 也为 true(其中 j 表示当前要判断的和数)。
最终,如果 dp[sum] 为 true,其中 sum 表示给定的数,那么就说明存在一个非连续的子数组的和等于给定的数。
Java 代码实现如下:
```
public boolean findSubarray(int[] nums, int target) {
boolean[] dp = new boolean[target + 1];
dp[0] = true;
for (int i = 0; i < nums.length; i++) {
for (int j = target; j >= nums[i]; j--) {
dp[j] = dp[j] || dp[j - nums[i]];
}
}
return dp[target];
}
```
时间复杂度为 O(n * target),空间复杂度为 O(target)。
相关问题
给定一个未排序的整数数组,找出数组连续的最长的序列并且打印列表
思路:先将数组排序,然后遍历数组,统计当前连续序列的长度和起始数字,如果当前数字不是上一个数字的后继,则当前连续序列结束,比较当前连续序列长度和最长连续序列长度,如果当前连续序列更长,则更新最长连续序列的长度和起始数字。
代码如下:
```python
def longestConsecutive(nums):
if not nums:
return []
nums.sort()
max_len = 1
cur_len = 1
start = nums[0]
res = [start]
for i in range(1, len(nums)):
if nums[i] == nums[i-1] + 1:
cur_len += 1
elif nums[i] != nums[i-1]:
if cur_len > max_len:
max_len = cur_len
res = list(range(start, start+max_len))
cur_len = 1
start = nums[i]
if cur_len > max_len:
res = list(range(start, start+cur_len))
return res
```
测试:
```python
print(longestConsecutive([100, 4, 200, 1, 3, 2])) # [1, 2, 3, 4]
print(longestConsecutive([1, 2, 0, 1])) # [0, 1, 2]
```
给定一个整数数组,找到一个具有最大和的连续子数组
解法1:暴力枚举
通过枚举所有的连续子数组,计算它们的和,最后返回最大的和。
时间复杂度:O(n^2)
代码:
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
max_sum = float('-inf')
for i in range(len(nums)):
cur_sum = 0
for j in range(i, len(nums)):
cur_sum += nums[j]
if cur_sum > max_sum:
max_sum = cur_sum
return max_sum
解法2:动态规划
我们可以用 dp[i] 表示以第 i 个元素结尾的最大连续子数组的和,那么 dp[i] 可以由 dp[i-1] 转移得到:
dp[i] = max(dp[i-1] + nums[i], nums[i])
时间复杂度:O(n)
代码:
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
dp = [0] * len(nums)
dp[0] = nums[0]
max_sum = nums[0]
for i in range(1, len(nums)):
dp[i] = max(dp[i-1] + nums[i], nums[i])
max_sum = max(max_sum, dp[i])
return max_sum
解法3:分治法
将数组分成左右两部分,分别求出左半部分的最大子数组、右半部分的最大子数组以及跨越中心的最大子数组,最后返回三者中的最大值。
时间复杂度:O(nlogn)
代码:
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
return self.helper(nums, 0, len(nums)-1)
def helper(self, nums, left, right):
if left > right:
return float('-inf')
mid = (left + right) // 2
left_max = self.helper(nums, left, mid-1)
right_max = self.helper(nums, mid+1, right)
cross_max = self.crossMax(nums, left, mid, right)
return max(left_max, right_max, cross_max)
def crossMax(self, nums, left, mid, right):
left_max = float('-inf')
cur_sum = 0
for i in range(mid, left-1, -1):
cur_sum += nums[i]
left_max = max(left_max, cur_sum)
right_max = float('-inf')
cur_sum = 0
for i in range(mid+1, right+1):
cur_sum += nums[i]
right_max = max(right_max, cur_sum)
return left_max + right_max
解法4:贪心算法
我们可以从左到右遍历数组,记录当前连续子数组的和 cur_sum 和最大连续子数组的和 max_sum,如果 cur_sum 加上下一个数 nums[i] 小于 nums[i],那么从 nums[i] 开始重新计算 cur_sum。每次更新 max_sum,最后返回 max_sum 即可。
时间复杂度:O(n)
代码:
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
cur_sum = max_sum = nums[0]
for i in range(1, len(nums)):
cur_sum = max(nums[i], cur_sum+nums[i])
max_sum = max(max_sum, cur_sum)
return max_sum