面试题5:最大下标距离

题目:给定一个整型数组A,找出最大下标距离j-i,当且仅当 A[i]<A[j]和i<j

书中给出的思路:

思路一:常规我们最直观想到的解决方法是

(1)i=0,j=end(end为最后下标所在位置),max=0

(2)如果A[i]<A[j],j-i>max,则max=j-i

(3)i++,j=end

(4)重复第二、第三步骤,直到i==j

这种算法的时间复杂度是 1+2+...+n-1 = (n-1)*(n-2)/2 = O(n^2)


思路二:通过观察,我们可以得到这样一个规律,在递减序列中,递减系列最小(下标i1),如存在一个i2,使得i1<i2,A[i1]<A[i2],那么若i2<j且A[i2]<A[j],则i1<j和A[i1]<A[j]这个条件一定满足,这时j-i1>j-i2,先理解这上面一段

假设:{5,3,4,0,1,4,1}这个整型数组

算法核心思路:

(1)找出下降序列(这边找到的是5,3,0。为什么不可以是5,4,0呢?这边值3的下标是1,值4的下标是2,用反证法,在这个下降序列后面存在一个值大于4的值下标为j,则一定满足j-1>j-2,看到书上实现找出下降序列的代码非常好)

(2)i=值最小的下标位置,j=最末尾的下标位置

(3)j--,如果满足A[i]<A[j]和i<j,则判断max和j-i的大小,max小于j-i的话,max=j-i

            若出现i>=j,则跳到第五步骤

(4)i--,如果满足i为下降序列中的一员,i>=0,则判断A[i]和A[j]大小,

            如果A[i]<A[j],判断max和j-i的大小,max小于j-i的话,max=j-i

            如果A[i]>A[j],i--已经没有意义了(因为比当前i更小的下降序列对应的值肯定是大于A[j]),此时要跳完第三步骤

            若出现i<0,则跳到第五步骤

(5)此时的max即为最大下标距离

func maxIndexDistance(a []int) int {
	if len(a) < 2 {
		return 0
	}
	inDescSeq, min, n := make([]bool, 0), a[0], len(a)
	// 步骤一
	for i := 0;i < n;i += 1 {
		inDescSeq = append(inDescSeq, false)
		if a[i] < min {
			// 做下降序列的标记
			inDescSeq[i] = true
			min = a[i]
		}
	}
	// 步骤二
	maxDist, i, j := 0, n - 1, n - 1
	for i >= 0 {
		// 第三步骤
		if inDescSeq[i] == false {
			// 第一次找出下降序列的元素也是属于,步骤二
			i--
			continue
		}
		// 第四步骤
		for a[i] >= a[j] && j > i {
			j--	// 从后往前移动直至找到符合的元素,
		}
		if (j - i) > maxDist {
			maxDist = j - i
		}
		i--
	}
	// 第五步骤
	return maxDist
}

以上总共做了三次线性扫描,每次扫描的时间复杂度为O(n),因此,整个算法的时间复杂度为O(n)


猜你喜欢

转载自blog.csdn.net/qq_35191331/article/details/80210146