題目描述:輸入n個整數,找出其中最小的k個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4.
題目分析:這道題最簡單的思路莫過於把n個整數排序,然後最前面的k個數就是最小的k個數,但是時間複雜度是o(nlogn)。我們應該想一想有沒有更快的方法。
解法一:o(n)的演算法,只有當可以修改輸入的陣列時可用。
基於快排裡的partition函式,基於陣列中的第k個數來調整,使得比第k個數小的都在左邊,比第k個數大的都在右邊。在隨機快速排序演算法中,我們先在陣列中隨機選擇乙個數字,然後調整陣列中數字的順序, 使得比選中的數字小的數字都排在它的左邊,比選中的數字大的數字都排在它的右邊。如果這個選中的數字的下標剛好是k,那麼這個數字之前的數字正好是最小的k個數。否則就遞迴尋找。
//最小的k個數
//快排partition函式
public
static
int partition(int numbers, int start, int end)
numbers[start] = numbers[end];
while (start < end && numbers[start] <= temp)
numbers[end] = numbers[start];
}numbers[start] = temp;
return start;
}//第一種方法
public
static
void getmink(int input, int output)
int start = 0;
int end = input.length - 1;
int k = output.length;
intindex = partition(input, start, end);
while (index != k) else
index = partition(input,start,end);
}system.arraycopy(input, 0, output, 0, output.length);
}
方法二:o(nlogk)的演算法,特別適合處理海量資料
我們可以先建立乙個大小為k的容器,然後依次讀入那n個數字,直到填滿容器,然後再讀入的數字就跟容器中的最大值做比較,如果大於最大值,則拋棄不用,繼續讀取下乙個數字,如果小於容器中最大值,就把它跟最大值替換。當n個數字讀完後,容器中就是最小的k個數。
容器填滿後,需要完成三個工作,乙個是從容器中找到最大值,二是有可能需要刪除最大值,三是有可能插入乙個新的數字。如果用二叉樹來實現這個容器,就能在o(logk)時間內完成。
//第二種方法
public
static treesetgetmink(int arr, int k)
treesettreeset = new treeset<>();
for (int i = 0; i < arr.length; i++) else}}
return treeset;
}
劍指offer 面試題30 最小的K個數
題目 輸入n個數,找出其中最小的k個數。例如輸入4 5 1 6 2 7 3 8這8個數字,則最小的4個數字是1,2,3,4。思路 這道題目是典型的top k問題。兩種方法 1 如果允許改變量列,半快速排序,是基準值正好為第k個數,那麼基準值左邊的都是小於它的,即可得到最小的k個數 求最大的過程類似 ...
劍指Offer 面試題30 最小的k個數
題目 輸入n個整數,找出其中最小的k個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4,思路 1 首先,使用快排中的思路 每進行一次快排,會確定乙個位置上的數字,使得該位置前的數字都小於該數字,而該位置後的數字都大於該數字。2 所以,要找最小的k個數,即某一次快...
《劍指offer》面試題30 最小的k 個數
劍指offer 面試題30 最小的k 個數 1.題目描述 輸入n個整數,找出其中最小的k個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4,2.解題思路 1。全排序。時間複雜度o nlogn 2。partiton思想 用快速排序,時間複雜度o n 3。最大堆 時...