使用常数空间在线性时间内排序大小为 3 的子序列
给定一个数组,任务是找到该数组的三个元素,使它们处于排序形式,即对于任何三个元素 a[i]、a[j] 和 a[k],它们遵循以下关系: a[i] < a[j] < a[k]其中i < j < k 。这个问题必须使用恒定空间或不使用额外空间来解决。
这个问题已经在线性时间使用线性空间解决了: Find a sorted subsequence of size 3 in Linear Time
例子:
Input: arr[] = {12, 11, 10, 5, 2, 6, 30}
Output: 5 6 30
or 2 6 30
Explanation: Answer is 5, 6, 30 because 5 < 6 < 30
and they occur in this sequence in the array.
Input: arr[] = {5, 7, 4, 8}
Output: 5 7 8
Explanation: Answer is 5 ,7 ,8 because 5 < 7 < 8
and they occur in the same sequence in the array
解决方案:目标是找到三个元素a、b和 c ,使得a < b < c ,并且这些元素必须在数组中以相同的顺序出现。
方法:问题涉及找到三个元素 a、b、c,其中 a < b < c 并且它们必须以与数组中相同的顺序出现。因此,任何步骤的直觉都必须如此。其中一个变量(small)应该存储数组的最小元素,并且当(small)变量中已经存在较小的值时,将为第二个变量large分配一个值。这将导致形成一对两个变量,它们将形成所需序列的前两个元素。类似地,如果在前两个变量已经赋值并且具有比当前元素小的值的数组中可以找到另一个值,则对第三个值的搜索将完成。这完成了三元组 a、b 和 c,使得 a < b < c,以与数组类似的顺序。
算法
- 创建三个变量, small——存储最小元素, large——存储序列的第二个元素, i——循环计数器
- 从开始到结束沿着输入数组移动。
- 如果当前元素小于或等于变量small ,则更新变量。
- 否则,如果当前元素小于或等于变量large ,则更新变量。所以在这里我们在这个瞬间得到一对(小,大) ,其中小<大,它们以所需的顺序出现。
- 否则,如果前两种情况不匹配,则中断循环,因为我们有一对当前元素大于变量small和large 。将索引存储在变量i中。
- 如果没有遇到 break 语句,则保证不存在这样的三元组。
- 否则,有一个三元组满足标准,但变量small可能已更新为新的较小值。
- 所以从开始遍历数组到索引i。
- 将变量small重新分配给任何小于large的元素,保证存在一个。
- 打印值small 、 large和第 i 个数组元素
执行
C++
// C/C++ program to find a sorted sub-sequence of
// size 3 using constant space
#include
using namespace std;
// A function to fund a sorted sub-sequence of size 3
void find3Numbers(int arr[], int n)
{
// Initializing small and large(second smaller)
// by INT_MAX
int small = INT_MAX, large = INT_MAX;
int i;
for (i = 0; i < n; i++)
{
// Update small for smallest value of array
if (arr[i] <= small)
small = arr[i];
// Update large for second smallest value of
// array after occurrence of small
else if (arr[i] <= large)
large = arr[i];
// If we reach here, we found 3 numbers in
// increasing order : small, large and arr[i]
else
break;
}
if (i == n)
{
printf("No such triplet found");
return;
}
// last and second last will be same, but first
// element can be updated retrieving first element
// by looping upto i
for (int j = 0; j <= i; j++)
{
if (arr[j] < large)
{
small = arr[j];
break;
}
}
printf("%d %d %d", small, large, arr[i]);
return;
}
// Driver program to test above function
int main()
{
int arr[] = {5, 7, 4, 8};
int n = sizeof(arr)/sizeof(arr[0]);
find3Numbers(arr, n);
return 0;
}
Java
// Java program to find a sorted subsequence of
// size 3 using constant space
class GFG
{
// A function to fund a sorted subsequence of size 3
static void find3Numbers(int arr[], int n)
{
// Initializing small and large(second smaller)
// by INT_MAX
int small = +2147483647, large = +2147483647;
int i;
for (i = 0; i < n; i++)
{
// Update small for smallest value of array
if (arr[i] <= small)
small = arr[i];
// Update large for second smallest value of
// array after occurrence of small
else if (arr[i] <= large)
large = arr[i];
// If we reach here, we found 3 numbers in
// increasing order : small, large and arr[i]
else
break;
}
if (i == n)
{
System.out.print("No such triplet found");
return;
}
// last and second last will be same, but first
// element can be updated retrieving first element
// by looping upto i
for (int j = 0; j <= i; j++)
{
if (arr[j] < large)
{
small = arr[j];
break;
}
}
System.out.print(small+" "+large+" "+arr[i]);
return;
}
// Driver program
public static void main(String arg[])
{
int arr[] = {5, 7, 4, 8};
int n = arr.length;
find3Numbers(arr, n);
}
}
// This code is contributed by Anant Agarwal.
Python3
# Python3 program to find a sorted subsequence
# of size 3 using constant space
# Function to fund a sorted subsequence of size 3
def find3Numbers(arr, n):
# Initializing small and large(second smaller)
# by INT_MAX
small = +2147483647
large = +2147483647
for i in range(n):
# Update small for smallest value of array
if (arr[i] <= small):
small = arr[i]
# Update large for second smallest value of
# array after occurrence of small
elif (arr[i] <= large):
large = arr[i]
# If we reach here, we found 3 numbers in
# increasing order : small, large and arr[i]
else:
break
if (i == n):
print("No such triplet found")
return
# last and second last will be same, but
# first element can be updated retrieving
# first element by looping upto i
for j in range(i + 1):
if (arr[j] < large):
small = arr[j]
break
print(small," ",large," ",arr[i])
return
# Driver program
arr= [5, 7, 4, 8]
n = len(arr)
find3Numbers(arr, n)
# This code is contributed by Anant Agarwal.
C#
// C# program to find a sorted sub-sequence of
// size 3 using constant space
using System;
class GFG {
// A function to fund a sorted sub-sequence
// of size 3
static void find3Numbers(int []arr, int n)
{
// Initializing small and large(second smaller)
// by INT_MAX
int small = +2147483647, large = +2147483647;
int i;
for (i = 0; i < n; i++)
{
// Update small for smallest value of array
if (arr[i] <= small)
small = arr[i];
// Update large for second smallest value of
// array after occurrence of small
else if (arr[i] <= large)
large = arr[i];
// If we reach here, we found 3 numbers in
// increasing order : small, large and arr[i]
else
break;
}
if (i == n)
{
Console.Write("No such triplet found");
return;
}
// last and second last will be same, but first
// element can be updated retrieving first element
// by looping upto i
for (int j = 0; j <= i; j++)
{
if (arr[j] < large)
{
small = arr[j];
break;
}
}
Console.Write(small + " " + large + " " + arr[i]);
return;
}
// Driver program
public static void Main()
{
int []arr = {5, 7, 4, 8};
int n = arr.Length;
find3Numbers(arr, n);
}
}
// This code is contributed by nitin mittal
PHP
Javascript
输出:
5 7 8
复杂性分析:
- 时间复杂度: O(n)。
由于数组仅被遍历两次,时间复杂度为O(2*n) ,等于O(n) 。
- 空间复杂度: O(1)。
由于只存储了三个元素,空间复杂度是常数或O(1) 。