假设有一个数组,找出元素较小的元素和元素较大的元素。否则返回-1。我知道如何在O(n ^ 2)中做到这一点。但是如何在O(n)中完成呢?
O(n ^ 2)的代码:
#include <iostream>
using namespace std;
int main(){
int array[] = {5, 1, 4, 3, 2, 8, 10, 7, 9};
int sizeOfArray = sizeof(array)/sizeof(array[0]);
for (int i = 1; i < sizeOfArray-1; ++i) {
int j = i-1;
int k = i+1;
while(array[j] < array[i] && array[k] > array[i]){
if(j == 0 && k == sizeOfArray-1){
cout << array[i];
return 0;
}
if(j>0){
j--;
}
if(k<sizeOfArray){
k++;
}
}
}
cout << -1;
return 0;
}
答案 0 :(得分:0)
1)从左到右扫描数组,记住到目前为止最大的值;
2)从右到左扫描数组,记住目前为止的最小值。
3)扫描两个新阵列,直到找到最大值不超过最小值。
示例:
3 6 4 5 9 8 7
3 6 6 6 9 9 9
3 4 4 5 7 7 7
没有解决方案。
3 2 4 6 9 8 7
3 3 4 6 9 9 9
2 2 4 6 7 7 7
^ ^
有两种解决方案。
实际上,两次扫描就足够了。
答案 1 :(得分:0)
// example with n2 complexity.
class Elementwithleftsidesmallerandrightsidegreater {
static void find(int[] arr) {
for (int i = 1; i < arr.length; i++) {
int head = arr[i];
int left = i - 1;
int right = i + 1;
while (left >= 0 && arr[left] < head) {
left--;
}
while (right < arr.length && arr[right] > head) {
right++;
}
if (left == -1 && right == arr.length) {
System.out.println("index is " + i);
System.out.println("value is " + arr[i]);
}
}
}
public static void main(String[] args) {
int arr[] = new int[] { 2, 1, 1, 3, 111, 80, 100, 79, 19 };
find(arr);
}
}
答案 2 :(得分:0)
这是O(3n)= O(n)的实现:
private static int findPivot(int[] a) {
int length = a.length;
int[] leftMax = new int[length];
int[] rightMin = new int[length];
leftMax[0] = a[0];
for(int i=1; i<length; i++) {
leftMax[i] = leftMax[i-1]>a[i]?leftMax[i-1]:a[i];
}
rightMin[length -1] = a[length-1];
for(int i=length-2; i>0; i--) {
rightMin[i] = rightMin[i+1]<a[i]?rightMin[i+1]:a[i];
}
int position = -1;
for(int i=1; i<length-1; i++) {
if(leftMax[i-1] < rightMin[i+1]) {
position = i;
break;
}
}
return position;
}
以下是运行结果:
Initial array: [5, -1, 3, 8, 6, 10]
Partitions: [5, -1] 3 [8, 6, 10]
Initial array: [5, 5, -2, -3, 0, 3, 8, 6, 10]
Partitions: [5, 5, -2, -3, 0] 3 [8, 6, 10]
Initial array: [3, -2, -2, -3, 0, 7, 2, 8, 6, 10]
Partitions: [3, -2, -2, -3, 0, 7, 2, 8] 6 [10]
这是如何以这种方式打印它:
public static void main(String[] args) {
int[] a = { 5, -1, 3, 8, 6, 10 };
int pivot = findPivot(a);
if (pivot != -1) {
printPartitions(pivot, a);
}
int[] b = { 5, 5, -2, -3, 0, 3, 8, 6, 10 };
int pivot1 = findPivot(b);
if (pivot1 != -1) {
printPartitions(pivot1, b);
}
int[] c = { 3, -2, -2, -3, 0, 7, 2, 8, 6, 10 };
int pivot2 = findPivot(c);
if (pivot2 != -1) {
printPartitions(pivot2, c);
}
}
private static void printPartitions(int pivot, int[] a) {
System.out.println("Initial array:\t" + Arrays.toString(a));
System.out.println("Partitions:\t" + Arrays.toString(Arrays.copyOfRange(a, 0, pivot)) + " " + a[pivot] + " "
+ Arrays.toString(Arrays.copyOfRange(a, pivot + 1, a.length)));
}
答案 3 :(得分:-1)
这是O(n):
我已经用JavaScript上的代码替换了我的算法描述,所以你可以简单地运行它,看看那里发生了什么。这段代码可以很容易地转换为C ++。
var arrayItems = [1, 3, 2, 3, 4, 6, 4, 7, 9, 10, 8];
var sizeOfArray = arrayItems.length;
var maxValue = arrayItems[0];
var pointValue = maxValue;
var elIndex = -1;
for (var index = 0; index < sizeOfArray; index++) {
var set = false;
// Check set of new point value
if (-1 === elIndex && arrayItems[index] > maxValue) {
pointValue = arrayItems[index];
elIndex = index;
set = true;
}
// Update max value
if (arrayItems[index] > maxValue) {
maxValue = arrayItems[index];
}
// Reset point value
if (!set && -1 !== elIndex && arrayItems[index] <= pointValue) {
pointValue = maxValue;
elIndex = -1;
}
console.log([arrayItems[index], maxValue, pointValue, elIndex, index]);
}
console.log(elIndex);
当循环结束时,您将获得elIndex
中的值:
arrayItems: 1 3 2 3 4 6 4 7 9 10 8
maxValue: 1 3 3 3 4 6 6 7 9 10 10
pointValue: 1 3 3 3 4 4 6 7 7 7 7
elIndex: -1 1 -1 -1 4 4 -1 7 7 7 7
index: 0 1 2 3 4 5 6 7 8 9 10