您的位置:首页 > 其它

对数组每个元素增加一个量,使得数组递增

2014-12-02 21:29 393 查看
一个题目,据说来自Hired online test:

#!/usr/bin/env python3
# coding: utf-8

"""
Challenge 3: Hill

Given an array of integer elements

Your task is to

- write a function that finds the minimum value X that makes possible the
following: generate a new array that is sorted in strictly ascending order
by increasing or decreasing each of the elements of the initial array with
integer values in the [0, X] range.

- Example: Having the initial array [5, 4, 3, 2, 8] the minimum value
for X is 3. Decrease the first element (5) by 3, decrease the second
one (4) by 1, increase the third one (3) by 1, increase the forth one
(2) by 3 and do nothing to the last one (8). In the end we obtain the
array [2, 3, 4, 5, 8] which is sorted in strictly ascending order.

- print the result X to the standard output (stdout)

Note that your function will receive the following arguments:

- v, which is the array of integers

Data constraints

- numbers are in ascending order when arranged from the smallest to the
largest number
- strictly ascending order means that each element is greater than the
preceding one (e.g., [1, 2, 2, 3] is NOT strictly ascending order)
- the length of the array will not exceed 5000
- the elements of any of the arrays are integer numbers in the [1, 2^31 - 1]
range

Efficiency constraints

- your function is expected to print the result in less than 2 seconds

Example

Input                Output
----------------     ------
v: 5, 4, 3, 2, 8     3
"""

def hill(v):
# Write your code here
# To print results to the standard output you can use print
# Example print "Hello world!"


大意:给定一数组arr[],找出一个最小的X,使得在数组每一元素arr[i]上加一个[-X,X]内的值后,数组arr[]严格递增。

思路:

(1)不难看出,如果区间[-X,X]可行,则区间[-X-1,X+1]一定可行,因此我们可以采用二分法探索X的最值

(2)如果数组原本就严格递增,则X = 0

(3)进一步发现,X = max(n, m)时,肯定可行,其中m为数组中的最大值:我们可以通过对每个元素加上一个[-X,X]的值,使得数组离变为0, 1, 2, ..., n-1

(4)如何判断[-X,X]是否是一个有效的区间呢,这样考虑:我们希望变换后的数组严格递增,很容易想到首先让arr[0]变得最小(其他值可以的话,最小值肯定可以),因此arr[0]变为trans[0] = arr[0]-X,对于arr[i],我们把它变成大于trans[i-1]的最小trans[i](其他值可以的话,最小值肯定可以),则arr[i] + inc[i] > arr[i-1] + inc[i-1],即inc[i] =arr[i-1] + inc[i-1] - arr[i] + 1,如果inc[i]
< -X,那我们不得不把inc[i]调大,让inc[i] = -X,如果inc[i] > X,则arr[i]无论如何都不能成为递增数组的一部分,毕竟arr[0, i)已经是最小的可行值了。

每检查一个区间[-X,X]是否可行,我们需要遍历一次数组,而我们需要检查O(log(max(m, n)))个区间,因此时间复杂度为O(nlog(max(m,n))),空间复杂度为O(1)。

根据上述思路,可以得到如下代码:

#include <cstdio>
#include <algorithm>
using namespace std;

//check if we can make arr[] become ascending
//by adding a number within [-m, m] to each element
bool canMakeAHill(int arr[], int n, int m)
{
int d = -m, i = 1;
for(; i < n; ++i){
d = arr[i-1] + d - arr[i] + 1;
if(d > m) return false;
if(d < -m) d = -m;
}
return true;
}
//find out the minimum number m that we can make arr[] become ascending
//by adding a number within [-m, m] to each element
int hill(int arr[], int n)
{
int i, l, r;
bool sorted = true;
//check if arr[] is sorted already and find out the max element
r = arr[0];
for(i = 1; i < n; ++i){
if(arr[i-1] >= arr[i]) sorted = false;
else r = max(r, arr[i]);
}
if(sorted) return 0;
//binary search
l = 0;
r = max(r, n);
while(l + 1 < r){
int m = (l + r) >> 1;
if(canMakeAHill(arr, n, m)) r = m;
else l = m;
}
return r;
}

int main()
{
int arr[] = {5, 4, 3, 2, 8};
printf("%d\n", hill(arr, sizeof(arr)/sizeof(arr[0])));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