Optimization 如何使执行时间从O(N^2)变为O(N)
我试图在线解决一个编程问题(既不是我的家庭作业,也不是我的任何面试/测试,但可能是一个很好的候选人)。 下面给出了问题。我下面的代码在功能上是正确的,但它的运行时复杂性是O(N2),正如解决方案所期望的那样,应该是O(N) 我尝试了两种其他方法来优化它-1)对数组进行排序,然后尝试是否可以让它工作,但由于排序会导致原始数字的索引丢失,我甚至将它们保留在单独的数组中,并解决了它,但即使是O(N2)。我确信数组的排序将有助于达到O(N),但只是无法确定它 使用任何方法在O(N)中完成此问题的任何帮助都是有用的 (为冗长的帖子道歉) 考虑一个由N个整数组成的零索引数组。此数组的索引是0到N之间的整数−1.取一个索引K。如果A[J]>A[K],则索引J称为K的递增项。注意,如果A[K]是数组A中的最大值,则K没有递增项 如果abs(K),则K的上升点J称为K的最近上升点−J) 是可能的最小值(即,如果J和K之间的距离最小)。注意,K最多可以有两个最近的上升点:一个比K小,一个比K大Optimization 如何使执行时间从O(N^2)变为O(N),optimization,Optimization,我试图在线解决一个编程问题(既不是我的家庭作业,也不是我的任何面试/测试,但可能是一个很好的候选人)。 下面给出了问题。我下面的代码在功能上是正确的,但它的运行时复杂性是O(N2),正如解决方案所期望的那样,应该是O(N) 我尝试了两种其他方法来优化它-1)对数组进行排序,然后尝试是否可以让它工作,但由于排序会导致原始数字的索引丢失,我甚至将它们保留在单独的数组中,并解决了它,但即使是O(N2)。我确信数组的排序将有助于达到O(N),但只是无法确定它 使用任何方法在O(N)中完成此问题的任何帮助
例如,让我们考虑以下数组A:
A[0]=4A[1]=3A[2]=1A[3]=4A[4]=1A[5]=2A[6]=1A[7]=5A[8]=7 如果K=3,那么K有两个上升点:7和8。它最近的上升点是7,K和7之间的距离等于abs(K−7) =4 编写一个函数:struct Results {
int * R;
int N;
};
struct Results array_closest_ascenders(int A[], int N);
给定一个由N个整数组成的零索引数组a,返回一个由N个整数组成的零索引数组R,这样(对于K=0,…,N−1) :
例如,给定以下数组A:
A[0]=4A[1]=3A[2]=1A[3]=4A[4]=1A[5]=2A[6]=1A[7]=5A[8]=7
函数应返回以下数组R:
R[0]=7R[1]=1R[2]=1R[3]=4R[4]=1R[5]=2R[6]=1R[7]=1R[8]=0
数组R应返回为:
a structure Results (in C), or
a vector of integers (in C++), or
a record Results (in Pascal), or
an array of integers (in any other programming language).
假设:
N is an integer within the range [0..50,000];
each element of array A is an integer within the range [−1,000,000,000..1,000,000,000].
复杂性:
expected worst-case time complexity is O(N);
expected worst-case space complexity is O(N), beyond input storage (not counting the storage required for input arguments).
可以修改输入数组的元素
我的解决方案(O(N2)):
#include <math.h>
#include "stdio.h"
#include "stdlib.h"
struct Results
{
int *R;
int N;
};
struct Results array_closest_ascenders ( int A[], int N )
{
struct Results result;
int i,j,asc_found=0;
result.R = (int*)malloc(sizeof(int)*N);
for(i=0;i<N;i++)
result.R[i] = N;
result.N = N;
for(i=0;i<N;i++)
{
asc_found = 0;
for(j=0;j<N;j++)
{
if(A[i] < A[j])
{
//if(result.R[i] == 0)
{
if(result.R[i] > abs(i-j))
{
result.R[i] = abs(i-j);
asc_found = 1;
}
}
}
}
if(asc_found == 0)
result.R[i] = 0;
}
return result;
}
void main()
{
//int A[] = {4, 3, 1, 4, -1, 2, 1, 5, 7};
int A[] = {691446939, -241956306, 485954938, 604054438, 383714185, -656099986, -357341170, -255988102, -139683363, -463281394, -382925609, 712727854};
struct Results tmp;
tmp = array_closest_ascenders(A,sizeof(A)/sizeof(A[0]));
}
#包括
#包括“stdio.h”
#包括“stdlib.h”
结构结果
{
int*R;
int N;
};
结构结果数组\u最近的\u递增项(int A[],int N)
{
结构结果;
inti,j,asc_=0;
结果R=(int*)malloc(sizeof(int)*N);
对于(i=0;i我想将其添加为注释,但没有显示注释链接。R[]是否应该跟随
R[0]=abs(0-7)=7;
R[1]=abs(1-0)=1;
R[2]=abs(2-5)=3;
R[3]=abs(3-7)=4;
R[4]=abs(4-2)=2;/or 4-6
R[5]=abs(5-1)=4;
R[6]=abs(6-5)=1;
R[7]=abs(7-8)=1;
R[8]=abs(8-8)=0;
根据您在下面的评论,这是一个有效的程序。该算法基于计数排序(如上所示)。“偏移量”允许出现“-1”之类的负值
注意:尽管有一个用于填充R[]的嵌套循环,但该算法不是N^2,因为第二个循环在桶的数量上迭代
回答:[7,1,1,4,1,2,1,1,0]
import java.util.ArrayList;
import java.util.Arrays;
public class Ascender {
public static int[] ascenderArray(int[] A) {
int max = A[0], min = A[0];
for (int i : A) {
if (max < i)
max = i;
if (min > i)
min = i;
}
int offset = min < 0 ? -min : 0;
ArrayList<Integer> buckets[] = new ArrayList[max + 1 + offset];
for (int i = 0; i < buckets.length; i++)
buckets[i] = new ArrayList<Integer>();
for (int i = 0; i < A.length; i++)
buckets[A[i] + offset].add(i);
int[] R = new int[A.length];
for (int i = 0; i < R.length; i++) {
try {
min = A.length;
int x = A[i] + 1 + offset;
for (int n = x; n < buckets.length; n++) {
x=n;
while (buckets[x].isEmpty())
x++;
n=x;
int tmp = Math.abs(i - buckets[n].get(0));
if (min > tmp)
min = tmp;
}
R[i] = min==A.length?0:min;
} catch (Exception e) {
R[i] = 0;
}
}
return R;
}//
public static void main(String... args) {
int A[] = { 4, 3, 1, 4, -1, 2, 1, 5, 7 };
int R[] = ascenderArray(A);
System.out.println(Arrays.toString(R));
}
}
import java.util.ArrayList;
导入java.util.array;
公共阶级上升者{
公共静态int[]上行阵列(int[]A){
int max=A[0],min=A[0];
对于(int i:A){
如果(最大值i)
min=i;
}
int offset=min<0?-min:0;
ArrayList bucket[]=新的ArrayList[max+1+偏移];
对于(int i=0;itmp)
min=tmp;
}
R[i]=min==A.length?0:min;
}捕获(例外e){
R[i]=0;
}
}
返回R;
}//
公共静态void main(字符串…参数){
inta[]={4,3,1,4,-1,2,1,5,7};
int R[]=上升线(A);
System.out.println(Arrays.toString(R));
}
}
左最近升序和右最近升序可以分别考虑。我们在数组中遍历一次,计算左最近升序;然后在相反方向上再次计算右最近升序。最近升序是两个升序中的较近者
在下面的algo算法中,只考虑左上升键。索引堆栈跟踪当前元素的左上升键(全部)。最近的上升键始终位于堆栈顶部
for i in 0 .. N
while (!stack.empty) && (A[stack.top] <= A[i])
stack.pop
if stack.empty
then R[i] = 0
else R[i] = i - stack.top
stack.push(i)
0..N中的i的
虽然(!stack.empty)&&(A[stack.top]我不确定是否有一个Ⅹ(N)解决方案,但这里有一个JavaScript中的Ⅹ(N·log N)解决方案:
var A = [4,3,1,4,-1,2,1,5,7],
N = A.length;
// build an array of index:value pairs and sort them in ascending order
var sorted = [];
for (var i=0; i<N; i++) {
sorted.push({index:i, value:A[i]});
}
sorted.sort(function(a, b) { return a.value - b.value; });
// iterate the sorted array in descending order
var ascenders = [],
closest, // closest ascender
curr = sorted[N-1]; // initiate curr with largest item
ascenders[N-1] = 0;
for (var i=N-2; i>=0; i--) {
// compare curr from the previous iteration with the future
// curr of the current iteration
if (sorted[i].value !== curr.value) {
// update closest ascender if their values differ
closest = curr;
}
curr = sorted[i];
ascenders[i] = Math.abs(curr.index-closest.index);
}
// rearrange ascenders in the original order
var ret = [];
for (var i=0; i<N; i++) {
ret[sorted[i].index] = ascenders[i];
}
var A=[4,3,1,4,-1,2,1,5,7],
N=A.长度;
//构建一个索引:值对数组,并按升序排序
var排序=[];
对于(变量i=0;i=0;i--){
//将上一次迭代的curr与将来的curr进行比较
//当前迭代的curr
if(已排序[i].value!==当前值){
//如果它们的值不同,则更新最近的提升器
最近值=当前值;
}
curr=已排序的[i];
升序器[i]=数学绝对值(当前索引最接近的索引);
}
//按原始顺序重新排列升序器
var-ret=[];
对于(var i=0;iimport java.util.array;
导入java.util.TreeMap;
公共类AsenderUtil{
公共静态int[]GetCloseStatSenderInDices(int[]arr,int indx){
if(indx<0 | | arr.length类程序
{
静态void Main(字符串[]参数)
{
int[]A=新的int[]{4,3,1,4,-1,2,1,5,7};
int[]B=新的int[A.长度];
int[]R=新的int[A.长度];
Program obj=新程序();
对象ABC(A、B、R);
}
公共无效ABC(int[]A,int[]B,int[]R)
{
int i,j,m,k
var A = [4,3,1,4,-1,2,1,5,7],
N = A.length;
// build an array of index:value pairs and sort them in ascending order
var sorted = [];
for (var i=0; i<N; i++) {
sorted.push({index:i, value:A[i]});
}
sorted.sort(function(a, b) { return a.value - b.value; });
// iterate the sorted array in descending order
var ascenders = [],
closest, // closest ascender
curr = sorted[N-1]; // initiate curr with largest item
ascenders[N-1] = 0;
for (var i=N-2; i>=0; i--) {
// compare curr from the previous iteration with the future
// curr of the current iteration
if (sorted[i].value !== curr.value) {
// update closest ascender if their values differ
closest = curr;
}
curr = sorted[i];
ascenders[i] = Math.abs(curr.index-closest.index);
}
// rearrange ascenders in the original order
var ret = [];
for (var i=0; i<N; i++) {
ret[sorted[i].index] = ascenders[i];
}
import java.util.Arrays;
import java.util.TreeMap;
public class AsenderUtil {
public static int[] getClosestAsenderIndices(int[] arr, int indx) {
if (indx < 0 || arr.length <= indx)
throw new RuntimeException("wrong input");
int baseVal = arr[indx];
TreeMap<Integer,Integer> ts = new TreeMap<Integer,Integer>();
for(int i=0;i<arr.length;i++){
if(arr[i]>baseVal) {
ts.put(Math.abs(i-indx),i);
}
}
int[] toReturn = new int[2];
toReturn[0] = ts.remove(ts.firstKey());
toReturn[1] = ts.remove(ts.firstKey());
return toReturn;
}
public static void main(String... args) {
int A[] = { 4, 3, 1, 4, -1, 2, 1, 5, 7 };
int R[] = getClosestAsenderIndices(A,3);
System.out.println(Arrays.toString(R));
}
}
class Program
{
static void Main(string[] args)
{
int[] A = new int[] { 4, 3, 1, 4, -1, 2, 1, 5, 7 };
int[] B = new int[A.Length];
int[] R = new int[A.Length];
Program obj = new Program();
obj.ABC(A,B, R);
}
public void ABC(int[] A,int[]B, int[] R)
{
int i, j, m,k;
// int temp = 0;
int n = A.Length - 1;
for (i = 0; i < n; i++)
{
for (j = 0; j <= n; j++)
{
if (A[i] < A[j])
{
m = Math.Abs(j - i);
R[i] = m;
break;
}
}
for (j = i-1; j > 0; j--)
{
if (A[i] < A[j])
{
k = Math.Abs(j - i);
B[i] = k;
break;
}
}
}
for (i = 0; i < n; i++)
{
if (R[i] > B[i] && (B[i] == 0))
{
R[i] = R[i];
//Console.WriteLine(R[i]);
//Console.ReadLine();
}
else { R[i] = B[i]; }
}
}
}
class ArrayClosestAscendent {
public int[] solution(int[] A) {
int i;
int r[] = new int[A.length];
for(i=0;i<A.length;i++){
r[i] = search(A, i);
}
return r;
}
public int search(int[] A, int i) {
int j,k;
j=i+1;
k=i-1;
int result = 0;
if(j <= A.length-1 && (A[j]>A[i]))
return Math.abs(j-i);
j++;
while(k>=0 || j < A.length){
if(k >= 0 && A[k] > A[i]){
return Math.abs(i-k);
}else if(j < A.length && A[j] > A[i]){
return Math.abs(i-j);
}else{
j++;
k--;
}
}
return result;
}
}