一、问题描述
有一个整数数组,请求出两两之差绝对值最小的值,记住,只要得出最小值即可,不需要求出是哪两个数。
进一步思考:如果需要记录是哪两个数呢?
数组A[n]
二、解题思路
1、暴力穷举法:n个数两两做差,取最小值。
2、先用快排将数组A排序,再两两做差,取最小值。
3、利用辅助数组B[n-1]
……
所以任意A中任意两个数之差,可以表示为B数组中子序列相加。例如
。时间复杂度三、代码实现。
1、穷举法 略 (若要记录两个数的索引值,只需要在遍历的时候记录取最小值时的i,j即可)
2、先用快排,再两两做差.。(这个方法要记录两个数的索引值比较麻烦。)
#include<iostream>
#include<algorithm>
#include<limits.h>
using namespace std;
int main(){
int arr[]={1,5,3};
int n=sizeof(arr)/sizeof(arr[0]);
sort(arr,arr+3);
for(int i=0;i<n;i++){
cout<<arr[i];
}
int min=INT_MAX;
for(int i=1;i<n;i++)
{
if(arr[i]-arr[i-1]<min)
min=arr[i]-arr[i-1];
}
cout<<endl<<"×îС²î"<<min;
}
输入:[1,5,3]
3、辅助数组法
先构造辅助数组b[n-1] 时间复杂度
在使用动态规划思想求b[n-1]中最小绝对值子序列
创建dp[i][j]表示从
到所有元素相加的和。初始化:dp[i][i]=b[i]
递推公式:dp[i][j]=dp[i][j-1]+b[j]
代码如下:
#include<iostream>
#include<algorithm>
#include<limits.h>
#include<algorithm>
using namespace std;
int dp[10000+10][10000+10];
int main(){
int arr[]={1,7,6,12,8,0};
int n=sizeof(arr)/sizeof(arr[0]);
int b[n-1];
for(int i=0;i<n-1;i++)
{
b[i]=arr[i]-arr[i+1];
}
//初始化dp[i][i]=b[i],
int min=INT_MAX;
for(int i=0;i<n-1;i++){
dp[i][i]=b[i];
}
int pos1=0,pos2=1;//记录绝对值最小的两个数的索引
//dp[0][1]=b[0]+b[1];
//dp[i][j] 从bi到bj所有元素相加的和
//递推公式 dp[i][j]=dp[i][j-1]+b[j]
for(int i=0;i<n-1;i++)
{
for(int j=i;j<n-1;j++){
dp[i][j]=dp[i][j-1]+b[j];
if(abs(dp[i][j])<min)
{
min=dp[i][j];
pos1=i;
pos2=j+1;
}
}
}
for(int i=0;i<n-1;i++)
{
for(int j=i;j<n-1;j++)
cout<<"dp("<<i<<","<<j<<")"<<"="<<dp[i][j]<<" ";
cout<<endl;
}
cout<<"整数数组中两两之差绝对值最小"<<min<<" 索引值"<<"("<<pos1<<","<<pos2<<")";
}
这里我用pos1,pos2变量记录了最相近两数的索引值
输入:[1,7,6,12,8,0]
四、类似题。(我也不确定类不类似)
输入数组A[n]。输出n-1行,第i行输出,A[i]之前的数中,与A[i]最接近的数的索引值和两者的差的绝对值。
只写了暴力法解决的:
#include<iostream>
#include<algorithm>
#include<limits.h>
#include<algorithm>
using namespace std;
int dp[10000+10][10000+10];
int main(){
int arr[]={1,7,6,12,8,0};
int n=sizeof(arr)/sizeof(arr[0]);
int b[n-1];
for(int i=0;i<n-1;i++)
{
b[i]=arr[i]-arr[i+1];
}
//初始化dp[i][i]=b[i],
int min=INT_MAX;
for(int i=0;i<n-1;i++){
dp[i][i]=b[i];
}
int pos1=0,pos2=1;//记录绝对值最小的两个数的索引
//dp[0][1]=b[0]+b[1];
//dp[i][j] 从bi到bj所有元素相加的和
//递推公式 dp[i][j]=dp[i][j-1]+b[j]
for(int i=1;i<n-1;i++)
{
for(int j=i;j<n-1;j++){
dp[i][j]=dp[i][j-1]+b[j];
if(abs(dp[i][j])<min)
{
min=dp[i][j];
pos1=i;
pos2=j+1;
}
}
}
for(int i=0;i<n-1;i++)
{
for(int j=i;j<n-1;j++)
cout<<"dp("<<i<<","<<j<<")"<<"="<<dp[i][j]<<" ";
cout<<endl;
}
cout<<"整数数组中两两之差绝对值最小"<<min<<" 索引值"<<"("<<pos1<<","<<pos2<<")";
}
来源:CSDN
作者:LYROOO
链接:https://blog.csdn.net/LYROOO/article/details/88550921