問題描述
給你兩個數組,arr1
和 arr2
,
arr2
中的元素各不相同arr2
中的每個元素都出現在arr1
中
對arr1
中的元素進行排序,使arr1
中項的相對順序和arr2
中的相對順序相同。未在arr2
中出現過的元素需要按照升序放在arr1
的末尾。
示例:
輸入:arr1 = [2,3,1,3,2,4,6,7,9,2,19], arr2 = [2,1,4,3,9,6]
輸出:[2,2,2,1,4,3,3,9,6,7,19]
解題報告
二分搜索
首先將數組 arr1
進行排序
然後依次遍歷數組 arr2
中的元素,在數組 arr1
中找到其所有位置,然後將其換到arr1
的前面。最後返回數組 arr1
即可。
時間複雜度:
空間複雜度:
具體實現上:
- 二分查找一個有序數組中元素出現的第一個位置
int find(vector<int>& nums, int target)
{
int l=0,r=nums.size()-1,mid;
while(l<=r)
{
mid=(l+r)/2;
if (target>nums[mid]) l=mid+1;
else r=mid;
if (r==l) break;
}
return l;
}
接下來搜索該元素共有多少個,首先將這些元素刪除,然後將其插入到 arr1
的前面。這樣處理之後,接下來的元素還是有序的,依然可以二分搜索。
桶排序
注意到這題數組中每個數的取值範圍較小——和數組大小相同,所以用桶排序法非常方便。
首先創建一個大小爲 1001
的桶,遍歷數組 arr1
,每個桶中記錄該桶出現的次數。
然後遍歷數組 arr2
,按照 arr2
數組中的元素順序,將各個桶放到結果數組中,最後將剩餘的桶依次放到結果數組中即可。
時間複雜度:
空間複雜度:
實現代碼
二分搜索實現
class Solution {
public:
vector<int> relativeSortArray(vector<int>& arr1, vector<int>& arr2) {
int tmp = 0,l=0,r=arr1.size(),mid,counter;
sort(arr1.begin(), arr1.end());
for(int i = 0;i<arr2.size();++i){
l=tmp,r=arr1.size()-1,counter=1;
while(l<=r){
mid=(l+r)/2;
if (arr2[i]>arr1[mid]) l=mid+1;
else r=mid;
if (r==l) break;
}
int temp=arr1[l],index=l;
while(true){
if(l<arr1.size()-1&&temp==arr1[l+1]){
counter++;
l++;
}
else break;
}
arr1.erase(arr1.begin()+index,arr1.begin()+index+counter);
arr1.insert(arr1.begin()+tmp, counter, temp);
tmp+=counter;
}
return arr1;
}
};
桶排序實現
class Solution{
public:
vector<int> relativeSortArray(vector<int>& arr1, vector<int>& arr2){
vector<int>bucket(1001,0),ans;
int counter=0;
for(int i=0;i<arr1.size();i++)
bucket[arr1[i]]=bucket[arr1[i]]+1;
for(int i=0;i<arr2.size();i++){
ans.insert(ans.end(), bucket[arr2[i]], arr2[i]);
bucket[arr2[i]]=0;
}
for(int i=0;i<bucket.size();i++){
if(bucket[i]>0) ans.insert(ans.end(), bucket[i], i);
}
return ans;
}
};
補充
二分查找一個有序數組中元素出現的第一個位置
int find(vector<int>& nums, int target)
{
int l=0,r=nums.size()-1,mid;
while(l<=r)
{
mid=(l+r+1)/2;
if (target>=nums[mid]) l=mid;
else r=mid-1;
if (r==l) break;
}
return r;
}