给定一个数组= {1 2 3 3 2 4 6 7}
增长最长的子阵列是2 4 6 7.请注意,这与最长的子序列不同,因为值必须是连续的。
这个问题有没有O(n)解决方案?
答案 0 :(得分:14)
您可以使用动态编程。
伪代码:
def DP(a[]):
dp[1] = 1
for i = 2 to n:
if a[i] > a[i - 1]:
dp[i] = dp[i - 1] + 1
else:
dp[i] = 1
答案 1 :(得分:4)
答案 2 :(得分:4)
1 < 2 < 3 >= 3 >= 2 < 4 < 6 < 7
| 1 2 3 | 1 | 1 2 3 4 <- Length of runs
从左到右遍历数组。跟踪当前运行的时间。
当跑步结束时,将其与目前为止的最佳跑步进行比较,为此您存储长度和结束的位置。如果刚刚结束的运行更好,请更新运行良好的数据。
1 < 2 < 3 >= 3 >= 2 < 4 < 6 < 7
| 1 2 3 | 1 | 1 2
^
Longest run,
ending at index 2
1 < 2 < 3 >= 3 >= 2 < 4 < 6 < 7
| 1 2 3 | 1 | 1 2 3 4
^ ^
Longest run, Current run ends
ending at index 2 Better than last longest run, update
由于您一次只访问一个元素并且另外访问最佳运行数据,因此您只遍历数组,因此每个元素都会执行恒定时间。因此,该算法在O(n)
中运行。
答案 3 :(得分:2)
您应该能够在线性时间内解决此问题,如下所示。保持每个点
然后,您可以在一次传递中循环遍历数组,并为每个值执行以下操作:
这样O(1)工作O(n)次,因此整体解决方案在时间O(n)内运行。
希望这有帮助!
答案 4 :(得分:2)
int flag = 0;
int maxSubarray =0;
int maxStart=0,maxEnd=0,start=0,end=0;
for(int i=1;i<n;i++){
if(a[i-1]<a[i]){
if(flag!=1){
start = i-1;
flag=1;
}
if(i == n-1){
end = n-1;
}
}
else{
if(flag==1 ){
end = i-1;
flag =0;
}
}
if(maxSubarray < end - start){
maxSubarray = end - start;
maxStart = start;
maxEnd = end;
}
}
System.out.println(maxSubarray);
System.out.println("Starting index = "+maxStart+" Ending index = "+maxEnd);`
`
时间复杂度:O(n) 空间复杂度:O(1)
答案 5 :(得分:1)
Jun HU的回答是正确的,但我认为我们不需要维护一个占用O(n)空间的数组。我们可以改为跟踪当前子阵列的大小,例如
int maxSize, currentSize = 1;
for (int i = 1; i < array.size(); i++) {
if (array[i] > array[i-1]) {
currentSize++;
maxSize = max(currentSize, maxSize);
} else {
currentSize = 1;
}
}
这是有效的,因为在对数组进行排序时,如果当前元素不高于前一个元素,则当前子数组不再按递增顺序排列,因此我们不再关心它的大小。这样,我们可以在保持线性时间复杂度的同时实现恒定的空间复杂度。
答案 6 :(得分:0)
def lis(a):
m = 0
c = 1
index = 0
for i in xrange(1, len(a)):
x = a[i]
if x > a[i - 1]:
c += 1
else:
if c > m:
m = c
index = i
c = 1
if c > m:
m = c
index = i
return a[i - m + 1: i + 1]
答案 7 :(得分:0)
Java中的O(n)实现,也是通用的,可以用于任何事情!
import java.util.Arrays;
public class LongestIncreasing {
private static class PairHolder<T> {
int start = -1;
int end = -1;
int weight = -1;
PairHolder(int start, int end) {
this.start = start;
this.end = end;
this.weight = start == -1 ? -1 : end-start+1;
}
String getSubArray(T[] arr) {
return Arrays.toString(Arrays.copyOfRange(arr, start, end+1));
}
@Override
public String toString() {
return "[" + start + ", " + end + ", weight: " + weight + "]";
}
}
public static <T extends Comparable<? super T>> void getContiguousChain(T[] chain) {
int start = -1, end = -1;
PairHolder<T> longest = new PairHolder<T>(-1, -1);
for (int i = 0; i < chain.length - 1; i++) {
if (start == -1) {
start = i;
end = i;
}
if (chain[i+1].compareTo(chain[i]) == -1 || chain[i+1].compareTo(chain[i]) == 0) {
if (end-start+1 > longest.weight) {
longest = new PairHolder<T>(start, end);
}
start = -1; end = -1;
continue;
}
end = i+1;
}
if (end-start+1 > longest.weight) { //corner case where last element of chain is also end of array
longest = new PairHolder<T>(start, end);
}
System.out.println(longest.getSubArray(chain));
}
public static void main(String[] args) {
Integer[] arr = {2, 3, 3, 4, 5, 6, 2, 9, 10, 12, 14, 13};
getContiguousChain(arr);
}
}
答案 8 :(得分:0)
这将为您提供范围(开始和结束索引)。
public static Range getLargest(int[] array) {
int max = 1;
int start = 0;
int aux = 0;
int count = 1;
for (int i = 1; i < array.length; i++) {
if (array[i] > array[i - 1]) {
count++;
} else {
aux = i;
count = 1;
}
if (count > max) {
max = count;
start = aux;
}
}
return new Range(start, start + max - 1);
}
public static class Range {
public final int start;
public final int end;
public Range(int start, int end) {
this.start = start;
this.end = end;
}
}
答案 9 :(得分:0)
这不是动态编程解决方案,但我只是尝试了一些场景,它看起来可以正常使用。对你来说可能是一个很好的起点
public static int MaxSlice(int[] A)
{
//100,40,45,50,55,60, 30,20,40,25,28,30
int maxstartIndex = 0;
int MaxAscendingCount = 0;
int thisStartIndex = 0;
int thisAscendingCount = 0;
bool reset = false;
bool wasLastAscending = false;
for (int i = 0; i < A.Length-1; i++ )
{
if (A[i + 1] > A[i])
{
if(!wasLastAscending)
thisStartIndex = i;
thisAscendingCount++;
wasLastAscending = true;
}
else
{
reset = true;
wasLastAscending = false;
}
if (reset && thisAscendingCount > MaxAscendingCount)
{
MaxAscendingCount = thisAscendingCount;
maxstartIndex = thisStartIndex;
reset = false;
thisAscendingCount = 0;
}
}
MaxAscendingCount = thisAscendingCount;
maxstartIndex = thisStartIndex;
return maxstartIndex;
}