1. 程式人生 > >求k個數組包含每個陣列至少一個元素的最小範圍(待字閨中,備忘)

求k個數組包含每個陣列至少一個元素的最小範圍(待字閨中,備忘)

有k個有序的陣列,請找到一個最小的數字範圍。使得這k個有序陣列中,每個陣列都至少有一個數字在該範圍中。

例如:

1: 4, 10, 15, 24, 26

2: 0, 9, 12, 20

3: 5, 18, 22, 30

所得最小範圍為[20,24],其中,20在2中,22在3中,24在1中。

這是待字閨中的一道面試題,就個人經驗來看一般有序陣列的題目都會讓人聯想到有折半查詢來解決,到有序陣列為多個時,一般會聯想到歸併排序的思想,那麼這道題就不例外。

以下引自待字閨中的分析:

那這個題目選擇哪個方法繼續嘗試呢?那我們再分析一下要解決的問題。找到一個最小的範圍,每一個有序陣列中,都至少有一個元素在這個範圍中。找到這樣一個範圍並不難,可是如何確定最小的範圍呢?最終得到的最小的範圍,至少包含三個元素,並且在所有陣列整體的排序中,是相鄰的。假設最小範圍是[a, b, c],a < b < c。 c-a是最小的。並且,a,b,c來自不同的有序陣列。還有一種情況是[a,b,d,c],a,b,c不是緊鄰的,中間有一個d即: a< d < c。這時,d只能是來自b所在的陣列,如下分析:

  1. d來自a所在的陣列,那麼應有更短的範圍c - d

  2. d來自c所在的陣列,那麼應有更短的範圍d - a

  3. d來自b所在的陣列,範圍大小是不變的,就是無論是考慮d,還是考慮b。都沒有影響。

從上面的分析,我們得出,只需要考慮在最終的排序中,考慮鄰近的、並且來自不同有序陣列的元素,作為備選的範圍。那麼該怎麼樣做到只考慮臨近的、並且來自不同的有序陣列的元素呢?這裡就用到了歸併排序的思想。以原題中的例子為例,假設有三個指標指,p1,p2,p3,分別指向三個陣列的第一個元素:

步驟 指標當前值 最大值 最小值 min_range_value 移動指標
1 4,0,5 5 0 5 p2
2 4,9,5 9 4 5 p1
3 10,9,5 10 5 5 p3
4 10,9,18 18 9 9 p2
5 10,12,18 18 10 8 p1
6 15,12,18 18 12 6 p2
7 15,20,18 20 15 5 p1
8 24,20,18 24 18 6 p3
9 24,20,22 24 20 4 p2
end

結束是因為第二個陣列已經沒有元素可以再進行遍歷了。最終得到最小的min_range_value為4,即為題目例子的答案。

上面這個方法,通過歸併排序的思想,確保每次都是k個來自不同的陣列的元素進行比較,得到最大值、最小值。就可以得到一個範圍,包含了所有陣列中的數字。

這個題的著名變種是從網頁中產生包含所有查詢詞的最小的摘要。如果你 面過Google,你應該聽說過這題。

個人的理解:

其實就是利用歸併的思想,三個陣列或更多個數組做歸併排序,排在最小的元素向前移動,計算最大最小元素之間的間隔,這樣當一個數組用盡的時候,記錄的最小間隔即為所求。

/*************************************************************************
        > File Name: mindiff.c
        > Author: desionwang
        > Mail: [email protected] 
        > Created Time: Wed 23 Oct 2013 02:57:44 PM CST
 ************************************************************************/


#include<stdio.h>


int mindiff(int a[], int size_a, int b[], int size_b, int c[], int size_c){
        int i = 0, j = 0 ,k = 0;
        int minnum;
        int mindiff = 65535;
        if(a == NULL || b == NULL || c == NULL){
                return -1;
        }
        if(size_a <= 0 || size_b <= 0 || size_c <= 0){
                return -1;
        }
        int max, min, diff;
        int index;
        while(i < size_a && j < size_b && k < size_c){
                printf("a:%d\tb:%d\tc:%d\n", a[i], b[j], c[k]);
                if(a[i] >= b[j]){
                        if(a[i] >= c[k]){
                                max = a[i];
                        }else{
                                max = c[k];
                        }
                        if(b[j] <= c[k]){
                                min = b[j];
                                index = j;
                                j++;
                        }else{
                                min = c[k];
                                index = k;
                                k++;
                        }
                }else{
                        if(b[j] >= c[k]){
                                max = b[j];
                        }else{
                                max = c[k];
                        }
                        if(a[i] <= c[k]){
                                min = a[i];
                                index = k;
                                i++;
                        }else{
                                min = c[k];
                                index = i;
                                k++;
                        }
                }


                printf("max:%d\tmin:%d\n", max, min);
                //printf("a:%d\tb:%d\tc:%d\n", a[i], b[j], c[k]);
                diff = max - min;
                if(diff < mindiff){
                        mindiff = diff;
                }
        }
        //printf("a:%d\tb:%d\tc:%d\n", a[i], b[j--], c[k]);
        printf("mindiff:%d\n", mindiff);
        return mindiff;


}


