一、問題描述
有一個整數數組,請求出兩兩之差絕對值最小的值,記住,只要得出最小值即可,不需要求出是哪兩個數。
進一步思考:如果需要記錄是哪兩個數呢?
數組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<<")";
}