2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
भूमिका: अयं लेखः द्रुतक्रमण-अल्गोरिदमस्य प्रारम्भिक-शिक्षणस्य विषये केषाञ्चन संशयानां विस्तृत-उत्तराणि प्रददाति, तथा च मूलभूत-द्रुत-क्रमण-अल्गोरिदम् इत्यस्य अनुकूलितं संस्करणं प्रददाति
द्रुतक्रमण-अल्गोरिदम् इत्यस्य मूलं अस्ति分治思想
,विभाजनं विजयं च रणनीतिः निम्नलिखितत्रयेषु ,पदेषु विभक्तः अस्ति:
द्रुतक्रमण-अल्गोरिदम्-इत्यत्र प्रयुक्तम् :
द्रुतक्रमणस्य मुख्यसङ्केतः अस्ति如何根据基准元素划分数组区间(parttion)
, विघटनविधयः बहवः सन्ति, अत्र एकः एव विधिः प्रदत्तः ।挖坑法
संहिता : १.
class Solution {
public int[] sortArray(int[] nums) {
quick(nums, 0, nums.length - 1);
return nums;
}
private void quick(int[] arr, int start, int end) {
if(start >= end) return;// 递归结束条件
int pivot = parttion(arr, start, end);
// 递归解决子问题
quick(arr, start, pivot - 1);
quick(arr, pivot + 1, end);
}
// 挖坑法进行分解
private int parttion(int[] arr, int left, int right) {
int key = arr[left];
while(left < right) {
while(left < right && arr[right] >= key) right--;
arr[left] = arr[right];
while(left < right && arr[left] <= key) ++left;
arr[right] = arr[left];
}
arr[left] = key;
return left;
}
}
विस्तृत उत्तराणि : १.
1.किमर्थम्start>=end
किं पुनरावृत्तेः अन्त्यस्थितिः ?
उपसमस्यायाः निरन्तरं विघटनं कुर्वन्तु उपसमस्यायाः अन्तिमः आकारः १ भवति, अर्थात् केवलम् एकः एव तत्त्वः अस्ति अस्मिन् समये आरम्भ-अन्त-सूचकाः एकस्मिन् एव तत्त्वे सूचयन्ति कालः।
2. वामस्य स्थाने प्रथमं दक्षिणं किमर्थं गन्तव्यम् ?
प्रथमं कः गच्छति इति अवलम्बते
基准元素的位置
,उपर्युक्ते कोड् मध्ये आधारतत्त्वं (key) वामतमं तत्त्वम् अस्ति यदि प्रथमं चालितम् अस्तिleft
, left प्रथमं आधारतत्त्वात् बृहत्तरं तत्त्वं सम्मुखीभवति, ततः निष्पादयतिarr[right] = arr[left]
,असञ्चितत्वात्arr[right]
, एतत् तत्त्वं नष्टं भविष्यति
यदि भवान् प्रथमं दक्षिणतः गच्छति तर्हि दक्षिणतः प्रथमं आधारतत्त्वात् लघुतरं तत्त्वं सम्मुखीभवति, ततः निष्पादयतिarr[left]=arr[right]
, यतः अस्मिन् समये वामपक्षः न गतः, अद्यापि सः पिवट् अस्ति, परन्तु पिवट् अस्माभिः कीलस्य उपयोगेन रक्षितः अस्ति ।
3.किमर्थं arr[right]>=key?>किं न सम्भवति?
अधिकं वा समं वा मुख्यतया संसाधनार्थम् अस्ति
重复元素问题
यथा - सरणी अस्ति[6,6,6,6,6]
यदि > अस्ति तर्हि दक्षिणसूचकः न गमिष्यति, वामः सूचकः अपि न चलति, अनन्तपाशस्य च अटति ।
4. किमर्थं गर्तखननविधिः इति कथ्यते ?
यदा r सूचकः प्रथमस्य सम्मुखीभवति
arr[r] = arr[l]
, अस्मिन् समये ल स्थितिः शून्या भवति, गर्तं निर्मायते ।
मुख्यतया अनुकूलनदिशौ स्तः : १.
O(N*logN)
, अर्थात् उत्तमकालजटिलता数组分三块
तस्मिन् एव काले यदि भवान् विशेषपरीक्षाप्रकरणानाम् (क्रमिकसरणौ अथवा विपरीतसरणौ) सम्मुखीभवति तर्हि समयजटिलता यावत् अवनतिः भविष्यतिO(N^2)
प्रथमं प्रश्नस्य आधारेण (वर्णेन क्रमयन्तु) किम् इति अवगच्छन्तु数组分三块
विश्लेषणं कुरुत
संहिता : १.
class Solution {
public void sortColors(int[] nums) {
// 分治 --
// 1.定义三指针
int i = 0;// 遍历整个数组
int l = -1, r = nums.length;
while(i < r) {
if(nums[i] == 0) swap(nums,++l,i++);
else if(nums[i] == 1) i++;
else swap(nums,--r,i);
}
return;
}
private void swap(int[] nums,int x,int y) {
int tmp = nums[x]; nums[x] = nums[y]; nums[y] = tmp;
}
}
l,r的起始位置
, प्रथमतत्त्वं अन्तिमतत्त्वं च अन्तर्भवति未处理状态
, अतः `l, r एतौ तत्त्वौ दर्शयितुं न शक्नोति, अन्तरालात् बहिः भवितुमर्हति三个指针去分别维护四个区间
, एकः अन्तरालः अस्ति未处理区间
, यथा यथा cur सूचकः निरन्तरं गच्छति तथा सर्वे अन्तरालाः संसाधिताः भवन्ति, अन्ते च केवलं त्रयः अन्तरालाः सन्ति ।उपर्युक्तविचाराः प्रयोजयन्तु快速排序的parttion中
, अन्तिमफलं त्रिषु अन्तरेषु विभक्तं भवति
संहिता : १.
class Solution {
// 快速排序优化版
// 分解--解决--合并
public int[] sortArray(int[] nums) {
qsort(nums, 0, nums.length - 1);
return nums;
}
private void qsort(int[] nums, int start, int end) {
if(start >= end) return;// 递归结束条件
// 分解
int pivot = nums[start];
int l = start - 1, r = end + 1, i = start;
while(i < r) {
int cur = nums[i];
if(cur < pivot) swap(nums, ++l, i++);
else if(cur == pivot) ++i;
else swap(nums, --r, i);
}
// [start, l] [l+1, r-1] [r, end]
// 递归解决
qsort(nums, start, l);
qsort(nums, r, end);
}
private void swap(int[] nums,int i, int j) {
int tmp = nums[i]; nums[i] = nums[j]; nums[j] = tmp;
}
}
2. आधारमूल्यं यादृच्छिकरूपेण चिनोतु
यादृच्छिकसङ्ख्यानां उपयोगेन आधारमूल्यं यादृच्छिकरूपेण चिनोतु
int pivot = nums[start + new Random().nextInt(end - start + 1)];
// 起始位置 随机产生的偏移量
सम्पूर्णतया उन्नतसङ्केतः : १.
class Solution {
// 快速排序优化版
// 分解--解决--合并
public int[] sortArray(int[] nums) {
qsort(nums, 0, nums.length - 1);
return nums;
}
private void qsort(int[] nums, int start, int end) {
if(start >= end) return;// 递归结束条件
// 分解
int pivot = nums[start + new Random().nextInt(end - start + 1)];
int l = start - 1, r = end + 1, i = start;
while(i < r) {
int cur = nums[i];
if(cur < pivot) swap(nums, ++l, i++);
else if(cur == pivot) ++i;
else swap(nums, --r, i);
}
// [start, l] [l+1, r-1] [r, end]
// 递归解决
qsort(nums, start, l);
qsort(nums, r, end);
}
private void swap(int[] nums,int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
द्रुतचयन-अल्गोरिदम् अस्ति基于快速排序优化版本
एक कालजटिलता केO(N)
चयन-अल्गोरिदम्, उपयोग-परिदृश्यम् अस्ति第K大/前K大
चयनविषयाणि यथा
01.सरणौ Kth बृहत्तमः तत्त्वः
लिङ्कः: https://leetcode.cn/problems/kth-largest-element-in-an-array/
विश्लेषणं कुरुत
sort
क्रमबद्धं कृत्वा ततः Kth बृहत्तमं प्रति प्रत्यागच्छन्तुO(N*logN)
O(logN)
पुनरावृत्तिद्वारा उत्पन्नानि आह्वानं स्तम्भयन्तुतदनन्तरं कार्यान्वयनार्थं द्रुतचयन-अल्गोरिदम् उपयुज्यतेO(N)
कालजटिलता का
संहिता : १.
class Solution {
public int findKthLargest(int[] nums, int k) {
return qsort(nums, 0, nums.length - 1, k);
}
private int qsort(int[] nums, int start, int end, int k) {
if(start >= end) return nums[start];
int pivot = nums[start + new Random().nextInt(end - start + 1)];
// 数组分三块 <pivot ==pivot >pivot
int l = start - 1, r = end + 1, i = start;
while(i < r) {
if(nums[i] < pivot) swap(nums, ++l, i++);
else if(nums[i] == pivot) ++i;
else swap(nums, --r, i);
}
// [start, l] [l+1, r - 1] [r, end]
int c = end - r + 1, b = r - 1 - (l + 1) + 1, a = l - start + 1;
// 分情况讨论 进行选择
if(c >= k) return qsort(nums, r, end, k);
else if(b + c >= k) return pivot;
else return qsort(nums, start, l, k - b - c);// 找较小区间的第(k-b-c)大
}
private void swap(int[] arr, int i, int j) {
int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp;
}
}
O(N)