int main(){
        int a[5] = {4, 10, 15, 24, 26};
        int b[] = {0, 9, 12, 20};
        int c[] = {5, 18, 22, 30};
        mindiff(a, 5, b, 4, c , 4);
}


相關推薦

k個數包含每個陣列至少一個元素範圍待字閨中

有k個有序的陣列,請找到一個最小的數字範圍。使得這k個有序陣列中,每個陣列都至少有一個數字在該範圍中。 例如: 1: 4, 10, 15, 24, 26 2: 0, 9, 12, 20 3: 5, 18, 22, 30 所得最小範圍為[20,24],其中,2

個數中右邊第一個比他大的數單調棧

題意思路如標題 int main() { int n; cin >> n; int a[MAXN]; for (int i = 0; i < n; ++i) { cin >> a[i];

旋轉數數字C++ 和 Python 實現

ram 兩個 requires images red 輸入 off internet iat (說明:本博客中的題目、題目詳細說明及參考代碼均摘自 “何海濤《劍指Offer:名企面試官精講典型編程題》2012年”) 題目   把一個數組最開始的若幹個元素搬到數組的末尾,我們

個數中第k大的數要求不能另外申請空間陣列順序不能被改變

這是一道今日頭條的面試題,當面試官提出這樣一道題目時。我想相信,大多數人都會這樣反應 1.是不是可以先排一下序,然後再求第k大的,然後就想到陣列順序不能被改變,然後否定了 2.是不是可以用小堆來做。我建立一個堆大小為k的小堆,然後把這些資料全部扔進小堆中,除了堆頂,其他的數

繼續對上一頁的ecah進行 優化個數的和大值獲取陣列中的元素3

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style t

個數k個數java

問題描述:求一個數組的最大k個數,如,{1,5,8,9,11,2,3}的最大三個數應該是,8,9,11 問題分析:     1.解法一:最直觀的做法是將陣列從大到小排序,然後選出其中最大的K個數,但是這樣的解法,複雜度是O(logn*n),但是有時候並不需要排序,用簡單的選

演算法12--topK個數中第k大的數

求一個數組中第k大的值 解法一: 建立一個k個元素的最大堆,首先將陣列中前k個元素放入堆中,此時堆頂元素為第k大的元素,後面繼續遍歷陣列,比較堆頂元素與陣列中元素值,當陣列中元素小於堆頂元素時,將堆頂元素彈出,新元素入堆,這樣最終堆頂元素即為第k大。 可以直接利用Jav

個數裡連續子陣列大和的幾個演算法

注意:這裡的陣列元素,有可能全為負。這樣,所謂的: int find_max_array(const vector<int> &a) { int max_sum = 0; int this_sum = 0; fo

個數K個數字

用快排思想:import java.util.ArrayList; import java.util.Arrays; import java.util.Scanner; class Solution

紅書2017年筆試】個數中平均數大的子陣列

 題目:   * 給一個數組,裡邊有N個整數,找長度為K(0<K<N)且平均值最大的子陣列,並把這個最大值輸出來 輸入描述:* 6 (N的值)* 1 12 -5 -6 50 3 (含有N個整數的陣列)* 4 (K的值) 輸出描述: * 12.75 題目很簡單,時

個數的和大的連續子陣列及擴充套件

在C++中a=1與a(1)有什麼區別?a=1是賦值,a(1)是一個函式值 求1億內的素數,並輸出。 #include<stdio.h> #include<math.h> const long N = 10000001; bool prime[1000

Java—個數的所有子陣列

最近在忙秋招,投了各種公司,參加了各種線上筆試,在線上筆試的過程中,經常遇到一些題目,想要求得最終結果的話需要獲取某一陣列的所有子集(暴力破解)。 import java.util.ArrayLi

算法 - 個數長遞減子序列C++

str log bst article subst else from return ear //************************************************************************************

【單調棧】個數第一個比他的數的位置

type 技術分享 bit esp alt log lap while play 【AC】 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int

leetcode-350-Intersection of Two Arrays II個數的交集

CA 更新 lse write limited elements 表示 app 順序 題目描述: Given two arrays, write a function to compute their intersection. Example:Given nums1 =

O(n)個數中連續區間和的大值

return 區間 scan CI spa 最大 %d 區間和 數組 int n, a[5000]; int main(){ scanf("%d", &n); for (int i = 1; i <= n; i++)cin >>

個數大值與

div return urn 技術 code include 一個 最小值 array #include <stdio.h> int main() { int array[10]={100,1,40,29,45,22,98,2,83,75};

演算法 個數長遞減子序列 C

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

java二分法來個數一個值的key

package TestArray;import java.util.Arrays;/** * 二分法查詢 */public class Test { public static void main(String[] args) { int[] arr = {30, 20, 50, 10,

通過一個數找到每個元素對應出現的次數

var arrayObj = ['a','b','b','a','d','g']; function countData(arrayObj){         var arrayNew = new Array(); &nbs