01 如何求數對之差的最大值
方法一:蠻力法
首先遍歷數組,找到所有可能的差值,其次從所有差值中找出最大值。
public static int getMax(int[] a){
int n=a.length;
int max=Integer.MIN_VALUE;
for (int i=0;i<n;i++){
for (int j=i+1;j<n;j++){
if (a[i]-a[j]>max)
max=a[i]-a[j];
}
}
return max;
}
public static void main(String[] args) {
int a[]={1,2,3,4,0,6,7,8,9};
System.out.println(getMax(a));
}
方法二:二分法
把數組分爲兩個子數組,那麼最大的差值只能有3種可能:
1.最大的差值對應的被減數和減數都在左子數組中,假設最大的差值爲leftMax
2.被減數和減數都在右子數組中,假設最大差值爲rightMax
3.被減數是右子數組中最小值,假設差值爲minMax。
public static int getMax1(int a[]){
if (a==null)
return Integer.MAX_VALUE;
int len=a.length;
if (len<1)
return Integer.MIN_VALUE;
AtomicInteger max = new AtomicInteger(0);
AtomicInteger min = new AtomicInteger(0);
return getMaxDiff(a,0,len-1,max,min);
}
private static int getMaxDiff(int[] a, int begin, int end, AtomicInteger max, AtomicInteger min) {
if (begin==end){
max.set(a[begin]);
min.set(a[begin]);
return Integer.MIN_VALUE;
}
int middle=begin+(end-begin)/2;
//數組前半部分的最小值與最大值
AtomicInteger lMax = new AtomicInteger(0);
AtomicInteger lMin = new AtomicInteger(0);
//數組前半部分的最大差值(第一種情況)
int leftMax=getMaxDiff(a,begin,middle,lMax,lMin);
//數組前半部分的最小值與最大值
AtomicInteger rMax=new AtomicInteger(0);
AtomicInteger rMin =new AtomicInteger(0);
//數組後半部分的最大差值(第二種情況)
int rightMax=getMaxDiff(a,middle+1,end,rMax,rMin);
//對應第三種情況
int minMax=lMax.get()-rMin.get();
//求數組的最大值和最小值
if (lMax.get()>rMax.get())
max.set(lMax.get());
else
max.set(rMax.get());
if (lMin.get()<rMin.get())
min.set(lMin.get());
else
min.set(rMin.get());
//求最大的差值
int allMax =(leftMax>rightMax)?leftMax:rightMax;
allMax=(allMax>minMax)?allMax:minMax;
return allMax;
}
public static void main(String[] args) {
int a[]={1,2,3,4,0,6,7,8,9};
System.out.println(getMax1(a));
}
方法三:動態規劃
public static int max(int m,int n){
return (m>n)?m:n;
}
public static int getMax2(int a[]){
if (a==null)
return Integer.MAX_VALUE;
int len=a.length;
if (len<=1)
return Integer.MIN_VALUE;
int[] diff=new int[len];
int[] max=new int[len];
diff[0]=Integer.MIN_VALUE;
max[0]=a[0];
for (int i=1;i<len;i++){
diff[i]=max(diff[i-1],max[i-1]-a[i]);
max[i]=max(max[i-1],a[i]);
}
return diff[len-1];
}
public static void main(String[] args) {
int a[]={1,2,3,4,0,6,7,8,9};
System.out.println(getMax2(a));
}
動態規劃優化
public static int getMax3(int a[]){
if (a==null)
return Integer.MIN_VALUE;
int len=a.length;
if (len<=1)
return Integer.MIN_VALUE;
int diff=0;
int max=0;
for (int i=1;i<len;i++){
diff=max(diff,max-a[i]);
max=max(max,a[i]);
}
return diff;
}
public static void main(String[] args) {
int a[]={1,2,3,4,0,6,7,8,9};
System.out.println(getMax3(a));
}
02 如何求絕對值最小的數
問題描述:有一個升序排列的數組,數組中可能有正數、負數、0,求數組中元素的絕對值最小的數。例如:數組{-10,-5,-2,7,15,20}
二分法:
public static int getMinAbsoluteValue(int []a){
if (a==null)
return Integer.MIN_VALUE;
int len =a.length;
if (len<1)
return Integer.MIN_VALUE;
//數組中沒有負數
if (a[0]>0)
return a[0];
//數組中沒有正數
if (a[len-1]<0)
return a[len-1];
int mid=0;
int begin=0;
int end=len-1;
int absMin=0;
//數組中既有正數又有負數
while (true){
mid=begin+(end-begin)/2;
//如果值等於0,那麼就是絕對值最小的數
if (a[mid]==0)
return 0;
//如果值大於0,那麼正負數的分界點在左半部分
else if (a[mid]>0){
//繼續在數組的左半部分查找
if (a[mid-1]>0){
end=mid-1;
}else if (a[mid-1]==0)
return 0;
//找到正負的分界點
else
break;
}//如果值小於0,那麼正負數的分界點在右半部分
else{
//在數組的右半邊查找
if (a[mid+1]<0)
begin=mid+1;
else if (a[mid+1]==0)
return 0;
else
break;
}
}
//已獲得正負分界點,找出最小絕對值
if (a[mid]>0){
if (a[mid]<Math.abs(a[mid-1]))
absMin=a[mid];
else
absMin=a[mid-1];
}else{
if (Math.abs(a[mid])>a[mid+1])
absMin=a[mid+1];
else
absMin=a[mid];
}
return absMin;
}
public static void main(String[] args) {
int a1[]={-5,-4,-3,-2,-1,3,6,9};
int a2[]={2,3,4,7,9};
int a3[]={-15,-12,-10,-8,-6,-3};
System.out.println(getMinAbsoluteValue(a1));
System.out.println(getMinAbsoluteValue(a2));
System.out.println(getMinAbsoluteValue(a3));
}
03 如何求數組中兩個元素的最小距離
問題描述:給定一個數組,數組中含有重複元素,給出兩個數n1和n2,求這兩個數字在數組中搜出現位置的最小距離。例如:數組{4,5,6,4,7,8,4,2,3,4,5,4,6,9}中,4和8的最小距離爲1
定義一個變量min_dist記錄n1和n2的最小距離,在以上兩種情況下,每次求出n1和n2的距離後與min_dist相比,求最小值。時間複雜度O(n)
private static int min(int a,int b){
return (a>b)?b:a;
}
public static int getMinDistance(int a[],int n1,int n2){
if (a==null)
return Integer.MIN_VALUE;
int len=a.length;
int n1_index=-1;
int n2_index=-1;
int min_dist=Integer.MIN_VALUE+1;
for (int i=0;i<len;i++){
if (a[i]==n1){
n1_index=i;
if (n2_index>=0)
min_dist=min(Math.abs(min_dist),Math.abs(n1_index-n2_index));
}
if (a[i]==n2){
n2_index=i;
if (n1_index>=0)
min_dist=min(Math.abs(min_dist),Math.abs(n2_index-n1_index));
}
}
return min_dist;
}
public static void main(String[] args) {
int a[]={4,5,6,4,7,8,4,2,3,4,5,4,6,9};
System.out.println(getMinDistance(a,4,8));
}
04 如何求指定數字在數組中第一次出現的位置
問題描述:給定數組{4,5,6,5,4,3,2,1,2,3,4,5,6,7,8,9},這個數組中相鄰元素之差都爲1,給定數字9,它在數組中第一次出現的位置下標爲13。
跳躍搜索法:
public static int getFindIndex(int a[],int t){
if (a==null)
return Integer.MIN_VALUE;
int len=a.length;
int i=0;
while (i<len){
if (a[i]==t)
return i;
else
i+=Math.abs(t-a[i]);
}
return -1;
}
public static void main(String[] args) {
int a[]={4,5,6,5,4,3,2,1,2,3,4,5,6,7,8,9};
System.out.println(getFindIndex(a,7));
}
05 如何對數組的兩個子有序段進行合併
public static void getFindRightPlaceForMid(int []a,int mid){
int len=a.length;
int tmp;
for (int i=mid;i<len-1;i++){
if (a[i+1]<a[i]){
tmp=a[i];
a[i]=a[i+1];
a[i+1]=tmp;
}
}
}
public static void sort (int a[],int mid){
int tmp;
for (int i=0;i<mid;i++){
if (a[mid]<a[i]){
tmp=a[i];
a[i]=a[mid];
a[mid]=tmp;
getFindRightPlaceForMid(a,mid);
}
}
}
public static void main(String[] args) {
int a[]={1,3,5,7,9,2,4,6,8};
int mid=5;
sort(a,5);
System.out.println(Arrays.toString(a));
}