给一个数组nums=[5,4,8,2],给一个n=5416, 让你从nums中选出一些元素,使得组成的数字是小于n的最大数
思路:贪心+二分查找
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef pair<int,int>PII;
//找小于idex的的最后一个
int searchl(vector<int>nums,int target){
int l=0,r=nums.size()-1;
while(l<r){
int mid=l+r+1>>1;
if(nums[mid]<target)l=mid;
else r=mid-1;
}
if(nums[l]<target)return l;
else return -1;
}
//找小于等于idex的最后一个
int searchle(vector<int>nums,int target){
int l=0,r=nums.size()-1;
while(l<r){
int mid=l+r+1>>1;
if(nums[mid]<=target)l=mid;
else r=mid-1;
}
if(nums[l]<=target)return l;
else return -1;
}
PII dsearchl(int h,vector<int>nums,vector<int>maxn){
if(h<=-1||h>=maxn.size()){
return PII(-1,0);
}
//cout<<"h=="<<h<<endl;
int t=searchl(nums,maxn[h]);
//cout<<"t=="<<t<<endl;
if(t==-1){
return dsearchl(h-1,nums,maxn);
}else{
return PII(h,nums[t]);
}
}
int main(){
vector<int>nums={5,4,8,2};
int n=5416;
//最大位数字各位数,答案
vector<int>maxn,ans;
//对可选数字进行排序
sort(nums.begin(),nums.end());
while(n){
maxn.push_back(n%10);
n/=10;
}
int len=maxn.size();
int h=len-1;
reverse(maxn.begin(),maxn.end());
// for(int i=0;i<len;i++){
// cout<<maxn[i];
// }
//puts("");
//从高位到低位进行遍历
for(int i=0;i<len;i++){
//找小于等于maxn[i]的数字的数位
int idx=searchle(nums,maxn[i]);
//printf("maxi=%d,idx=%d\n",maxn[i],idx);
//记录提供的数字中不等于maxn[i]的首位
if(nums[idx]!=maxn[i]){
h=i;
//cout<<"---------------h=="<<h<<" "<<"s=="<<searchl(nums,maxn[i])<<endl;
break;
}
}
//查看是否能找到比该位更小的位
//int t=searchl(nums,maxn[h]);
//分类讨论:
//1.h==len-1 即没找到/找到位为最后一位
// 1.1 t!=-1 即找到比该位更小的位,则用最小位替换该位,后面其余位为最大值
// 1.2 t==-1 即未找到比该位更小的位,递归查找比前一位更小的位,其余位为最大值,
// 如果递归到第0位且没有比第0位更小的,第0位置0,后面其余位为最大值
//2.h!=len-1
// 2.1 t!=-1 即找到比该位更小的位,则用最小位替换该位,后面其余位为最大值
// 2.2 t==-1 即未找到比该位更小的位,递归查找比前一位更小的位,其余位为最大值,
// 如果递归到第0位且没有比第0位更小的,第0位置0,后面其余位为最大值
//可以把1,2两种情况合一起,即
//t!=-1 即找到比该位更小的位,则用最小位替换该位,后面其余位为最大值
//t==-1 即未找到比该位更小的位,递归查找比前一位更小的位,其余位为最大值,
// 如果递归到第0位且没有比第0位更小的,第0位置0,后面其余位为最大值
PII end=dsearchl(h,nums,maxn);
//找到比该位更小的位的位置
int index=end.first;
//该位值
int value=end.second;
// cout<<"--index--="<<index<<endl;
// cout<<"--value--="<<value<<endl;
if(index==-1){
for(int i=1;i<len;i++){
ans.push_back(nums[len-1]);
}
}else{
for(int i=0;i<index;i++){
ans.push_back(maxn[i]);
}
ans.push_back(value);
for(int i=index+1;i<len;i++){
ans.push_back(nums[len-1]);
}
}
for(int i=0;i<ans.size();i++){
printf("%d\n",ans[i]);
}
return 0;
}